mirror of
				https://github.com/rad4day/Waybar.git
				synced 2025-11-04 01:32:42 +01:00 
			
		
		
		
	refactor(clock): remove struct waybar_time
The structure was used to pass the locale instance to the date formatter. All the supported versions of `fmt` are passing the locale parameter via `FormatContext.locale()` so we can remove the struct and simplify the code. While we at it, drop `date::make_zoned` in favor of CTAD on a `date::zoned_time` constructor.
This commit is contained in:
		@@ -5,11 +5,7 @@
 | 
				
			|||||||
#include "ALabel.hpp"
 | 
					#include "ALabel.hpp"
 | 
				
			||||||
#include "util/sleeper_thread.hpp"
 | 
					#include "util/sleeper_thread.hpp"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
namespace waybar {
 | 
					namespace waybar::modules {
 | 
				
			||||||
 | 
					 | 
				
			||||||
struct waybar_time;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
namespace modules {
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
const std::string kCalendarPlaceholder = "calendar";
 | 
					const std::string kCalendarPlaceholder = "calendar";
 | 
				
			||||||
const std::string KTimezonedTimeListPlaceholder = "timezoned_time_list";
 | 
					const std::string KTimezonedTimeListPlaceholder = "timezoned_time_list";
 | 
				
			||||||
@@ -36,12 +32,11 @@ class Clock : public ALabel {
 | 
				
			|||||||
  std::string fmt_str_weeks_;
 | 
					  std::string fmt_str_weeks_;
 | 
				
			||||||
  std::string fmt_str_calendar_;
 | 
					  std::string fmt_str_calendar_;
 | 
				
			||||||
  int fmt_weeks_left_pad_{0};
 | 
					  int fmt_weeks_left_pad_{0};
 | 
				
			||||||
  auto calendar_text(const waybar_time& wtime) -> std::string;
 | 
					  auto calendar_text(const date::zoned_seconds& ztime) -> std::string;
 | 
				
			||||||
  auto weekdays_header(const date::weekday& first_dow, std::ostream& os) -> void;
 | 
					  auto weekdays_header(const date::weekday& first_dow, std::ostream& os) -> void;
 | 
				
			||||||
  auto first_day_of_week() -> date::weekday;
 | 
					  auto first_day_of_week() -> date::weekday;
 | 
				
			||||||
  const date::time_zone* current_timezone();
 | 
					  const date::time_zone* current_timezone();
 | 
				
			||||||
  bool is_timezone_fixed();
 | 
					  bool is_timezone_fixed();
 | 
				
			||||||
  auto timezones_text(std::chrono::system_clock::time_point* now) -> std::string;
 | 
					  auto timezones_text(std::chrono::system_clock::time_point* now) -> std::string;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
}  // namespace modules
 | 
					}  // namespace waybar::modules
 | 
				
			||||||
}  // namespace waybar
 | 
					 | 
				
			||||||
 
 | 
				
			|||||||
@@ -3,17 +3,8 @@
 | 
				
			|||||||
#include <date/tz.h>
 | 
					#include <date/tz.h>
 | 
				
			||||||
#include <fmt/format.h>
 | 
					#include <fmt/format.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
namespace waybar {
 | 
					template <typename Duration, typename TimeZonePtr>
 | 
				
			||||||
 | 
					struct fmt::formatter<date::zoned_time<Duration, TimeZonePtr>> {
 | 
				
			||||||
struct waybar_time {
 | 
					 | 
				
			||||||
  std::locale locale;
 | 
					 | 
				
			||||||
  date::zoned_seconds ztime;
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
}  // namespace waybar
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
template <>
 | 
					 | 
				
			||||||
struct fmt::formatter<waybar::waybar_time> {
 | 
					 | 
				
			||||||
  std::string_view specs;
 | 
					  std::string_view specs;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  template <typename ParseContext>
 | 
					  template <typename ParseContext>
 | 
				
			||||||
@@ -33,7 +24,11 @@ struct fmt::formatter<waybar::waybar_time> {
 | 
				
			|||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  template <typename FormatContext>
 | 
					  template <typename FormatContext>
 | 
				
			||||||
  auto format(const waybar::waybar_time& t, FormatContext& ctx) {
 | 
					  auto format(const date::zoned_time<Duration, TimeZonePtr>& ztime, FormatContext& ctx) {
 | 
				
			||||||
    return format_to(ctx.out(), "{}", date::format(t.locale, fmt::to_string(specs), t.ztime));
 | 
					    if (ctx.locale()) {
 | 
				
			||||||
 | 
					      const auto loc = ctx.locale().template get<std::locale>();
 | 
				
			||||||
 | 
					      return fmt::format_to(ctx.out(), "{}", date::format(loc, fmt::to_string(specs), ztime));
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    return fmt::format_to(ctx.out(), "{}", date::format(fmt::to_string(specs), ztime));
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
@@ -9,15 +9,13 @@
 | 
				
			|||||||
#include <sstream>
 | 
					#include <sstream>
 | 
				
			||||||
#include <type_traits>
 | 
					#include <type_traits>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "util/date.hpp"
 | 
				
			||||||
#include "util/ustring_clen.hpp"
 | 
					#include "util/ustring_clen.hpp"
 | 
				
			||||||
#include "util/waybar_time.hpp"
 | 
					 | 
				
			||||||
#ifdef HAVE_LANGINFO_1STDAY
 | 
					#ifdef HAVE_LANGINFO_1STDAY
 | 
				
			||||||
#include <langinfo.h>
 | 
					#include <langinfo.h>
 | 
				
			||||||
#include <locale.h>
 | 
					#include <locale.h>
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
using waybar::waybar_time;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
waybar::modules::Clock::Clock(const std::string& id, const Json::Value& config)
 | 
					waybar::modules::Clock::Clock(const std::string& id, const Json::Value& config)
 | 
				
			||||||
    : ALabel(config, "clock", id, "{:%H:%M}", 60, false, false, true),
 | 
					    : ALabel(config, "clock", id, "{:%H:%M}", 60, false, false, true),
 | 
				
			||||||
      current_time_zone_idx_(0),
 | 
					      current_time_zone_idx_(0),
 | 
				
			||||||
@@ -110,15 +108,13 @@ bool waybar::modules::Clock::is_timezone_fixed() {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
auto waybar::modules::Clock::update() -> void {
 | 
					auto waybar::modules::Clock::update() -> void {
 | 
				
			||||||
  auto time_zone = current_timezone();
 | 
					  const auto* time_zone = current_timezone();
 | 
				
			||||||
  auto now = std::chrono::system_clock::now();
 | 
					  auto now = std::chrono::system_clock::now();
 | 
				
			||||||
  waybar_time wtime = {locale_,
 | 
					  auto ztime = date::zoned_time{time_zone, date::floor<std::chrono::seconds>(now)};
 | 
				
			||||||
                       date::make_zoned(time_zone, date::floor<std::chrono::seconds>(now))};
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
  auto shifted_date = date::year_month_day{date::floor<date::days>(now)} + calendar_shift_;
 | 
					  auto shifted_date = date::year_month_day{date::floor<date::days>(now)} + calendar_shift_;
 | 
				
			||||||
  auto now_shifted = date::sys_days{shifted_date} + (now - date::floor<date::days>(now));
 | 
					  auto now_shifted = date::sys_days{shifted_date} + (now - date::floor<date::days>(now));
 | 
				
			||||||
  waybar_time shifted_wtime = {
 | 
					  auto shifted_ztime = date::zoned_time{time_zone, date::floor<std::chrono::seconds>(now_shifted)};
 | 
				
			||||||
      locale_, date::make_zoned(time_zone, date::floor<std::chrono::seconds>(now_shifted))};
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
  std::string text = "";
 | 
					  std::string text = "";
 | 
				
			||||||
  if (!is_timezone_fixed()) {
 | 
					  if (!is_timezone_fixed()) {
 | 
				
			||||||
@@ -127,7 +123,7 @@ auto waybar::modules::Clock::update() -> void {
 | 
				
			|||||||
    auto localtime = fmt::localtime(std::chrono::system_clock::to_time_t(now));
 | 
					    auto localtime = fmt::localtime(std::chrono::system_clock::to_time_t(now));
 | 
				
			||||||
    text = fmt::format(locale_, format_, localtime);
 | 
					    text = fmt::format(locale_, format_, localtime);
 | 
				
			||||||
  } else {
 | 
					  } else {
 | 
				
			||||||
    text = fmt::format(format_, wtime);
 | 
					    text = fmt::format(locale_, format_, ztime);
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
  label_.set_markup(text);
 | 
					  label_.set_markup(text);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -136,13 +132,13 @@ auto waybar::modules::Clock::update() -> void {
 | 
				
			|||||||
      std::string calendar_lines{""};
 | 
					      std::string calendar_lines{""};
 | 
				
			||||||
      std::string timezoned_time_lines{""};
 | 
					      std::string timezoned_time_lines{""};
 | 
				
			||||||
      if (is_calendar_in_tooltip_) {
 | 
					      if (is_calendar_in_tooltip_) {
 | 
				
			||||||
        calendar_lines = calendar_text(shifted_wtime);
 | 
					        calendar_lines = calendar_text(shifted_ztime);
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
      if (is_timezoned_list_in_tooltip_) {
 | 
					      if (is_timezoned_list_in_tooltip_) {
 | 
				
			||||||
        timezoned_time_lines = timezones_text(&now);
 | 
					        timezoned_time_lines = timezones_text(&now);
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
      auto tooltip_format = config_["tooltip-format"].asString();
 | 
					      auto tooltip_format = config_["tooltip-format"].asString();
 | 
				
			||||||
      text = fmt::format(tooltip_format, shifted_wtime,
 | 
					      text = fmt::format(locale_, tooltip_format, shifted_ztime,
 | 
				
			||||||
                         fmt::arg(kCalendarPlaceholder.c_str(), calendar_lines),
 | 
					                         fmt::arg(kCalendarPlaceholder.c_str(), calendar_lines),
 | 
				
			||||||
                         fmt::arg(KTimezonedTimeListPlaceholder.c_str(), timezoned_time_lines));
 | 
					                         fmt::arg(KTimezonedTimeListPlaceholder.c_str(), timezoned_time_lines));
 | 
				
			||||||
      label_.set_tooltip_markup(text);
 | 
					      label_.set_tooltip_markup(text);
 | 
				
			||||||
@@ -190,8 +186,8 @@ bool waybar::modules::Clock::handleScroll(GdkEventScroll* e) {
 | 
				
			|||||||
  return true;
 | 
					  return true;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
auto waybar::modules::Clock::calendar_text(const waybar_time& wtime) -> std::string {
 | 
					auto waybar::modules::Clock::calendar_text(const date::zoned_seconds& ztime) -> std::string {
 | 
				
			||||||
  const auto daypoint = date::floor<date::days>(wtime.ztime.get_local_time());
 | 
					  const auto daypoint = date::floor<date::days>(ztime.get_local_time());
 | 
				
			||||||
  const auto ymd{date::year_month_day{daypoint}};
 | 
					  const auto ymd{date::year_month_day{daypoint}};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  if (calendar_cached_ymd_ == ymd) {
 | 
					  if (calendar_cached_ymd_ == ymd) {
 | 
				
			||||||
@@ -318,7 +314,6 @@ auto waybar::modules::Clock::timezones_text(std::chrono::system_clock::time_poin
 | 
				
			|||||||
    return "";
 | 
					    return "";
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
  std::stringstream os;
 | 
					  std::stringstream os;
 | 
				
			||||||
  waybar_time wtime;
 | 
					 | 
				
			||||||
  for (size_t time_zone_idx = 0; time_zone_idx < time_zones_.size(); ++time_zone_idx) {
 | 
					  for (size_t time_zone_idx = 0; time_zone_idx < time_zones_.size(); ++time_zone_idx) {
 | 
				
			||||||
    if (static_cast<int>(time_zone_idx) == current_time_zone_idx_) {
 | 
					    if (static_cast<int>(time_zone_idx) == current_time_zone_idx_) {
 | 
				
			||||||
      continue;
 | 
					      continue;
 | 
				
			||||||
@@ -327,8 +322,8 @@ auto waybar::modules::Clock::timezones_text(std::chrono::system_clock::time_poin
 | 
				
			|||||||
    if (!timezone) {
 | 
					    if (!timezone) {
 | 
				
			||||||
      timezone = date::current_zone();
 | 
					      timezone = date::current_zone();
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    wtime = {locale_, date::make_zoned(timezone, date::floor<std::chrono::seconds>(*now))};
 | 
					    auto ztime = date::zoned_time{timezone, date::floor<std::chrono::seconds>(*now)};
 | 
				
			||||||
    os << fmt::format(format_, wtime) << '\n';
 | 
					    os << fmt::format(locale_, format_, ztime) << '\n';
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
  return os.str();
 | 
					  return os.str();
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										94
									
								
								test/date.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										94
									
								
								test/date.cpp
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,94 @@
 | 
				
			|||||||
 | 
					#include "util/date.hpp"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#if __has_include(<catch2/catch_test_macros.hpp>)
 | 
				
			||||||
 | 
					#include <catch2/catch_test_macros.hpp>
 | 
				
			||||||
 | 
					#include <catch2/matchers/catch_matchers_all.hpp>
 | 
				
			||||||
 | 
					#else
 | 
				
			||||||
 | 
					#include <catch2/catch.hpp>
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					#include <chrono>
 | 
				
			||||||
 | 
					#include <stdexcept>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					using namespace std::literals::chrono_literals;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * Check that the date/time formatter with locale and timezone support is working as expected.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const date::zoned_time<std::chrono::seconds> TEST_TIME = date::zoned_time{
 | 
				
			||||||
 | 
					    "UTC", date::local_days{date::Monday[1] / date::January / 2022} + 13h + 4min + 5s};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					TEST_CASE("Format UTC time", "[clock][util]") {
 | 
				
			||||||
 | 
					  const auto loc = std::locale("C");
 | 
				
			||||||
 | 
					  const auto tm = TEST_TIME;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  REQUIRE(fmt::format(loc, "{}", tm).empty());  // no format specified
 | 
				
			||||||
 | 
					  REQUIRE(fmt::format(loc, "{:%c %Z}", tm) == "Mon Jan  3 13:04:05 2022 UTC");
 | 
				
			||||||
 | 
					  REQUIRE(fmt::format(loc, "{arg:%Y%m%d%H%M%S}", fmt::arg("arg", tm)) == "20220103130405");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  /* Test a few locales that are most likely to be present */
 | 
				
			||||||
 | 
					  SECTION("US locale") {
 | 
				
			||||||
 | 
					    try {
 | 
				
			||||||
 | 
					      const auto loc = std::locale("en_US");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      REQUIRE(fmt::format(loc, "{}", tm).empty());  // no format specified
 | 
				
			||||||
 | 
					      REQUIRE_THAT(fmt::format(loc, "{:%c}", tm),   // HowardHinnant/date#704
 | 
				
			||||||
 | 
					                   Catch::Matchers::StartsWith("Mon 03 Jan 2022 01:04:05 PM"));
 | 
				
			||||||
 | 
					      REQUIRE(fmt::format(loc, "{:%x %X}", tm) == "01/03/2022 01:04:05 PM");
 | 
				
			||||||
 | 
					      REQUIRE(fmt::format(loc, "{arg:%Y%m%d%H%M%S}", fmt::arg("arg", tm)) == "20220103130405");
 | 
				
			||||||
 | 
					    } catch (const std::runtime_error&) {
 | 
				
			||||||
 | 
					      // locale not found; ignore
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  SECTION("GB locale") {
 | 
				
			||||||
 | 
					    try {
 | 
				
			||||||
 | 
					      const auto loc = std::locale("en_GB");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      REQUIRE(fmt::format(loc, "{}", tm).empty());  // no format specified
 | 
				
			||||||
 | 
					      REQUIRE_THAT(fmt::format(loc, "{:%c}", tm),   // HowardHinnant/date#704
 | 
				
			||||||
 | 
					                   Catch::Matchers::StartsWith("Mon 03 Jan 2022 13:04:05"));
 | 
				
			||||||
 | 
					      REQUIRE(fmt::format(loc, "{:%x %X}", tm) == "03/01/22 13:04:05");
 | 
				
			||||||
 | 
					      REQUIRE(fmt::format(loc, "{arg:%Y%m%d%H%M%S}", fmt::arg("arg", tm)) == "20220103130405");
 | 
				
			||||||
 | 
					    } catch (const std::runtime_error&) {
 | 
				
			||||||
 | 
					      // locale not found; ignore
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					TEST_CASE("Format zoned time", "[clock][util]") {
 | 
				
			||||||
 | 
					  const auto loc = std::locale("C");
 | 
				
			||||||
 | 
					  const auto tm = date::zoned_time{"America/New_York", TEST_TIME};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  REQUIRE(fmt::format(loc, "{}", tm).empty());  // no format specified
 | 
				
			||||||
 | 
					  REQUIRE(fmt::format(loc, "{:%c %Z}", tm) == "Mon Jan  3 08:04:05 2022 EST");
 | 
				
			||||||
 | 
					  REQUIRE(fmt::format(loc, "{arg:%Y%m%d%H%M%S}", fmt::arg("arg", tm)) == "20220103080405");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  /* Test a few locales that are most likely to be present */
 | 
				
			||||||
 | 
					  SECTION("US locale") {
 | 
				
			||||||
 | 
					    try {
 | 
				
			||||||
 | 
					      const auto loc = std::locale("en_US");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      REQUIRE(fmt::format(loc, "{}", tm).empty());  // no format specified
 | 
				
			||||||
 | 
					      REQUIRE_THAT(fmt::format(loc, "{:%c}", tm),   // HowardHinnant/date#704
 | 
				
			||||||
 | 
					                   Catch::Matchers::StartsWith("Mon 03 Jan 2022 08:04:05 AM"));
 | 
				
			||||||
 | 
					      REQUIRE(fmt::format(loc, "{:%x %X}", tm) == "01/03/2022 08:04:05 AM");
 | 
				
			||||||
 | 
					      REQUIRE(fmt::format(loc, "{arg:%Y%m%d%H%M%S}", fmt::arg("arg", tm)) == "20220103080405");
 | 
				
			||||||
 | 
					    } catch (const std::runtime_error&) {
 | 
				
			||||||
 | 
					      // locale not found; ignore
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  SECTION("GB locale") {
 | 
				
			||||||
 | 
					    try {
 | 
				
			||||||
 | 
					      const auto loc = std::locale("en_GB");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      REQUIRE(fmt::format(loc, "{}", tm).empty());  // no format specified
 | 
				
			||||||
 | 
					      REQUIRE_THAT(fmt::format(loc, "{:%c}", tm),   // HowardHinnant/date#704
 | 
				
			||||||
 | 
					                   Catch::Matchers::StartsWith("Mon 03 Jan 2022 08:04:05"));
 | 
				
			||||||
 | 
					      REQUIRE(fmt::format(loc, "{:%x %X}", tm) == "03/01/22 08:04:05");
 | 
				
			||||||
 | 
					      REQUIRE(fmt::format(loc, "{arg:%Y%m%d%H%M%S}", fmt::arg("arg", tm)) == "20220103080405");
 | 
				
			||||||
 | 
					    } catch (const std::runtime_error&) {
 | 
				
			||||||
 | 
					      // locale not found; ignore
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -15,7 +15,7 @@ test_src = files(
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
if tz_dep.found()
 | 
					if tz_dep.found()
 | 
				
			||||||
  test_dep += tz_dep
 | 
					  test_dep += tz_dep
 | 
				
			||||||
  test_src += files('waybar_time.cpp')
 | 
					  test_src += files('date.cpp')
 | 
				
			||||||
endif
 | 
					endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
waybar_test = executable(
 | 
					waybar_test = executable(
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,95 +0,0 @@
 | 
				
			|||||||
#include "util/waybar_time.hpp"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#include <date/date.h>
 | 
					 | 
				
			||||||
#include <date/tz.h>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#if __has_include(<catch2/catch_test_macros.hpp>)
 | 
					 | 
				
			||||||
#include <catch2/catch_test_macros.hpp>
 | 
					 | 
				
			||||||
#include <catch2/matchers/catch_matchers_all.hpp>
 | 
					 | 
				
			||||||
#else
 | 
					 | 
				
			||||||
#include <catch2/catch.hpp>
 | 
					 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
#include <chrono>
 | 
					 | 
				
			||||||
#include <stdexcept>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
using namespace std::literals::chrono_literals;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/*
 | 
					 | 
				
			||||||
 * Check that the date/time formatter with locale and timezone support is working as expected.
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
const date::zoned_time<std::chrono::seconds> TEST_TIME = date::make_zoned(
 | 
					 | 
				
			||||||
    "UTC", date::local_days{date::Monday[1] / date::January / 2022} + 13h + 4min + 5s);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
TEST_CASE("Format UTC time", "[clock][util]") {
 | 
					 | 
				
			||||||
  waybar::waybar_time tm{std::locale("C"), TEST_TIME};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  REQUIRE(fmt::format("{}", tm).empty());  // no format specified
 | 
					 | 
				
			||||||
  REQUIRE(fmt::format("{:%c %Z}", tm) == "Mon Jan  3 13:04:05 2022 UTC");
 | 
					 | 
				
			||||||
  REQUIRE(fmt::format("{arg:%Y%m%d%H%M%S}", fmt::arg("arg", tm)) == "20220103130405");
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  /* Test a few locales that are most likely to be present */
 | 
					 | 
				
			||||||
  SECTION("US locale") {
 | 
					 | 
				
			||||||
    try {
 | 
					 | 
				
			||||||
      tm.locale = std::locale("en_US");
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
      REQUIRE(fmt::format("{}", tm).empty());  // no format specified
 | 
					 | 
				
			||||||
      REQUIRE_THAT(fmt::format("{:%c}", tm),   // HowardHinnant/date#704
 | 
					 | 
				
			||||||
                   Catch::Matchers::StartsWith("Mon 03 Jan 2022 01:04:05 PM"));
 | 
					 | 
				
			||||||
      REQUIRE(fmt::format("{:%x %X}", tm) == "01/03/2022 01:04:05 PM");
 | 
					 | 
				
			||||||
      REQUIRE(fmt::format("{arg:%Y%m%d%H%M%S}", fmt::arg("arg", tm)) == "20220103130405");
 | 
					 | 
				
			||||||
    } catch (const std::runtime_error&) {
 | 
					 | 
				
			||||||
      // locale not found; ignore
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
  SECTION("GB locale") {
 | 
					 | 
				
			||||||
    try {
 | 
					 | 
				
			||||||
      tm.locale = std::locale("en_GB");
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
      REQUIRE(fmt::format("{}", tm).empty());  // no format specified
 | 
					 | 
				
			||||||
      REQUIRE_THAT(fmt::format("{:%c}", tm),   // HowardHinnant/date#704
 | 
					 | 
				
			||||||
                   Catch::Matchers::StartsWith("Mon 03 Jan 2022 13:04:05"));
 | 
					 | 
				
			||||||
      REQUIRE(fmt::format("{:%x %X}", tm) == "03/01/22 13:04:05");
 | 
					 | 
				
			||||||
      REQUIRE(fmt::format("{arg:%Y%m%d%H%M%S}", fmt::arg("arg", tm)) == "20220103130405");
 | 
					 | 
				
			||||||
    } catch (const std::runtime_error&) {
 | 
					 | 
				
			||||||
      // locale not found; ignore
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
TEST_CASE("Format zoned time", "[clock][util]") {
 | 
					 | 
				
			||||||
  waybar::waybar_time tm{std::locale("C"), date::make_zoned("America/New_York", TEST_TIME)};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  REQUIRE(fmt::format("{}", tm).empty());  // no format specified
 | 
					 | 
				
			||||||
  REQUIRE(fmt::format("{:%c %Z}", tm) == "Mon Jan  3 08:04:05 2022 EST");
 | 
					 | 
				
			||||||
  REQUIRE(fmt::format("{arg:%Y%m%d%H%M%S}", fmt::arg("arg", tm)) == "20220103080405");
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  /* Test a few locales that are most likely to be present */
 | 
					 | 
				
			||||||
  SECTION("US locale") {
 | 
					 | 
				
			||||||
    try {
 | 
					 | 
				
			||||||
      tm.locale = std::locale("en_US");
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
      REQUIRE(fmt::format("{}", tm).empty());  // no format specified
 | 
					 | 
				
			||||||
      REQUIRE_THAT(fmt::format("{:%c}", tm),   // HowardHinnant/date#704
 | 
					 | 
				
			||||||
                   Catch::Matchers::StartsWith("Mon 03 Jan 2022 08:04:05 AM"));
 | 
					 | 
				
			||||||
      REQUIRE(fmt::format("{:%x %X}", tm) == "01/03/2022 08:04:05 AM");
 | 
					 | 
				
			||||||
      REQUIRE(fmt::format("{arg:%Y%m%d%H%M%S}", fmt::arg("arg", tm)) == "20220103080405");
 | 
					 | 
				
			||||||
    } catch (const std::runtime_error&) {
 | 
					 | 
				
			||||||
      // locale not found; ignore
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  SECTION("GB locale") {
 | 
					 | 
				
			||||||
    try {
 | 
					 | 
				
			||||||
      tm.locale = std::locale("en_GB");
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
      REQUIRE(fmt::format("{}", tm).empty());  // no format specified
 | 
					 | 
				
			||||||
      REQUIRE_THAT(fmt::format("{:%c}", tm),   // HowardHinnant/date#704
 | 
					 | 
				
			||||||
                   Catch::Matchers::StartsWith("Mon 03 Jan 2022 08:04:05"));
 | 
					 | 
				
			||||||
      REQUIRE(fmt::format("{:%x %X}", tm) == "03/01/22 08:04:05");
 | 
					 | 
				
			||||||
      REQUIRE(fmt::format("{arg:%Y%m%d%H%M%S}", fmt::arg("arg", tm)) == "20220103080405");
 | 
					 | 
				
			||||||
    } catch (const std::runtime_error&) {
 | 
					 | 
				
			||||||
      // locale not found; ignore
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
		Reference in New Issue
	
	Block a user