diff --git a/include/modules/clock.hpp b/include/modules/clock.hpp index 5fd9df54..aef3f52c 100644 --- a/include/modules/clock.hpp +++ b/include/modules/clock.hpp @@ -12,6 +12,7 @@ const std::string kOrdPlaceholder{"ordinal_date"}; enum class CldMode { MONTH, YEAR }; enum class WS { LEFT, RIGHT, HIDDEN }; +enum class WeekNumbering { LOCALE, ISO, MONDAY, SUNDAY }; class Clock final : public ALabel { public: @@ -51,6 +52,7 @@ class Clock final : public ALabel { date::day cldBaseDay_{0}; // calendar Cached day. Is used when today is changing(midnight) std::string cldText_{""}; // calendar text to print bool iso8601Calendar_{false}; // whether the calendar is in ISO8601 + WeekNumbering weekNumbering_{WeekNumbering::LOCALE}; // week number calculation method CldMode cldMode_{CldMode::MONTH}; auto get_calendar(const date::year_month_day& today, const date::year_month_day& ymd, const date::time_zone* tz) -> const std::string; diff --git a/man/waybar-clock.5.scd b/man/waybar-clock.5.scd index 263469f0..62d1394d 100644 --- a/man/waybar-clock.5.scd +++ b/man/waybar-clock.5.scd @@ -138,6 +138,13 @@ View all valid format options in *strftime(3)* or have a look https://en.cpprefe :[ When enabled, the calendar follows the ISO 8601 standard: weeks begin on Monday, and the first week of the year is numbered 1. The default week format is '{:%V}'. +|[ *weeks-numbering* +:[ string +:[ +:[ Override the week number calculation method, independent of *iso8601* and + locale settings. Possible values: *iso* (ISO 8601, {:%V}), *monday* + (Monday-based, {:%W}), *sunday* (Sunday-based, {:%U}). When not set, the + method is derived from *iso8601* or the locale. |[ *first-day-of-week* :[ integer :[ @@ -160,8 +167,9 @@ View all valid format options in *strftime(3)* or have a look https://en.cpprefe |[ *weeks* :[ string :[ *{:%U}* -:[ Format is applied to week numbers. When weekday format is not provided then - is used default format: '{:%W}' when week starts with Monday, '{:%U}' otherwise +:[ Format is applied to week numbers. The *{}* placeholder is replaced with the + format determined by *weeks-numbering* (if set), otherwise by *iso8601* or the + locale: '{:%V}' for ISO 8601, '{:%W}' when week starts with Monday, '{:%U}' otherwise |[ *weekdays* :[ string :[ diff --git a/src/modules/clock.cpp b/src/modules/clock.cpp index 5720a2b2..89ae5eba 100644 --- a/src/modules/clock.cpp +++ b/src/modules/clock.cpp @@ -82,6 +82,20 @@ waybar::modules::Clock::Clock(const std::string& id, const Json::Value& config) iso8601Calendar_ = config_[kCldPlaceholder]["iso8601"].asBool(); } + if (config_[kCldPlaceholder]["weeks-numbering"].isString()) { + const std::string wn{config_[kCldPlaceholder]["weeks-numbering"].asString()}; + const std::map wnModes{{"iso", WeekNumbering::ISO}, + {"monday", WeekNumbering::MONDAY}, + {"sunday", WeekNumbering::SUNDAY}}; + if (wnModes.find(wn) != wnModes.end()) + weekNumbering_ = wnModes.at(wn); + else + spdlog::warn( + "Clock calendar configuration weeks-numbering \"{}\" is not recognized. " + "Locale default is used instead", + wn); + } + if (config_[kCldPlaceholder]["weeks-pos"].isString()) { if (config_[kCldPlaceholder]["weeks-pos"].asString() == "left") cldWPos_ = WS::LEFT; if (config_[kCldPlaceholder]["weeks-pos"].asString() == "right") cldWPos_ = WS::RIGHT; @@ -105,18 +119,26 @@ waybar::modules::Clock::Clock(const std::string& id, const Json::Value& config) cldBaseDay_ = year_month_day{floor(local_time)}.day(); } else fmtMap_.insert({3, "{}"}); + const auto weekFmt = [this]() -> std::string { + switch (weekNumbering_) { + case WeekNumbering::ISO: + return "{:%V}"; + case WeekNumbering::MONDAY: + return "{:%W}"; + case WeekNumbering::SUNDAY: + return "{:%U}"; + default: + return iso8601Calendar_ ? "{:%V}" : ((first_day_of_week() == Monday) ? "{:%W}" : "{:%U}"); + } + }(); if (config_[kCldPlaceholder]["format"]["weeks"].isString() && cldWPos_ != WS::HIDDEN) { - const auto defaultFmt = - iso8601Calendar_ ? "{:%V}" : ((first_day_of_week() == Monday) ? "{:%W}" : "{:%U}"); fmtMap_.insert({4, std::regex_replace(config_[kCldPlaceholder]["format"]["weeks"].asString(), - std::regex("\\{\\}"), defaultFmt)}); + std::regex("\\{\\}"), weekFmt)}); Glib::ustring tmp{std::regex_replace(fmtMap_[4], std::regex("]+>|\\{.*\\}"), "")}; cldWnLen_ += tmp.size(); } else { if (cldWPos_ != WS::HIDDEN) { - const auto defaultFmt = - iso8601Calendar_ ? "{:%V}" : ((first_day_of_week() == Monday) ? "{:%W}" : "{:%U}"); - fmtMap_.insert({4, defaultFmt}); + fmtMap_.insert({4, weekFmt}); } else { cldWnLen_ = 0; }