summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKevin B Kenny <kennykb@acm.org>2004-05-18 21:52:56 (GMT)
committerKevin B Kenny <kennykb@acm.org>2004-05-18 21:52:56 (GMT)
commit9952f1458ffdf3f22b1013dab019fb273dff357f (patch)
tree68fc172017b9d4cf65f0d772cfaada0f085f643c
parent796e34e6aaf5f3b99f1c0e9d7906567eeb2ad087 (diff)
downloadtcl-9952f1458ffdf3f22b1013dab019fb273dff357f.zip
tcl-9952f1458ffdf3f22b1013dab019fb273dff357f.tar.gz
tcl-9952f1458ffdf3f22b1013dab019fb273dff357f.tar.bz2
* 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]
-rw-r--r--ChangeLog8
-rw-r--r--compat/strftime.c98
-rw-r--r--doc/clock.n8
-rw-r--r--tests/clock.test150
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 <kennykb@acm.org>
+
+ * 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 <kennykb.@acm.org>
* 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 <time.h>
@@ -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