Created attachment 255388 [details] Test code for strptime(..., "%x", ...) When I use strptime() input descriptor "%x" to decode date, then after 12/31/00 strptime() decodes wrong wday. Here are the different test results from the attached test program. Expected decoded values are (reference tests on Ubuntu Linux): 12/31/00: Time: 00:00:00 Date: 2000-12-31 Wday: 0 Yday: 365 (DST 0 Zone [(null)] offset 0) 01/01/01: Time: 00:00:00 Date: 2001-01-01 Wday: 1 Yday: 000 (DST 0 Zone [(null)] offset 0) 01/02/01: Time: 00:00:00 Date: 2001-01-02 Wday: 2 Yday: 001 (DST 0 Zone [(null)] offset 0) Actual values on FreeBSD 14.1-RELEASE-p5 GENERIC amd64: 12/31/00: Time: 00:00:00 Date: 2000-12-31 Wday: 0 Yday: 365 (DST 0 Zone [(null)] offset 0) 01/01/01: Time: 00:00:00 Date: 2001-01-01 Wday: 0 Yday: 000 (DST 0 Zone [(null)] offset 0) 01/02/01: Time: 00:00:00 Date: 2001-01-02 Wday: 1 Yday: 001 (DST 0 Zone [(null)] offset 0) Also wday values from %c and %x are different (first lines are decoded by using %c, last by using %x): Fri Mar 4 20:05:34 2005: Time: 20:05:34 Date: 2005-03-04 Wday: 5 Yday: 062 (DST 0 Zone [(null)] offset 0) 03/04/05: Time: 00:00:00 Date: 2005-03-04 Wday: 4 Yday: 062 (DST 0 Zone [(null)] offset 0)
Philip, do you sync the strptime() implementation from an upstream together with timezone info? Maybe we're missing a bug fix somewhere.
It might be worth also taking a look at: https://github.com/apple-oss-distributions/Libc/blob/main/stdtime/FreeBSD/strptime.c
I've only been syncing tzdata. DES has been tracking tzcode of late. I thought we were mostly in sync with upstream, but something may have been missed. DES: do you have time to take a look at this? If not, feel free to assign to me and I'll look for a round tuit. :) Thank you!
strptime(3) is not part of tzcode, but I'll take a look.
The situation was worse than I expected, with only 4 out of my 13 test cases passing: *** Check failed: expected 1 for 1582-12-20, got 2 *** Check failed: expected 4 for 1752-09-14, got 3 *** Check failed: expected 4 for 1801-01-01, got -3 *** Check failed: expected 1 for 1900-12-31, got 0 *** Check failed: expected 1 for 2001-01-01, got 0 *** Check failed: expected 5 for 2100-12-31, got 4 *** Check failed: expected 6 for 2101-01-01, got 5 *** Check failed: expected 3 for 2200-12-31, got 2 *** Check failed: expected 4 for 2201-01-01, got 3
A commit in branch main references this bug: URL: https://cgit.FreeBSD.org/src/commit/?id=4285e024baa80f81d13cdcc016fdf0721fe57862 commit 4285e024baa80f81d13cdcc016fdf0721fe57862 Author: Dag-Erling Smørgrav <des@FreeBSD.org> AuthorDate: 2024-12-09 12:37:45 +0000 Commit: Dag-Erling Smørgrav <des@FreeBSD.org> CommitDate: 2024-12-09 12:38:22 +0000 strptime: Fix day-of-week calculation. The day-of-week calculation used the raw year value without adjusting for TM_YEAR_BASE, so it was off by one for 300 years out of every 400; it just happened to be correct for 1901 through 2000. It also used a loop where a simple addition would have sufficed. While here, simplify our version of Gauss's algorithm, and document that we assume the Gregorian calendar. MFC after: 1 week PR: 282916 Reviewed by: imp, allanjude, philip Differential Revision: https://reviews.freebsd.org/D47977 etc/mtree/BSD.tests.dist | 2 ++ lib/libc/stdtime/strptime.3 | 7 +++- lib/libc/stdtime/strptime.c | 22 +++++------- lib/libc/tests/Makefile | 1 + lib/libc/tests/stdtime/Makefile (new) | 7 ++++ lib/libc/tests/stdtime/strptime_test.c (new) | 50 ++++++++++++++++++++++++++++ 6 files changed, 74 insertions(+), 15 deletions(-)
A commit in branch stable/14 references this bug: URL: https://cgit.FreeBSD.org/src/commit/?id=259dcedc4ade538c35100d364e5cfe30b89c9a95 commit 259dcedc4ade538c35100d364e5cfe30b89c9a95 Author: Dag-Erling Smørgrav <des@FreeBSD.org> AuthorDate: 2024-12-09 12:37:45 +0000 Commit: Dag-Erling Smørgrav <des@FreeBSD.org> CommitDate: 2024-12-16 10:37:08 +0000 strptime: Fix day-of-week calculation. The day-of-week calculation used the raw year value without adjusting for TM_YEAR_BASE, so it was off by one for 300 years out of every 400; it just happened to be correct for 1901 through 2000. It also used a loop where a simple addition would have sufficed. While here, simplify our version of Gauss's algorithm, and document that we assume the Gregorian calendar. MFC after: 1 week PR: 282916 Reviewed by: imp, allanjude, philip Differential Revision: https://reviews.freebsd.org/D47977 (cherry picked from commit 4285e024baa80f81d13cdcc016fdf0721fe57862) etc/mtree/BSD.tests.dist | 2 ++ lib/libc/stdtime/strptime.3 | 7 +++- lib/libc/stdtime/strptime.c | 22 +++++------- lib/libc/tests/Makefile | 1 + lib/libc/tests/stdtime/Makefile (new) | 7 ++++ lib/libc/tests/stdtime/strptime_test.c (new) | 50 ++++++++++++++++++++++++++++ 6 files changed, 74 insertions(+), 15 deletions(-)
A commit in branch stable/13 references this bug: URL: https://cgit.FreeBSD.org/src/commit/?id=48d21d15a8f22c766f1651c0a244554f6b5d7af7 commit 48d21d15a8f22c766f1651c0a244554f6b5d7af7 Author: Dag-Erling Smørgrav <des@FreeBSD.org> AuthorDate: 2024-12-09 12:37:45 +0000 Commit: Dag-Erling Smørgrav <des@FreeBSD.org> CommitDate: 2024-12-16 10:38:57 +0000 strptime: Fix day-of-week calculation. The day-of-week calculation used the raw year value without adjusting for TM_YEAR_BASE, so it was off by one for 300 years out of every 400; it just happened to be correct for 1901 through 2000. It also used a loop where a simple addition would have sufficed. While here, simplify our version of Gauss's algorithm, and document that we assume the Gregorian calendar. MFC after: 1 week PR: 282916 Reviewed by: imp, allanjude, philip Differential Revision: https://reviews.freebsd.org/D47977 (cherry picked from commit 4285e024baa80f81d13cdcc016fdf0721fe57862) etc/mtree/BSD.tests.dist | 2 ++ lib/libc/stdtime/strptime.3 | 7 +++- lib/libc/stdtime/strptime.c | 22 +++++------- lib/libc/tests/Makefile | 1 + lib/libc/tests/stdtime/Makefile (new) | 7 ++++ lib/libc/tests/stdtime/strptime_test.c (new) | 50 ++++++++++++++++++++++++++++ 6 files changed, 74 insertions(+), 15 deletions(-)