aboutsummaryrefslogtreecommitdiff
path: root/lib/libc
diff options
context:
space:
mode:
authorWolfgang Helbig <helbig@FreeBSD.org>1997-10-03 19:06:57 +0000
committerWolfgang Helbig <helbig@FreeBSD.org>1997-10-03 19:06:57 +0000
commitb9b51fb7313f84f2cd90ad276a5a4f66a83a704e (patch)
tree456dcf1463fe606bff4dcc8bea88c03e84da2c9c /lib/libc
parentab215c6703c3eea4c61c2457f7f31793de630d04 (diff)
downloadsrc-b9b51fb7313f84f2cd90ad276a5a4f66a83a704e.tar.gz
src-b9b51fb7313f84f2cd90ad276a5a4f66a83a704e.zip
Merged in better support of ISO 8601 from elsie.nci.nih.gov.
Added the conversion specifiers %g and %G, that are replaced by the year which contains the greater part of the week in question.
Notes
Notes: svn path=/head/; revision=30089
Diffstat (limited to 'lib/libc')
-rw-r--r--lib/libc/stdtime/strftime.350
-rw-r--r--lib/libc/stdtime/strftime.c130
2 files changed, 118 insertions, 62 deletions
diff --git a/lib/libc/stdtime/strftime.3 b/lib/libc/stdtime/strftime.3
index 7ce1b2475295..fe916a17eb85 100644
--- a/lib/libc/stdtime/strftime.3
+++ b/lib/libc/stdtime/strftime.3
@@ -35,7 +35,7 @@
.\"
.\" @(#)strftime.3 8.1 (Berkeley) 6/4/93
.\"
-.Dd June 4, 1993
+.Dd October 4, 1997
.Dt STRFTIME 3
.Os
.Sh NAME
@@ -113,6 +113,14 @@ representations.
.It Cm %e
is replaced by the day of month as a decimal number (1-31); single
digits are preceded by a blank.
+.It Cm \&%G
+is replaced by a year as a decimal number with century.
+This year is the one that contains the greater part of
+the week (Monday as the first day of the week).
+.It Cm %g
+is replaced by the same year as in
+.Dq Li %G ,
+but as a decimal number without century (00-99).
.It Cm \&%H
is replaced by the hour (24-hour clock) as a decimal number (00-23).
.It Cm %h
@@ -164,9 +172,10 @@ the week) as a decimal number (00-53).
is replaced by the weekday (Monday as the first day of the week)
as a decimal number (1-7).
.It Cm \&%V
-is replaced by the week number of the year (the first
-Monday as the first day of week 1) as a
-decimal number (01-53).
+is replaced by the week number of the year (Monday as the first day of
+the week) as a decimal number (01-53). If the week containing January
+1 has four or more days in the new year, then it is week 1; otherwise
+it is the last week of the previous year, and the next week is week 1.
.It Cm %v
is equivalent to
.Dq Li %e-%b-%Y .
@@ -205,9 +214,34 @@ The
.Fn strftime
function
conforms to
-.St -ansiC .
-The
-.Ql %s
-conversion specification is an extension.
+.St -ansiC
+with a lot of extensions including
+.Ql %C ,
+.Ql %D ,
+.Ql %E* ,
+.Ql %e ,
+.Ql %G ,
+.Ql %g ,
+.Ql %h ,
+.Ql %k ,
+.Ql %l ,
+.Ql %n ,
+.Ql %O* ,
+.Ql \&%R ,
+.Ql %r ,
+.Ql %s ,
+.Ql \&%T ,
+.Ql %t ,
+.Ql %u ,
+.Ql \&%V ,
+.Ql %+ .
+
+The peculiar week number and year occuring in the replacements of
+.Ql %G ,
+.Ql %g
+and
+.Ql \&%V
+are defined in ISO 8601: 1988.
+
.Sh BUGS
There is no conversion specification for the phase of the moon.
diff --git a/lib/libc/stdtime/strftime.c b/lib/libc/stdtime/strftime.c
index 126da8518167..893b784aaa23 100644
--- a/lib/libc/stdtime/strftime.c
+++ b/lib/libc/stdtime/strftime.c
@@ -17,7 +17,7 @@
#ifdef LIBC_RCS
static const char rcsid[] =
- "$Id: strftime.c,v 1.17 1997/02/22 15:03:19 peter Exp $";
+ "$Id: strftime.c,v 1.18 1997/08/09 15:43:53 joerg Exp $";
#endif
#ifndef lint
@@ -234,67 +234,89 @@ label:
pt = _conv((t->tm_wday == 0) ? 7 : t->tm_wday,
"%d", pt, ptlim);
continue;
- case 'V':
- /*
- ** From Arnold Robbins' strftime version 3.0:
- ** "the week number of the year (the first
- ** Monday as the first day of week 1) as a
- ** decimal number (01-53). The method for
- ** determining the week number is as specified
- ** by ISO 8601 (to wit: if the week 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 1)."
- ** (ado, 5/24/93)
- */
- /*
- ** XXX--If January 1 falls on a Friday,
- ** January 1-3 are part of week 53 of the
- ** previous year. By analogy, if January
- ** 1 falls on a Thursday, are December 29-31
- ** of the PREVIOUS year part of week 1???
- ** (ado 5/24/93)
- */
- /*
- ** You are understood not to expect this.
- */
+ case 'V': /* ISO 8601 week number */
+ case 'G': /* ISO 8601 year (four digits) */
+ case 'g': /* ISO 8601 year (two digits) */
+/*
+** From Arnold Robbins' strftime version 3.0: "the week number of the
+** year (the first Monday as the first day of week 1) as a decimal number
+** (01-53)."
+** (ado, 1993-05-24)
+**
+** From "http://www.ft.uni-erlangen.de/~mskuhn/iso-time.html" by Markus Kuhn:
+** "Week 01 of a year is per definition the first week which has the
+** Thursday in this year, which is equivalent to the week which contains
+** the fourth day of January. In other words, the first week of a new year
+** is the week which has the majority of its days in the new year. Week 01
+** might also contain days from the previous year and the week before week
+** 01 of a year is the last week (52 or 53) of the previous year even if
+** it contains days from the new year. A week starts with Monday (day 1)
+** and ends with Sunday (day 7). For example, the first week of the year
+** 1997 lasts from 1996-12-30 to 1997-01-05..."
+** (ado, 1996-01-02)
+*/
{
- int i;
+ int year;
+ int yday;
+ int wday;
+ int w;
- i = (t->tm_yday + 10 - (t->tm_wday ?
- (t->tm_wday - 1) : 6)) / 7;
- if (i == 0) {
+ year = t->tm_year + TM_YEAR_BASE;
+ yday = t->tm_yday;
+ wday = t->tm_wday;
+ for ( ; ; ) {
+ int len;
+ int bot;
+ int top;
+
+ len = isleap(year) ?
+ DAYSPERLYEAR :
+ DAYSPERNYEAR;
/*
- ** What day of the week does
- ** January 1 fall on?
+ ** What yday (-3 ... 3) does
+ ** the ISO year begin on?
*/
- i = t->tm_wday -
- (t->tm_yday - 1);
+ bot = ((yday + 11 - wday) %
+ DAYSPERWEEK) - 3;
/*
- ** Fri Jan 1: 53
- ** Sun Jan 1: 52
- ** Sat Jan 1: 53 if previous
- ** year a leap
- ** year, else 52
+ ** What yday does the NEXT
+ ** ISO year begin on?
*/
- if (i == TM_FRIDAY)
- i = 53;
- else if (i == TM_SUNDAY)
- i = 52;
- else i = isleap(t->tm_year +
- TM_YEAR_BASE) ?
- 53 : 52;
+ top = bot -
+ (len % DAYSPERWEEK);
+ if (top < -3)
+ top += DAYSPERWEEK;
+ top += len;
+ if (yday >= top) {
+ ++year;
+ w = 1;
+ break;
+ }
+ if (yday >= bot) {
+ w = 1 + ((yday - bot) /
+ DAYSPERWEEK);
+ break;
+ }
+ --year;
+ yday += isleap(year) ?
+ DAYSPERLYEAR :
+ DAYSPERNYEAR;
+ }
#ifdef XPG4_1994_04_09
- /*
- ** As of 4/9/94, though,
- ** XPG4 calls for 53
- ** unconditionally.
- */
- i = 53;
+ if ((w == 52
+ && t->tm_mon == TM_JANUARY)
+ || (w == 1
+ && t->tm_mon == TM_DECEMBER))
+ w = 53;
#endif /* defined XPG4_1994_04_09 */
- }
- pt = _conv(i, "%02d", pt, ptlim);
+ if (*format == 'V')
+ pt = _conv(w, "%02d",
+ pt, ptlim);
+ else if (*format == 'g') {
+ pt = _conv(year % 100, "%02d",
+ pt, ptlim);
+ } else pt = _conv(year, "%04d",
+ pt, ptlim);
}
continue;
case 'v':