From 9952f1458ffdf3f22b1013dab019fb273dff357f Mon Sep 17 00:00:00 2001 From: Kevin B Kenny Date: Tue, 18 May 2004 21:52:56 +0000 Subject: * compat/strftime.c (_fmt, ISO8601Week): * doc/clock.n: * tests/clock.test: Major rework to the handling of ISO8601 week numbers. Now passes all the %G and %V test cases on Windows, Linux and Solaris [Bugs #500285, #500389, and #852944] --- ChangeLog | 8 +++ compat/strftime.c | 98 +++++++++++++++++++++++++++-------- doc/clock.n | 8 ++- tests/clock.test | 150 +++++++++++++++++++++++++++++++++++++++++++++++++++++- 4 files changed, 241 insertions(+), 23 deletions(-) diff --git a/ChangeLog b/ChangeLog index 3179038..f34990d 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,11 @@ +2004-05-18 Kevin B. Kenny + + * compat/strftime.c (_fmt, ISO8601Week): + * doc/clock.n: + * tests/clock.test: Major rework to the handling of ISO8601 + week numbers. Now passes all the %G and %V test cases on + Windows, Linux and Solaris [Bugs #500285, #500389, and #852944] + 2004-05-17 Kevin B. Kenny * generic/tclInt.decls: Restored TclpTime_t kludge to all diff --git a/compat/strftime.c b/compat/strftime.c index 027e373..dbd7d54 100644 --- a/compat/strftime.c +++ b/compat/strftime.c @@ -10,7 +10,7 @@ * * Changes 2002 Copyright (c) 2002 ActiveState Corporation. * - * RCS: @(#) $Id: strftime.c,v 1.10 2002/05/29 00:19:39 hobbs Exp $ + * RCS: @(#) $Id: strftime.c,v 1.10.2.1 2004/05/18 21:52:56 kennykb Exp $ */ /* @@ -47,7 +47,7 @@ */ #if defined(LIBC_SCCS) -static char *rcsid = "$Id: strftime.c,v 1.10 2002/05/29 00:19:39 hobbs Exp $"; +static char *rcsid = "$Id: strftime.c,v 1.10.2.1 2004/05/18 21:52:56 kennykb Exp $"; #endif /* LIBC_SCCS */ #include @@ -113,6 +113,7 @@ static int _conv _ANSI_ARGS_((int n, int digits, int pad)); static int _secs _ANSI_ARGS_((const struct tm *t)); static size_t _fmt _ANSI_ARGS_((const char *format, const struct tm *t)); +static int ISO8601Week _ANSI_ARGS_((CONST struct tm* t, int *year )); size_t TclpStrftime(s, maxsize, format, t, useGMT) @@ -229,6 +230,24 @@ _fmt(format, t) if (!_conv(t->tm_mday, 2, ' ')) return(0); continue; + case 'g': + { + int year; + ISO8601Week( t, &year ); + if ( !_conv( year%100, 2, '0' ) ) { + return( 0 ); + } + continue; + } + case 'G': + { + int year; + ISO8601Week( t, &year ); + if ( !_conv( year, 4, '0' ) ) { + return( 0 ); + } + continue; + } case 'H': if (!_conv(t->tm_hour, 2, '0')) return(0); @@ -301,25 +320,7 @@ _fmt(format, t) continue; case 'V': { - /* ISO 8601 Week Of Year: - If the week (Monday - Sunday) containing - January 1 has four or more days in the new - year, then it is week 1; otherwise it is - week 53 of the previous year and the next - week is week one. */ - - int week = MON_WEEK(t); - - int days = (((t)->tm_yday + 7 - \ - ((t)->tm_wday ? (t)->tm_wday - 1 : 6)) % 7); - - - if (days >= 4) { - week++; - } else if (week == 0) { - week = 53; - } - + int week = ISO8601Week( t, NULL ); if (!_conv(week, 2, '0')) return(0); continue; @@ -449,3 +450,58 @@ _add(str) return(1); } } + +static int +ISO8601Week( t, year ) + CONST struct tm* t; + int* year; +{ + /* Find the day-of-year of the Thursday in + * the week in question. */ + + int ydayThursday; + int week; + if ( t->tm_wday == 0 ) { + ydayThursday = t->tm_yday - 3; + } else { + ydayThursday = t->tm_yday - t->tm_wday + 4; + } + + if ( ydayThursday < 0 ) { + + /* This is the last week of the previous year. */ + if ( IsLeapYear(( t->tm_year + TM_YEAR_BASE - 1 )) ) { + ydayThursday += 366; + } else { + ydayThursday += 365; + } + week = ydayThursday / 7 + 1; + if ( year != NULL ) { + *year = t->tm_year + 1899; + } + + } else if ( ( IsLeapYear(( t -> tm_year + TM_YEAR_BASE )) + && ydayThursday >= 366 ) + || ( !IsLeapYear(( t -> tm_year + + TM_YEAR_BASE )) + && ydayThursday >= 365 ) ) { + + /* This is week 1 of the following year */ + + week = 1; + if ( year != NULL ) { + *year = t->tm_year + 1901; + } + + } else { + + week = ydayThursday / 7 + 1; + if ( year != NULL ) { + *year = t->tm_year + 1900; + } + + } + + return week; + +} diff --git a/doc/clock.n b/doc/clock.n index de2baa2..41a1cef 100644 --- a/doc/clock.n +++ b/doc/clock.n @@ -10,7 +10,7 @@ '\" See the file "license.terms" for information on usage and redistribution '\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. '\" -'\" RCS: @(#) $Id: clock.n,v 1.11.2.1 2004/02/06 16:47:53 dgp Exp $ +'\" RCS: @(#) $Id: clock.n,v 1.11.2.2 2004/05/18 21:52:56 kennykb Exp $ '\" .so man.macros .TH clock n 8.4 Tcl "Tcl Built-In Commands" @@ -79,6 +79,12 @@ Day of month (01 - 31). Date as %m/%d/%y. .IP \fB%e\fR Day of month (1 - 31), no leading zeros. +.IP \fB%g\fR +The ISO8601 year number corresponding to the ISO8601 week (%V), expressed +as a two-digit year-of-the-century, with leading zero if necessary. +.IP \fB%G\fR +The ISO8601 year number corresponding to the ISO8601 week (%V), expressed +as a four-digit number. .IP \fB%h\fR Abbreviated month name. .VE 8.4 diff --git a/tests/clock.test b/tests/clock.test index 72c254e..8d69b72 100644 --- a/tests/clock.test +++ b/tests/clock.test @@ -10,7 +10,7 @@ # See the file "license.terms" for information on usage and redistribution # of this file, and for a DISCLAIMER OF ALL WARRANTIES. # -# RCS: @(#) $Id: clock.test,v 1.22.2.2 2004/05/14 21:41:11 kennykb Exp $ +# RCS: @(#) $Id: clock.test,v 1.22.2.3 2004/05/18 21:52:57 kennykb Exp $ set env(LC_TIME) POSIX @@ -482,6 +482,154 @@ test clock-9.1 {%s gmt testing} {needPST} { set c [expr {$b-$a}] } {28800} +test clock-10.1 {ISO week-based calendar 2000-W52-1} { + clock format 977702400 -format {%a %A %g %G %u %V %w} -gmt true; # 2000-12-25 +} {Mon Monday 00 2000 1 52 1} +test clock-10.2 {ISO week-based calendar 2000-W52-7} { + clock format 978220800 -format {%a %A %g %G %u %V %w} -gmt true; # 2000-12-31 +} {Sun Sunday 00 2000 7 52 0} +test clock-10.3 {ISO week-based calendar 2001-W01-1} { + clock format 978307200 -format {%a %A %g %G %u %V %w} -gmt true; # 2001-1-1 +} {Mon Monday 01 2001 1 01 1} +test clock-10.4 {ISO week-based calendar 2001-W01-7} { + clock format 978825600 -format {%a %A %g %G %u %V %w} -gmt true; # 2001-1-7 +} {Sun Sunday 01 2001 7 01 0} +test clock-10.5 {ISO week-based calendar 2001-W02-1} { + clock format 978912000 -format {%a %A %g %G %u %V %w} -gmt true; # 2001-1-8 +} {Mon Monday 01 2001 1 02 1} +test clock-10.6 {ISO week-based calendar 2001-W52-1} { + clock format 1009152000 -format {%a %A %g %G %u %V %w} -gmt true; # 2001-12-24 +} {Mon Monday 01 2001 1 52 1} +test clock-10.7 {ISO week-based calendar 2001-W52-7} { + clock format 1009670400 -format {%a %A %g %G %u %V %w} -gmt true; # 2001-12-30 +} {Sun Sunday 01 2001 7 52 0} +test clock-10.8 {ISO week-based calendar 2002-W01-1} { + clock format 1009756800 -format {%a %A %g %G %u %V %w} -gmt true; # 2001-12-31 +} {Mon Monday 02 2002 1 01 1} +test clock-10.9 {ISO week-based calendar 2002-W01-2} { + clock format 1009843200 -format {%a %A %g %G %u %V %w} -gmt true; # 2002-1-1 +} {Tue Tuesday 02 2002 2 01 2} +test clock-10.10 {ISO week-based calendar 2002-W01-7} { + clock format 1010275200 -format {%a %A %g %G %u %V %w} -gmt true; # 2002-1-6 +} {Sun Sunday 02 2002 7 01 0} +test clock-10.11 {ISO week-based calendar 2002-W02-1} { + clock format 1010361600 -format {%a %A %g %G %u %V %w} -gmt true; # 2002-1-7 +} {Mon Monday 02 2002 1 02 1} +test clock-10.12 {ISO week-based calendar 2002-W52-1} { + clock format 1040601600 -format {%a %A %g %G %u %V %w} -gmt true; # 2002-12-23 +} {Mon Monday 02 2002 1 52 1} +test clock-10.13 {ISO week-based calendar 2002-W52-7} { + clock format 1041120000 -format {%a %A %g %G %u %V %w} -gmt true; # 2002-12-29 +} {Sun Sunday 02 2002 7 52 0} +test clock-10.14 {ISO week-based calendar 2003-W01-1} { + clock format 1041206400 -format {%a %A %g %G %u %V %w} -gmt true; # 2002-12-30 +} {Mon Monday 03 2003 1 01 1} +test clock-10.15 {ISO week-based calendar 2003-W01-2} { + clock format 1041292800 -format {%a %A %g %G %u %V %w} -gmt true; # 2002-12-31 +} {Tue Tuesday 03 2003 2 01 2} +test clock-10.16 {ISO week-based calendar 2003-W01-3} { + clock format 1041379200 -format {%a %A %g %G %u %V %w} -gmt true; # 2003-1-1 +} {Wed Wednesday 03 2003 3 01 3} +test clock-10.17 {ISO week-based calendar 2003-W01-7} { + clock format 1041724800 -format {%a %A %g %G %u %V %w} -gmt true; # 2003-1-5 +} {Sun Sunday 03 2003 7 01 0} +test clock-10.18 {ISO week-based calendar 2003-W02-1} { + clock format 1041811200 -format {%a %A %g %G %u %V %w} -gmt true; # 2003-1-6 +} {Mon Monday 03 2003 1 02 1} +test clock-10.19 {ISO week-based calendar 2003-W52-1} { + clock format 1072051200 -format {%a %A %g %G %u %V %w} -gmt true; # 2003-12-22 +} {Mon Monday 03 2003 1 52 1} +test clock-10.20 {ISO week-based calendar 2003-W52-7} { + clock format 1072569600 -format {%a %A %g %G %u %V %w} -gmt true; # 2003-12-28 +} {Sun Sunday 03 2003 7 52 0} +test clock-10.21 {ISO week-based calendar 2004-W01-1} { + clock format 1072656000 -format {%a %A %g %G %u %V %w} -gmt true; # 2003-12-29 +} {Mon Monday 04 2004 1 01 1} +test clock-10.22 {ISO week-based calendar 2004-W01-3} { + clock format 1072828800 -format {%a %A %g %G %u %V %w} -gmt true; # 2003-12-31 +} {Wed Wednesday 04 2004 3 01 3} +test clock-10.23 {ISO week-based calendar 2004-W01-4} { + clock format 1072915200 -format {%a %A %g %G %u %V %w} -gmt true; # 2004-1-1 +} {Thu Thursday 04 2004 4 01 4} +test clock-10.24 {ISO week-based calendar 2004-W01-7} { + clock format 1073174400 -format {%a %A %g %G %u %V %w} -gmt true; # 2004-1-4 +} {Sun Sunday 04 2004 7 01 0} +test clock-10.25 {ISO week-based calendar 2004-W02-1} { + clock format 1073260800 -format {%a %A %g %G %u %V %w} -gmt true; # 2004-1-5 +} {Mon Monday 04 2004 1 02 1} +test clock-10.26 {ISO week-based calendar 2004-W52-1} { + clock format 1103500800 -format {%a %A %g %G %u %V %w} -gmt true; # 2004-12-20 +} {Mon Monday 04 2004 1 52 1} +test clock-10.27 {ISO week-based calendar 2004-W52-7} { + clock format 1104019200 -format {%a %A %g %G %u %V %w} -gmt true; # 2004-12-26 +} {Sun Sunday 04 2004 7 52 0} +test clock-10.28 {ISO week-based calendar 2004-W53-1} { + clock format 1104105600 -format {%a %A %g %G %u %V %w} -gmt true; # 2004-12-27 +} {Mon Monday 04 2004 1 53 1} +test clock-10.29 {ISO week-based calendar 2004-W53-5} { + clock format 1104451200 -format {%a %A %g %G %u %V %w} -gmt true; # 2004-12-31 +} {Fri Friday 04 2004 5 53 5} +test clock-10.30 {ISO week-based calendar 2004-W53-6} { + clock format 1104537600 -format {%a %A %g %G %u %V %w} -gmt true; # 2005-1-1 +} {Sat Saturday 04 2004 6 53 6} +test clock-10.31 {ISO week-based calendar 2004-W53-7} { + clock format 1104624000 -format {%a %A %g %G %u %V %w} -gmt true; # 2005-1-2 +} {Sun Sunday 04 2004 7 53 0} +test clock-10.32 {ISO week-based calendar 2005-W01-1} { + clock format 1104710400 -format {%a %A %g %G %u %V %w} -gmt true; # 2005-1-3 +} {Mon Monday 05 2005 1 01 1} +test clock-10.33 {ISO week-based calendar 2005-W01-7} { + clock format 1105228800 -format {%a %A %g %G %u %V %w} -gmt true; # 2005-1-9 +} {Sun Sunday 05 2005 7 01 0} +test clock-10.34 {ISO week-based calendar 2005-W02-1} { + clock format 1105315200 -format {%a %A %g %G %u %V %w} -gmt true; # 2005-1-10 +} {Mon Monday 05 2005 1 02 1} +test clock-10.35 {ISO week-based calendar 2005-W52-1} { + clock format 1135555200 -format {%a %A %g %G %u %V %w} -gmt true; # 2005-12-26 +} {Mon Monday 05 2005 1 52 1} +test clock-10.36 {ISO week-based calendar 2005-W52-6} { + clock format 1135987200 -format {%a %A %g %G %u %V %w} -gmt true; # 2005-12-31 +} {Sat Saturday 05 2005 6 52 6} +test clock-10.37 {ISO week-based calendar 2005-W52-7} { + clock format 1136073600 -format {%a %A %g %G %u %V %w} -gmt true; # 2006-1-1 +} {Sun Sunday 05 2005 7 52 0} +test clock-10.38 {ISO week-based calendar 2006-W01-1} { + clock format 1136160000 -format {%a %A %g %G %u %V %w} -gmt true; # 2006-1-2 +} {Mon Monday 06 2006 1 01 1} +test clock-10.39 {ISO week-based calendar 2006-W01-7} { + clock format 1136678400 -format {%a %A %g %G %u %V %w} -gmt true; # 2006-1-8 +} {Sun Sunday 06 2006 7 01 0} +test clock-10.40 {ISO week-based calendar 2006-W02-1} { + clock format 1136764800 -format {%a %A %g %G %u %V %w} -gmt true; # 2006-1-9 +} {Mon Monday 06 2006 1 02 1} +test clock-10.41 {ISO week-based calendar 2009-W52-1} { + clock format 1261353600 -format {%a %A %g %G %u %V %w} -gmt true; # 2009-12-21 +} {Mon Monday 09 2009 1 52 1} +test clock-10.42 {ISO week-based calendar 2009-W52-7} { + clock format 1261872000 -format {%a %A %g %G %u %V %w} -gmt true; # 2009-12-27 +} {Sun Sunday 09 2009 7 52 0} +test clock-10.43 {ISO week-based calendar 2009-W53-1} { + clock format 1261958400 -format {%a %A %g %G %u %V %w} -gmt true; # 2009-12-28 +} {Mon Monday 09 2009 1 53 1} +test clock-10.44 {ISO week-based calendar 2009-W53-4} { + clock format 1262217600 -format {%a %A %g %G %u %V %w} -gmt true; # 2009-12-31 +} {Thu Thursday 09 2009 4 53 4} +test clock-10.45 {ISO week-based calendar 2009-W53-5} { + clock format 1262304000 -format {%a %A %g %G %u %V %w} -gmt true; # 2010-1-1 +} {Fri Friday 09 2009 5 53 5} +test clock-10.46 {ISO week-based calendar 2009-W53-7} { + clock format 1262476800 -format {%a %A %g %G %u %V %w} -gmt true; # 2010-1-3 +} {Sun Sunday 09 2009 7 53 0} +test clock-10.47 {ISO week-based calendar 2010-W01-1} { + clock format 1262563200 -format {%a %A %g %G %u %V %w} -gmt true; # 2010-1-4 +} {Mon Monday 10 2010 1 01 1} +test clock-10.48 {ISO week-based calendar 2010-W01-7} { + clock format 1263081600 -format {%a %A %g %G %u %V %w} -gmt true; # 2010-1-10 +} {Sun Sunday 10 2010 7 01 0} +test clock-10.49 {ISO week-based calendar 2010-W02-1} { + clock format 1263168000 -format {%a %A %g %G %u %V %w} -gmt true; # 2010-1-11 +} {Mon Monday 10 2010 1 02 1} + # cleanup ::tcltest::cleanupTests return -- cgit v0.12