From d130ce6a664f79c4256b712049570e6bfd4a94af Mon Sep 17 00:00:00 2001 From: Alex Date: Sat, 4 Jul 2026 03:10:55 +0200 Subject: [PATCH] fix(clock): disambiguate DST transitions to stop tooltip crash Building a zoned_time/zoned_seconds from a local_time throws ambiguous_local_time during the DST fall-back hour and nonexistent_local_time across the spring-forward gap. update() runs this every minute with the tooltip enabled by default and has no try/catch, so Waybar aborts every minute during a DST transition. Pass choose::earliest at each construction to resolve deterministically instead of throwing. Fixes #2615; resolves the recurring DST-crash duplicates #5006, #5018, #5063, #5096, #3024. --- src/modules/clock.cpp | 25 ++++++++++++++++--------- 1 file changed, 16 insertions(+), 9 deletions(-) diff --git a/src/modules/clock.cpp b/src/modules/clock.cpp index 016d1d75..bd1a17d1 100644 --- a/src/modules/clock.cpp +++ b/src/modules/clock.cpp @@ -190,8 +190,13 @@ auto waybar::modules::Clock::update() -> void { if (tooltipEnabled()) { const year_month_day today{floor(now.get_local_time())}; const auto shiftedDay{today + cldCurrShift_}; + // choose::earliest disambiguates the DST fall-back hour (ambiguous local + // time) and skips forward over the spring-forward gap (nonexistent local + // time); without it this constructor throws and aborts Waybar every minute + // during a DST transition. Fixes #2615 (and its many duplicates). const zoned_time shiftedNow{ - tz, local_days(shiftedDay) + (now.get_local_time() - floor(now.get_local_time()))}; + tz, local_days(shiftedDay) + (now.get_local_time() - floor(now.get_local_time())), + choose::earliest}; if (tzInTooltip_) tzText_ = getTZtext(now.get_sys_time()); if (cldInTooltip_) cldText_ = get_calendar(today, shiftedDay, tz); @@ -441,9 +446,11 @@ auto waybar::modules::Clock::get_calendar(const year_month_day& today, const yea fmt_lib::make_format_args( (line == 2) ? static_cast( - zoned_seconds{tz, local_days{ymTmp / 1}}) - : static_cast(zoned_seconds{ - tz, local_days{cldGetWeekForLine(ymTmp, firstdow, line)}}))) + zoned_seconds{tz, local_days{ymTmp / 1}, choose::earliest}) + : static_cast( + zoned_seconds{tz, + local_days{cldGetWeekForLine(ymTmp, firstdow, line)}, + choose::earliest}))) << ' '; } else { os << pads; @@ -482,11 +489,11 @@ auto waybar::modules::Clock::get_calendar(const year_month_day& today, const yea << fmt_lib::vformat( m_locale_, fmtMap_[4], fmt_lib::make_format_args( - (line == 2) ? static_cast( - zoned_seconds{tz, local_days{ymTmp / 1}}) - : static_cast( - zoned_seconds{tz, local_days{cldGetWeekForLine( - ymTmp, firstdow, line)}}))); + (line == 2) ? static_cast(zoned_seconds{ + tz, local_days{ymTmp / 1}, choose::earliest}) + : static_cast(zoned_seconds{ + tz, local_days{cldGetWeekForLine(ymTmp, firstdow, line)}, + choose::earliest}))); else os << pads; }