changeset 582:3ec26150a8d6

(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..
author Jim Meyering <jim@meyering.net>
date Mon, 08 Apr 1996 04:53:54 +0000
parents 7be335c70443
children 3647a9e59ad1
files lib/strftime.c
diffstat 1 files changed, 44 insertions(+), 14 deletions(-) [+]
line wrap: on
line diff
--- a/lib/strftime.c	Fri Apr 05 23:33:09 1996 +0000
+++ b/lib/strftime.c	Mon Apr 08 04:53:54 1996 +0000
@@ -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 @@
   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 @@
 	      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;