Waybar icon indicating copy to clipboard operation
Waybar copied to clipboard

Calendar Week numbers display incorrectly

Open Noino opened this issue 6 months ago • 2 comments
trafficstars

Using en_DK locale, which should count the first week with four days as week no 1, displays as week 0

"clock": {
	"interval": 1,
    "locale": "en_DK.UTF-8",
    "format": " {:%H:%M:%S}",
	"format-alt": " {:%H:%M  %d.%m.%Y %A}",
	"tooltip-format": "<tt><small>{calendar}</small></tt>",
	"calendar": {
		"mode": "year",
		"mode-mon-col": 3,
		"weeks-pos": "left",
		"on-scroll": 1,
		"format": {
			"months": "<span color='#ffead3'><b>{}</b></span>",
			"days": "<span color='#ecc6d9'><b>{}</b></span>",
			"weeks": "<span color='#99ffdd'><b>W{}</b></span>",
			"weekdays": "<span color='#ffcc66'><b>{}</b></span>",
			"today": "<span color='#ff6699'><b><u>{}</u></b></span>"
		},
	}
},

Image

Noino avatar May 12 '25 21:05 Noino

That's ISO weeks, which is AFAIK the most common week numbering system: https://en.wikipedia.org/wiki/ISO_week_date

I checked the code and apparently it's hardcoded to consider the first week fully on a year as week 01 (which also depends on whether your week starts on a Sunday or a Monday).

I also want ISO week numbers, which would be %V instead of %U or %W

Code in question: https://github.com/Alexays/Waybar/blob/0332d2ebf84392c82c86d615079f762f27de94ba/src/modules/clock.cpp#L106C1-L106C82

Definition: https://eel.is/c++draft/tab:time.format.spec#row-31 or https://en.cppreference.com/w/cpp/chrono/year_month_day/formatter

pheki avatar May 20 '25 01:05 pheki

gpt tells me this is problem that can be solved 🤪

You're using glibc-specific extensions via <langinfo.h> and NL_TIME* macros, which are non-standard but powerful tools available on Linux systems with glibc. This is part of the locale extension support in glibc, and you're already on the right track for platform-aware, locale-correct behavior.

You can detect when to use %V (ISO 8601 week numbering) by using the values from:

  • _NL_TIME_FIRST_WEEKDAY → tells you if week starts on Monday (ISO requirement)

  • _NL_TIME_WEEK_1STDAY → gives you the anchor date for week 1 (should be the first Thursday of the year or contain Jan 4 for ISO 8601)


📘 Background: What %V, %W, %U Mean

Format Week starts Week 1 starts if... Common in
%U Sunday Jan 1 falls in week US (en_US)
%W Monday Jan 1 falls in week US alt
%V Monday Week with Jan 4 (ISO 8601) Europe, ISO

✅ When to use %V

ISO 8601 week numbering applies when:

  • First weekday is Monday (_NL_TIME_FIRST_WEEKDAY == 1)
  • Anchor date (from _NL_TIME_WEEK_1STDAY) contains January 4th, or is consistent with ISO 8601's rule (week 1 contains Jan 4).

That means: you can write logic like this:

bool is_iso_week_format(locale_t loc) {
    const int first_wd = static_cast<uint8_t>(*nl_langinfo_l(_NL_TIME_FIRST_WEEKDAY, loc));
    if (first_wd != 1)  // not Monday
        return false;

    const int yyyymmdd = (int)((intptr_t)nl_langinfo_l(_NL_TIME_WEEK_1STDAY, loc));
    const int y = yyyymmdd / 10000;
    const int m = (yyyymmdd / 100) % 100;
    const int d = yyyymmdd % 100;

    if (m != 1)
        return false;

    // ISO 8601: Week 1 is the one containing Jan 4
    if (d >= 4 && d <= 10)
        return true;

    return false;
}

🔧 Final Use

You can now safely set:

if (is_iso_week_format(loc)) {
    fmtMap_.insert({4, "{:%V}"});
} else if (first_day_of_week() == Monday) {
    fmtMap_.insert({4, "{:%W}"});
} else {
    fmtMap_.insert({4, "{:%U}"});
}

Unfortunately my cpp is very limited so this kind of speculative vibing is the best i can do - no PRs from here 😥

edit: Imperfect but i'll take it. Anyway world coverage goes up from <50% to >90%

how do those couple locales behave where week starts on friday or something crazy like that?

ChatGPT said: Great question — and yes, there are locales where the first day of the week is something other than Monday or Sunday, such as:

  • "ar_SA" (Arabic, Saudi Arabia) → first day is Saturday
  • "fa_IR" (Persian, Iran) → first day is Saturday
  • "af_ZA" (Afrikaans, South Africa) → first day is Sunday
  • "en_DJ" (English, Djibouti) → first day is Friday

These are rare, but glibc does support them through _NL_TIME_FIRST_WEEKDAY, and they break assumptions made by formats like %W, %U, and %V.

Noino avatar May 21 '25 05:05 Noino

You can specify the format that you want with:

"weeks": "<span color='#99ffdd'><b>W{:%V}</b></span>",

But, it would be nice for it to pick up the default based on the locale.

Unfortunately, the above doesn't seem to work for specifying the format of months or weekdays (I'd like to use custom formats, not based on any locale)., It gives clock: format error: failed to parse format-spec and breaks the calendar completely...

kankaristo avatar Jul 12 '25 21:07 kankaristo

I also was facing this issue and figured it out myself how to do it. Then I found this issue here. Maybe this information could be added to the wiki page.

Kazhuu avatar Oct 02 '25 08:10 Kazhuu