Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Inconsistent behaviour of dates / daylight savings after 2038 #874

Open
gowerc opened this issue Mar 12, 2025 · 3 comments
Open

Inconsistent behaviour of dates / daylight savings after 2038 #874

gowerc opened this issue Mar 12, 2025 · 3 comments

Comments

@gowerc
Copy link

gowerc commented Mar 12, 2025

Apologies in advance I appreciate this is likely a user issue as I am not that familiar with the low level details of datetimes but I am at a loss now for what is going wrong so suspect there is a small possibility it could be some form of a bug.

If I compile and build the library using USE_SYSTEM_TZ_DB=OFF I get the correct expected datetimes after 2038 e.g.

#include <iostream>
#include <chrono>
#include <date/date.h>
#include <date/tz.h>

void printme(long long x) {
    date::sys_seconds utc_time{std::chrono::seconds(x)};
    date::zoned_time ny_time{"America/New_York", utc_time};
    std::cout << "Local time: " << date::format("%F %T %Z", ny_time) << '\n';
}

int main() {
    std::cout << "C++ Standard Version: " << __cplusplus << std::endl;
    printme(2095940701);
    printme(2127476701);
    printme(2159012701);
    printme(2190548701);
}

Produces as expected:

C++ Standard Version: 201703
Local time: 2036-06-01 09:45:01 EDT
Local time: 2037-06-01 09:45:01 EDT
Local time: 2038-06-01 09:45:01 EDT
Local time: 2039-06-01 09:45:01 EDT

However if I compile and rebuild the library with USE_SYSTEM_TZ_DB=ON and run the same exact code I no longer get the expected results (in particular it no longer seems to follow daylight savings rules):

C++ Standard Version: 201703
Local time: 2036-06-01 09:45:01 EDT
Local time: 2037-06-01 09:45:01 EDT
Local time: 2038-06-01 08:45:01 EST
Local time: 2039-06-01 08:45:01 EST

My first thought was that it must be an issue with my local tzdata however that all appears to be up-to-date, that is when running zdump -v America/New_York I can see that the rules are populated up till 2499:

America/New_York  Sun Mar  9 06:59:59 2498 UT = Sun Mar  9 01:59:59 2498 EST isdst=0 gmtoff=-18000
America/New_York  Sun Mar  9 07:00:00 2498 UT = Sun Mar  9 03:00:00 2498 EDT isdst=1 gmtoff=-14400
America/New_York  Sun Nov  2 05:59:59 2498 UT = Sun Nov  2 01:59:59 2498 EDT isdst=1 gmtoff=-14400
America/New_York  Sun Nov  2 06:00:00 2498 UT = Sun Nov  2 01:00:00 2498 EST isdst=0 gmtoff=-18000
America/New_York  Sun Mar  8 06:59:59 2499 UT = Sun Mar  8 01:59:59 2499 EST isdst=0 gmtoff=-18000
America/New_York  Sun Mar  8 07:00:00 2499 UT = Sun Mar  8 03:00:00 2499 EDT isdst=1 gmtoff=-14400
America/New_York  Sun Nov  1 05:59:59 2499 UT = Sun Nov  1 01:59:59 2499 EDT isdst=1 gmtoff=-14400
America/New_York  Sun Nov  1 06:00:00 2499 UT = Sun Nov  1 01:00:00 2499 EST isdst=0 gmtoff=-18000

Likewise when I try using other software on my machine they also seem to be following the rules as expected e.g. Python:

import zoneinfo
import datetime

def printtime(time: int):
    ny_time =  datetime.datetime.fromtimestamp(time, zoneinfo.ZoneInfo("America/New_York"))
    print(f"Time: {ny_time} ({ny_time.tzname()})")

print(zoneinfo.TZPATH)  # ('/usr/share/zoneinfo', '/usr/lib/zoneinfo', '/usr/share/lib/zoneinfo', '/etc/zoneinfo')

printtime(2095940701)  # Time: 2036-06-01 09:45:01-04:00 (EDT)
printtime(2127476701)  # Time: 2037-06-01 09:45:01-04:00 (EDT)
printtime(2159012701)  # Time: 2038-06-01 09:45:01-04:00 (EDT)
printtime(2190548701)  # Time: 2039-06-01 09:45:01-04:00 (EDT)

And also in R:

as.POSIXct(2095940701, tz = "America/New_York")      # "2036-06-01 09:45:01 EDT"
as.POSIXct(2127476701, tz = "America/New_York")      # "2037-06-01 09:45:01 EDT"
as.POSIXct(2159012701, tz = "America/New_York")      # "2038-06-01 09:45:01 EDT"
as.POSIXct(2190548701, tz = "America/New_York")      # "2039-06-01 09:45:01 EDT"

Which implies to me that the local timezone database is fully up-to-date; so is this a bug with the library or am I specifying something incorrectly (apologies if the latter) ?

EDIT -

For reference I am on Fedora 41 on a x64 intel cpu laptop using the standard package manager distributed software

> dnf info tzdata
Name            : tzdata
Epoch           : 0
Version         : 2025a
Release         : 1.fc41
Architecture    : noarch
Installed size  : 1.6 MiB
Source          : tzdata-2025a-1.fc41.src.rpm
From repository : updates
Summary         : Timezone data
URL             : https://www.iana.org/time-zones
License         : LicenseRef-Fedora-Public-Domain AND (GPL-2.0-only WITH ClassPath-exception-2.0)
Description     : This package contains data files with rules for various timezones around
                : the world.
Vendor          : Fedora Project
> zdump --version
zdump (GNU libc) 2.40
> g++ --version     
g++ (GCC) 14.2.1 20250110 (Red Hat 14.2.1-7)
Copyright (C) 2024 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
@HowardHinnant
Copy link
Owner

You are correct that you have found a bug in this tz library.

This library was voted into the C++20 standard with very few changes. And gcc 14.2 fully implements it. My recommendation is to migrate to the C++20 version:

#include <iostream>
#include <chrono>
#include <format>

void printme(long long x) {
    std::chrono::sys_seconds utc_time{std::chrono::seconds(x)};
    std::chrono::zoned_time ny_time{"America/New_York", utc_time};
    std::cout << "Local time: " << std::format("{:%F %T %Z}", ny_time) << '\n';
}

int main() {
    std::cout << "C++ Standard Version: " << __cplusplus << std::endl;
    printme(2095940701);
    printme(2127476701);
    printme(2159012701);
    printme(2190548701);
}

@gowerc
Copy link
Author

gowerc commented Mar 12, 2025

@HowardHinnant - Thank you for the response, I can confirm using the 2020 std::chrono version appears to fix this issue for me thank you.

@DavisVaughan
Copy link
Contributor

Probably same issue as #563

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

No branches or pull requests

3 participants