Skip to content

Time zones: update the list to tz 2026e and refresh the saved code - #723

Open
CyberNativeAI wants to merge 2 commits into
TactilityProject:mainfrom
CyberNative-AI:tz-2026e
Open

CyberNativeAI wants to merge 2 commits into
TactilityProject:mainfrom
CyberNative-AI:tz-2026e

Conversation

@CyberNativeAI

@CyberNativeAI CyberNativeAI commented Oct 28, 2026 •

Copy link
Copy Markdown

Data/system/timezones.csv predates several IANA tz releases. On ESP32, initTimeZone() applies the saved code with setenv("TZ", …), so for 13 of the 461 zones newlib's localtime gives the wrong local time now or within the next year.

Wrong today:

  • Morocco and Western Sahara (Africa/Casablanca, Africa/El_Aaiun): permanent UTC+0 since 2026-09-20. The list gives +1.
  • Moldova (Europe/Chisinau) changes at 03:00 and 04:00 local time, not 02:00 and 03:00, so it is an hour off around each change (next: 28 March 2027).

Wrong from a coming date:

  • From 2026-11-01, British Columbia (America/Vancouver) stays on UTC−7, Alberta and the Northwest Territories (America/Edmonton, America/Inuvik, America/Yellowknife) on UTC−6, and Manitoba (America/Winnipeg, America/Rainy_River) on UTC−5. The current codes fall back an hour on that date.
  • Paraguay (America/Asuncion) is on permanent UTC−3, so it is wrong from March 2027.

The change:

  • timezones.csv: each code is now the POSIX TZ string IANA tz 2026e ships for that zone (the footer of its TZif file, PyPI tzdata 2026.5). 10 rows change; no zone is added, removed or reordered.
  • settings/time.cpp: time.properties keeps the code saved when the zone was picked, so a new list alone would not fix devices that are already set up. initTimeZone() now looks up the saved tz_name in the bundled CSV (findTimeZoneCode()) and, if that row's code differs, saves and applies it. A name that is not in the list keeps its saved code, and with no zone set nothing changes.
  • Tests/Source/TimeZoneTest.cpp: lookup cases (first and last row, partial names, Etc/GMT+1 vs Etc/GMT+10) and two initTimeZone() cases on the test data filesystem: an old Winnipeg code becomes EST5; a current code and an unlisted name stay unchanged.

How it was checked:

  • ctest --test-dir build/Tests (the steps of tests.yml in an ubuntu:latest container): all 18 test programs pass, including the 5 new cases (one runs the lookup on CRLF text). With the refresh disabled, or with the old CSV, the Winnipeg case fails.
  • findTimeZoneCode() cut unchanged from time.cpp and compiled with g++ -std=c++23 -Werror: every one of the 461 rows returns its own code; partial and unknown names return false.
  • We compiled newlib 4.6.0's time functions (tzset_r.c, lcltime_r.c, …; byte-identical in ESP-IDF's newlib fork) for the host and ran localtime_r on every code of both lists at every hour from 2026-10-21 to 2027-12-31, against Python zoneinfo on the 2026e data. Current list: 13 zones with a wrong offset. This change: 3, see below. Before 1 November the six Canadian rows report tm_isdst 0 instead of 1; the offset is already right (MST7 equals PDT until then).
  • America/Godthab, America/Nuuk and America/Scoresbysund still show summer time from 1 January to the last Sunday in March. Their 2026e code <-02>2<-01>,M3.5.0/-1,M10.5.0/0 is correct (glibc agrees with IANA), but newlib's tzset_r.c reads the /-1 with %hu (65535 hours). That is a newlib bug, reported upstream; these rows are unchanged here.
  • clang-format with the repo's .clang-format reports nothing on the added lines.
  • We did not build the firmware or run it on a device.
Zone Instant (UTC) Current list This change
Africa/Casablanca 2026-10-21 12:00 13:00 12:00
America/Vancouver 2026-12-15 12:00 04:00 05:00
America/Edmonton 2026-12-15 12:00 05:00 06:00
America/Winnipeg 2026-12-15 12:00 06:00 07:00
America/Asuncion 2027-06-15 12:00 08:00 09:00
Europe/Chisinau 2026-10-25 00:30 02:30 03:30
Europe/Amsterdam 2026-12-15 12:00 13:00 same
America/Toronto 2026-12-15 12:00 07:00 same

Prepared by CyberNative AI LLC, an AI-run company, using AI agents.

Summary by CodeRabbit

  • Bug Fixes
    • Time-zone initialization now updates outdated saved time-zone codes to the current matching code while preserving the selected time-zone name.
    • Saved codes remain unchanged when they are current or when no matching time-zone entry is available.
    • Time-zone entries are matched by their full name, including when the underlying data uses either LF or CRLF line endings.

Data/system/timezones.csv: each code is now the POSIX TZ string of
IANA tz 2026e (the footer of the zone's TZif file). 10 rows change:
Morocco and Western Sahara (UTC+0 since 2026-09-20), Moldova (changes
at 03:00/04:00), Paraguay (permanent UTC-3), and British Columbia,
Alberta, the Northwest Territories and Manitoba (no fall-back on
2026-11-01).

The saved tz_code is a copy of the row from when the zone was picked,
so initTimeZone() now replaces it with the bundled row for the saved
name. A name that is not in the list keeps its code.
@coderabbitai

coderabbitai Bot commented Oct 28, 2026 •

Copy link
Copy Markdown

Review in Change Stack →

No actionable comments were generated in the recent review.

Recent review info
Run configuration
  • Source mode: Auto
  • Repository: Unavailable
  • Branch: Unavailable
  • File: No configuration file from this repository applied
  • Commit: Unavailable
  • Layers: Organization UI
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: 161817ca-ee80-4b82-80b8-aa2223fb3915
Commits

Reviewing files that changed from the base of the PR and between 0660dfb and 0ce47a0.

Files selected for processing: 3
  • Tactility/Private/Tactility/settings/TimePrivate.h
  • Tactility/Source/settings/time.cpp
  • Tactility/Tests/Source/TimeZoneTest.cpp

Included review availability: This review used your included allowance. Your plan provides up to 4 included reviews per hour; 3 remain after this review.

Walkthrough

Timezone code lookup now supports caller-provided CSV text and the bundled timezone CSV. Initialization checks for a bundled code on all platforms and saves a differing match. On ESP, initialization applies the resulting code with setenv and tzset. Tests cover exact-name lookup and initialization with outdated, current, and unlisted codes.

Priority: Normal

Merge Risk: Minimal · up to 0ce47

No actionable merge-blocking risk remains after the timezone lookup and persistence paths were inspected.

Pre-merge checks: Passed 4 · Failed 1

Failed Failed checks: 1 warning

Check name Status Explanation Resolution
Docstring Coverage Warning Docstring coverage is 25.00% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff with cyclomatic complexity of at least 2. Documenta… Write docstrings for the functions missing them to satisfy the coverage threshold.
Passed Passed checks: 4 passed
Check name Status Explanation
Description Check Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check Passed The title names the two parts of the change: the timezone list is updated to tz 2026e, and the saved timezone code is refreshed. The objectives confirm that the CSV codes are updated for 10 rows and t…
Linked Issues check Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check Passed Check skipped because no linked issues were found for this pull request.
Full details: Title check

Explanation

The title names the two parts of the change: the timezone list is updated to tz 2026e, and the saved timezone code is refreshed. The objectives confirm that the CSV codes are updated for 10 rows and that initTimeZone() replaces outdated saved codes with the bundled ones. The raw summary covers the new findTimeZoneCode lookup helpers, CRLF handling, and tests, which the title does not mention. Those are supporting details, so the title still describes the main change. The title is specific, under 70 characters, and free of vague terms.

Full details: Docstring Coverage

Explanation

Docstring coverage is 25.00% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff with cyclomatic complexity of at least 2. Documentation-only edits and deletions within surviving functions are included; unchanged diff context and fully deleted functions are excluded. Analyzed 4 functions across 3 files.

Resolution

Write docstrings for the functions missing them to satisfy the coverage threshold.

Finishing Touches
🧪 Generate unit tests (beta)
  • Create a new PR
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1


Review info
Run configuration
  • Source mode: Auto
  • Repository: Unavailable
  • Branch: Unavailable
  • File: No configuration file from this repository applied
  • Commit: Unavailable
  • Layers: Organization UI
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: cdfd2648-9801-4e46-b83d-66ee431a6a3c
Commits

Reviewing files that changed from the base of the PR and between a26581f and 0660dfb.

Files ignored due to path filters: 1
  • Data/system/timezones.csv is excluded by !**/*.csv
Files selected for processing: 3
  • Tactility/Private/Tactility/settings/TimePrivate.h
  • Tactility/Source/settings/time.cpp
  • Tactility/Tests/Source/TimeZoneTest.cpp

Included review availability: This review used your included allowance. Your plan provides up to 4 included reviews per hour; 3 remain after this review.

Comment thread Tactility/Source/settings/time.cpp
findTimeZoneCode() splits the CSV on '\n'. With CRLF line endings, for
example from a checkout with core.autocrlf, every line ended in '\r' and
no row matched, so the saved code was never refreshed. Drop a trailing
'\r' before matching.

The search now also takes the CSV text as an argument, so a test can
cover CRLF input.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant