From 4da76e0c6fc47da53fd84ffaf844f4abfefeade4 Mon Sep 17 00:00:00 2001 From: Jim Meyering Date: Mon, 8 Apr 1996 04:53:54 +0000 Subject: (mon_week_ISO): New function to implement new %V format. (sun_week): Make TM parameter `const'. (mon_week): Likewise. (mon_week): Rewrite to correctly implement %W format.. --- lib/strftime.c | 58 ++++++++++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 44 insertions(+), 14 deletions(-) (limited to 'lib') diff --git a/lib/strftime.c b/lib/strftime.c index 5cf5f0d17..2b8f3600d 100644 --- a/lib/strftime.c +++ b/lib/strftime.c @@ -67,6 +67,7 @@ %j day of year (001..366) %m month (01..12) %U week number of year with Sunday as first day of week (00..53) + %V FIXME %w day of week (0..6) %W week number of year with Monday as first day of week (00..53) %x locale's date representation (mm/dd/yy) @@ -233,38 +234,63 @@ add_num_tz (string, max, minutes_east) return length; } -/* Return the week in the year of the time in TM, with the weeks - starting on Sundays. */ +/* Implement %U. Return the week in the year of the time in TM, + with the weeks starting on Sundays. */ static int sun_week (tm) - struct tm *tm; + const struct tm *tm; { int dl; /* %U Week of the year (Sunday as the first day of the week) as a decimal - number [00-53]. All days in a new year preceding the first Sunday are + number [00-53]. All days in a new year preceding the first Sunday are considered to be in week 0. */ dl = tm->tm_yday - tm->tm_wday; return dl < 0 ? 0 : dl / 7 + 1; } -/* Return the week in the year of the time in TM, with the weeks - starting on Mondays. */ +/* Implement %V. Similar to mon_week (%W), but there is no 0'th week -- + they're numbered [01-53]. And if the week containing January 1 has + four or more days in the new year, then it is considered week 1; + otherwise, it is week 53 of the previous year, and the next week is + week 1. (See the ISO 8601: 1988 standard.) */ + +static int +mon_week_ISO (tm) + const struct tm *tm; +{ + int dl, n_days_before_first_monday; + int week_num; + + n_days_before_first_monday = (tm->tm_yday + 7 - tm->tm_wday + 1) % 7; + dl = tm->tm_yday - n_days_before_first_monday; + week_num = dl < 0 ? 0 : dl / 7 + 1; + if (n_days_before_first_monday >= 4) + { + week_num = (week_num + 1) % 54; + if (week_num == 0) + week_num = 1; + } + if (week_num == 0) + week_num = 53; + + return week_num; +} + +/* Implement %W. Return the week in the year of the time in TM, + with the weeks starting on Mondays. */ static int mon_week (tm) - struct tm *tm; + const struct tm *tm; { - int dl, wday; + int dl, n_days_before_first_monday; - if (tm->tm_wday == 0) - wday = 6; - else - wday = tm->tm_wday - 1; - dl = tm->tm_yday - wday; - return dl <= 0 ? 0 : dl / 7 + (dl % 7 != 0); + n_days_before_first_monday = (tm->tm_yday + 7 - tm->tm_wday + 1) % 7; + dl = tm->tm_yday - n_days_before_first_monday; + return dl < 0 ? 0 : dl / 7 + 1; } #if !defined(HAVE_TM_ZONE) && !defined(HAVE_TZNAME) @@ -499,6 +525,10 @@ strftime (string, max, format, tm) length += add_num2 (&string[length], sun_week (tm), max - length, pad); break; + case 'V': + length += add_num2 (&string[length], mon_week_ISO (tm), + max - length, pad); + break; case 'w': add_char (tm->tm_wday + '0'); break; -- cgit v1.2.3-70-g09d2