From 84b671f6b27090fc1d77e277a73b52e05aa4d867 Mon Sep 17 00:00:00 2001 From: Guillaume Maudoux Date: Tue, 21 Jan 2020 23:48:16 +0100 Subject: [PATCH] Attempt at supporting locale and timezones (#1) --- include/modules/clock.hpp | 3 ++ man/waybar-clock.5.scd | 8 +++++- src/modules/clock.cpp | 60 +++++++++++++++++++++------------------ 3 files changed, 43 insertions(+), 28 deletions(-) diff --git a/include/modules/clock.hpp b/include/modules/clock.hpp index a10f96a..e54f4d2 100644 --- a/include/modules/clock.hpp +++ b/include/modules/clock.hpp @@ -20,6 +20,9 @@ class Clock : public ALabel { private: util::SleeperThread thread_; + std::locale locale_; + const date::time_zone* time_zone_; + bool fixed_time_zone_; }; } // namespace waybar::modules diff --git a/man/waybar-clock.5.scd b/man/waybar-clock.5.scd index 9f79f88..e3213f3 100644 --- a/man/waybar-clock.5.scd +++ b/man/waybar-clock.5.scd @@ -18,13 +18,19 @@ The *clock* module displays the current date and time. *format*: ++ typeof: string ++ default: {:%H:%M} ++ - The format, how the date and time should be displayed. + The format, how the date and time should be displayed. ++ + It uses the format of the date library. See https://howardhinnant.github.io/date/date.html#to_stream_formatting for details. *timezone*: ++ typeof: string ++ default: inferred local timezone ++ The timezone to display the time in, e.g. America/New_York. +*locale*: ++ + typeof: string ++ + default: inferred from current locale ++ + A locale to be used to display the time. Intended to render times in custom timezones with the proper language and format. + *max-length*: ++ typeof: integer ++ The maximum length in character the module should display. diff --git a/src/modules/clock.cpp b/src/modules/clock.cpp index 1ad29a3..38af115 100644 --- a/src/modules/clock.cpp +++ b/src/modules/clock.cpp @@ -1,7 +1,20 @@ #include "modules/clock.hpp" waybar::modules::Clock::Clock(const std::string& id, const Json::Value& config) - : ALabel(config, "clock", id, "{:%H:%M}", 60) { + : ALabel(config, "clock", id, "{:%H:%M}", 60) + , fixed_time_zone_(false) +{ + if (config_["timezone"].isString()) { + time_zone_ = date::locate_zone(config_["timezone"].asString()); + fixed_time_zone_ = true; + } + + if (config_["locale"].isString()) { + locale_ = std::locale(config_["locale"].asString()); + } else { + locale_ = std::locale(""); + } + thread_ = [this] { dp.emit(); auto now = std::chrono::system_clock::now(); @@ -11,23 +24,28 @@ waybar::modules::Clock::Clock(const std::string& id, const Json::Value& config) }; } +using zoned_time = date::zoned_time; + +struct waybar_time { + std::locale locale; + zoned_time ztime; +}; + auto waybar::modules::Clock::update() -> void { - tzset(); // Update timezone information - const date::time_zone* zone; - auto now = std::chrono::floor(std::chrono::system_clock::now()); - if (config_["timezone"].isString()) { - zone = date::locate_zone(config_["timezone"].asString()); - } else { - zone = date::current_zone(); + if (!fixed_time_zone_) { + // Time zone can change. Be sure to pick that. + time_zone_ = date::current_zone(); } - auto localtime = date::make_zoned(zone, now); - auto text = fmt::format(format_, localtime); + auto now = std::chrono::system_clock::now(); + waybar_time wtime = {locale_, date::make_zoned(time_zone_, now)}; + + auto text = fmt::format(format_, wtime); label_.set_markup(text); if (tooltipEnabled()) { if (config_["tooltip-format"].isString()) { auto tooltip_format = config_["tooltip-format"].asString(); - auto tooltip_text = fmt::format(tooltip_format, localtime); + auto tooltip_text = fmt::format(tooltip_format, wtime); label_.set_tooltip_text(tooltip_text); } else { label_.set_tooltip_text(text); @@ -35,22 +53,10 @@ auto waybar::modules::Clock::update() -> void { } } -template -struct fmt::formatter> { - - std::string *format_string; - - constexpr auto parse(format_parse_context& ctx) { - format_string = new std::string[1]; - auto it = ctx.begin(), end = ctx.end(); - while (it != (end - 1)) { - *format_string += *it++; - } - return it; - } - +template <> +struct fmt::formatter : fmt::formatter { template - auto format(const date::zoned_time& d, FormatContext& ctx) { - return format_to(ctx.out(), "{}", date::format(std::locale(""), *format_string, d)); + auto format(const waybar_time& t, FormatContext& ctx) { + return format_to(ctx.out(), "{}", date::format(t.locale, fmt::to_string(tm_format), t.ztime)); } };