From nobody Mon Dec 16 13:35:20 2024 X-Original-To: dev-commits-src-all@mlmmj.nyi.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mlmmj.nyi.freebsd.org (Postfix) with ESMTP id 4YBgtJ5d1kz5hRT1; Mon, 16 Dec 2024 13:35:20 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from mxrelay.nyi.freebsd.org (mxrelay.nyi.freebsd.org [IPv6:2610:1c1:1:606c::19:3]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256 client-signature RSA-PSS (4096 bits) client-digest SHA256) (Client CN "mxrelay.nyi.freebsd.org", Issuer "R10" (verified OK)) by mx1.freebsd.org (Postfix) with ESMTPS id 4YBgtJ58nbz4Gdb; Mon, 16 Dec 2024 13:35:20 +0000 (UTC) (envelope-from git@FreeBSD.org) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1734356120; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=km0EtuXdmGT5z1nXEwC+vSE5VdSVMts942itWlkUwdc=; b=iIPWpQrGKZRfILUib0MjttZUfDP5WkMIdRYzpKZUIDmPaARLOX7Krdv9ZXaMVT8JFoj60r pC163tjFKZmq4W2oU/Gd1P1cU12Y027Da0vJTNXd0KF0lLQ7mrVDiDkV6RIzNVSMfWsAS5 jxZLVcxGz6oQJq3ONMTsJPXUZEkZXBlQ5kN1Q1cy3GtSEka87oRsB+eXlMg7uA0KCOVbcb 7ypiJryUVOEuenviJs3bPnx8173o7oPz3Ez9aKpaut0c48fEwnl2CmF9Wb/Ho/NWjThNBs rRL+Bmyy3/AYw7qz4M+jheFBitkkKyOt4Z46NoVQP9C7Ksx0K+juDBDKf36ghw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1734356120; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=km0EtuXdmGT5z1nXEwC+vSE5VdSVMts942itWlkUwdc=; b=Qcrx9+1/axLQDmJ/depWd7DOcgFpSdj9/nbJjF7R0CEN+/lBwObiPDoiFWL1ReGZyhj+G3 riaC5KFjpH2tCfwQl6t+JIVI+S6VBXVi7m/7vyjdl1pU6S7fkMBe0hq39Ss8Z3xOlgYoSl 4BEK8EDUuHAMo+BwRskSz+sk8FAdxBVPzbCfTC+1UkwEkL/xHTwtKaYKYoTM46Ygnr3hlk gZlPJswhuvCex0gaWaJWr3PSO0wR8dXcu5xC7D5ofe0lcICbuvZJ+yK7O1t7Uw+UaycFuk qQSrQ+rsp32suLgQ1FT1lkWR7SY9Z35tuHuEvR5qI8/QFHTJhxea9Hy0ycdHJg== ARC-Authentication-Results: i=1; mx1.freebsd.org; none ARC-Seal: i=1; s=dkim; d=freebsd.org; t=1734356120; a=rsa-sha256; cv=none; b=GdvH/aAfOCyxpWvLKsf2CiCQlkdWqmOBgkC7SFzZTW2sO4LMBYYUDzEhOq7y4yWM5DLBwl NYtcAcEXF17YytH3OlyV6MMIquibq2qEeI5+eav5xMWZ4dwApaJJQvC4Ow+GdzO0r4W+OU 99EUlBNcjArymO/eNmq8PHS0uDT1C1hZ8iqeeOSBolU1p7kH94ubvA2CM/HXLQ3N6iuUdm GQh6XOndWhUS+V8Fpzw4N96igCoz5KGsyObE0MJJUzRsBD0zypqPC9MUyKjPEChN0l1Yzv DdrQIN8ofYzpHjiDBxuAqRsctKJJk0ogOPwKscOIfskZ56zouPvNohRhowpDdA== Received: from gitrepo.freebsd.org (gitrepo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:5]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (Client did not present a certificate) by mxrelay.nyi.freebsd.org (Postfix) with ESMTPS id 4YBgtJ4l8jzw29; Mon, 16 Dec 2024 13:35:20 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from gitrepo.freebsd.org ([127.0.1.44]) by gitrepo.freebsd.org (8.18.1/8.18.1) with ESMTP id 4BGDZKh8020202; Mon, 16 Dec 2024 13:35:20 GMT (envelope-from git@gitrepo.freebsd.org) Received: (from git@localhost) by gitrepo.freebsd.org (8.18.1/8.18.1/Submit) id 4BGDZKJR020199; Mon, 16 Dec 2024 13:35:20 GMT (envelope-from git) Date: Mon, 16 Dec 2024 13:35:20 GMT Message-Id: <202412161335.4BGDZKJR020199@gitrepo.freebsd.org> To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-branches@FreeBSD.org From: Dag-Erling =?utf-8?Q?Sm=C3=B8rgrav?= Subject: git: 48d21d15a8f2 - stable/13 - strptime: Fix day-of-week calculation. List-Id: Commit messages for all branches of the src repository List-Archive: https://lists.freebsd.org/archives/dev-commits-src-all List-Help: List-Post: List-Subscribe: List-Unsubscribe: X-BeenThere: dev-commits-src-all@freebsd.org Sender: owner-dev-commits-src-all@FreeBSD.org MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit X-Git-Committer: des X-Git-Repository: src X-Git-Refname: refs/heads/stable/13 X-Git-Reftype: branch X-Git-Commit: 48d21d15a8f22c766f1651c0a244554f6b5d7af7 Auto-Submitted: auto-generated The branch stable/13 has been updated by des: URL: https://cgit.FreeBSD.org/src/commit/?id=48d21d15a8f22c766f1651c0a244554f6b5d7af7 commit 48d21d15a8f22c766f1651c0a244554f6b5d7af7 Author: Dag-Erling Smørgrav AuthorDate: 2024-12-09 12:37:45 +0000 Commit: Dag-Erling Smørgrav 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 | 7 +++++ lib/libc/tests/stdtime/strptime_test.c | 50 ++++++++++++++++++++++++++++++++++ 6 files changed, 74 insertions(+), 15 deletions(-) diff --git a/etc/mtree/BSD.tests.dist b/etc/mtree/BSD.tests.dist index c2d99ae33e30..4315fe9657c9 100644 --- a/etc/mtree/BSD.tests.dist +++ b/etc/mtree/BSD.tests.dist @@ -358,6 +358,8 @@ .. stdlib .. + stdtime + .. string .. sys diff --git a/lib/libc/stdtime/strptime.3 b/lib/libc/stdtime/strptime.3 index 0dfa33aa29cb..7df73d2d080a 100644 --- a/lib/libc/stdtime/strptime.3 +++ b/lib/libc/stdtime/strptime.3 @@ -23,7 +23,7 @@ .\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF .\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. .\" " -.Dd October 2, 2014 +.Dd December 9, 2024 .Dt STRPTIME 3 .Os .Sh NAME @@ -135,6 +135,11 @@ function has been contributed by Powerdog Industries. .Pp This man page was written by .An J\(:org Wunsch . +.Sh CAVEATS +The +.Fn strptime +function assumes the Gregorian calendar and will produce incorrect +results for dates prior to its introduction. .Sh BUGS Both the .Fa %e diff --git a/lib/libc/stdtime/strptime.c b/lib/libc/stdtime/strptime.c index 848b94545dd2..e9ffe7180916 100644 --- a/lib/libc/stdtime/strptime.c +++ b/lib/libc/stdtime/strptime.c @@ -70,17 +70,16 @@ static char * _strptime(const char *, const char *, struct tm *, int *, locale_t #define FLAG_WDAY (1 << 5) /* - * Calculate the week day of the first day of a year. Valid for - * the Gregorian calendar, which began Sept 14, 1752 in the UK - * and its colonies. Ref: - * http://en.wikipedia.org/wiki/Determination_of_the_day_of_the_week + * Gauss's algorithm for the day of the week of the first day of any year + * in the Gregorian calendar. */ - static int first_wday_of(int year) { - return (((2 * (3 - (year / 100) % 4)) + (year % 100) + - ((year % 100) / 4) + (isleap(year) ? 6 : 0) + 1) % 7); + return ((1 + + 5 * ((year - 1) % 4) + + 4 * ((year - 1) % 100) + + 6 * ((year - 1) % 400)) % 7); } static char * @@ -682,13 +681,8 @@ label: flags |= FLAG_MDAY; } if (!(flags & FLAG_WDAY)) { - i = 0; - wday_offset = first_wday_of(tm->tm_year); - while (i++ <= tm->tm_yday) { - if (wday_offset++ >= 6) - wday_offset = 0; - } - tm->tm_wday = wday_offset; + wday_offset = first_wday_of(tm->tm_year + TM_YEAR_BASE); + tm->tm_wday = (wday_offset + tm->tm_yday) % 7; flags |= FLAG_WDAY; } } diff --git a/lib/libc/tests/Makefile b/lib/libc/tests/Makefile index 7b262ea646fb..20238b376752 100644 --- a/lib/libc/tests/Makefile +++ b/lib/libc/tests/Makefile @@ -16,6 +16,7 @@ TESTS_SUBDIRS+= rpc TESTS_SUBDIRS+= setjmp TESTS_SUBDIRS+= stdio TESTS_SUBDIRS+= stdlib +TESTS_SUBDIRS+= stdtime TESTS_SUBDIRS+= string TESTS_SUBDIRS+= sys TESTS_SUBDIRS+= termios diff --git a/lib/libc/tests/stdtime/Makefile b/lib/libc/tests/stdtime/Makefile new file mode 100644 index 000000000000..c7a7f5b9436f --- /dev/null +++ b/lib/libc/tests/stdtime/Makefile @@ -0,0 +1,7 @@ +.include + +ATF_TESTS_C+= strptime_test + +TESTSDIR:= ${TESTSBASE}/${RELDIR:C/libc\/tests/libc/} + +.include diff --git a/lib/libc/tests/stdtime/strptime_test.c b/lib/libc/tests/stdtime/strptime_test.c new file mode 100644 index 000000000000..79a97764999c --- /dev/null +++ b/lib/libc/tests/stdtime/strptime_test.c @@ -0,0 +1,50 @@ +/*- + * Copyright (c) 2024 Dag-Erling Smørgrav + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#include + +#include + +ATF_TC_WITHOUT_HEAD(dayofweek); +ATF_TC_BODY(dayofweek, tc) +{ + static const struct { + const char *str; + int wday; + } cases[] = { + { "1582-12-20", 1 }, + { "1700-03-01", 1 }, + { "1752-09-14", 4 }, + { "1800-12-31", 3 }, + { "1801-01-01", 4 }, + { "1900-12-31", 1 }, + { "1901-01-01", 2 }, + { "2000-12-31", 0 }, + { "2001-01-01", 1 }, + { "2100-12-31", 5 }, + { "2101-01-01", 6 }, + { "2200-12-31", 3 }, + { "2201-01-01", 4 }, + { }, + }; + struct tm tm; + + for (unsigned int i = 0; cases[i].str != NULL; i++) { + if (strptime(cases[i].str, "%Y-%m-%d", &tm) == NULL) { + atf_tc_fail_nonfatal("failed to parse %s", + cases[i].str); + } else if (tm.tm_wday != cases[i].wday) { + atf_tc_fail_nonfatal("expected %d for %s, got %d", + cases[i].wday, cases[i].str, tm.tm_wday); + } + } +} + +ATF_TP_ADD_TCS(tp) +{ + ATF_TP_ADD_TC(tp, dayofweek); + return (atf_no_error()); +}