View | Details | Raw Unified | Return to bug 137307 | Differences between
and this patch

Collapse All | Expand All

(-)new/strptime.c (-7 / +62 lines)
Lines 76-90 static char * _strptime(const char *, co Link Here
76
76
77
#define asizeof(a)	(sizeof (a) / sizeof ((a)[0]))
77
#define asizeof(a)	(sizeof (a) / sizeof ((a)[0]))
78
78
79
#define leapyear(y)	((y) % 4 == 0 && ((y) % 100 != 0 || (y) % 400 == 0))
80
81
/* Calculate the week day of the first day of a year.  Valid for
82
   the Gregorian calendar, which began Sept 14, 1752 in the UK
83
   and its colonies.  Ref:
84
   http://en.wikipedia.org/wiki/Calculating_the_day_of_the_week
85
   */
86
87
static int
88
first_wday_of(int year)
89
{
90
	return (((2 * (3 - (year / 100) % 4)) + (year % 100) +
91
		((year % 100) / 4) + (leapyear(year) ? 6 : 0) + 1) % 7);
92
}
93
79
static char *
94
static char *
80
_strptime(const char *buf, const char *fmt, struct tm *tm, int *GMTp)
95
_strptime(const char *buf, const char *fmt, struct tm *tm, int *GMTp)
81
{
96
{
82
	char	c;
97
	char	c;
83
	const char *ptr;
98
	const char *ptr;
84
	int	i,
99
	int	day_offset,
100
		i,
85
		len;
101
		len;
86
	int Ealternative, Oalternative;
102
	int Ealternative, Oalternative;
87
	struct lc_time_T *tptr = __get_current_time_locale();
103
	struct lc_time_T *tptr = __get_current_time_locale();
104
	static int start_of_month[2][13] = {
105
		{0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365},
106
		{0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366}};
88
107
89
	ptr = fmt;
108
	ptr = fmt;
90
	while (*ptr != 0) {
109
	while (*ptr != 0) {
Lines 154-159 label: Link Here
154
			Ealternative++;
173
			Ealternative++;
155
			goto label;
174
			goto label;
156
175
176
		case 'n':
177
		case 't':
178
			while (*buf != 0 && isspace ((unsigned char)*buf))
179
				buf++;
180
			break;
181
157
		case 'O':
182
		case 'O':
158
			if (Ealternative || Oalternative)
183
			if (Ealternative || Oalternative)
159
				break;
184
				break;
Lines 324-335 label: Link Here
324
349
325
		case 'U':
350
		case 'U':
326
		case 'W':
351
		case 'W':
327
			/*
352
			/* We expect that the year has already been
328
			 * XXX This is bogus, as we can not assume any valid
353
			   parsed.  */
329
			 * information present in the tm structure at this
330
			 * point to calculate a real value, so just check the
331
			 * range for now.
332
			 */
333
			if (!isdigit((unsigned char)*buf))
354
			if (!isdigit((unsigned char)*buf))
334
				return 0;
355
				return 0;
335
356
Lines 345-350 label: Link Here
345
			if (*buf != 0 && isspace((unsigned char)*buf))
366
			if (*buf != 0 && isspace((unsigned char)*buf))
346
				while (*ptr != 0 && !isspace((unsigned char)*ptr))
367
				while (*ptr != 0 && !isspace((unsigned char)*ptr))
347
					ptr++;
368
					ptr++;
369
370
			/* Week numbers are 1-origin.  So that we can always
371
			   return the date of a Sunday (or Monday), treat week
372
			   0 as week 1. */
373
374
			if (i == 0)
375
				i = 1;
376
377
			if (c == 'U')
378
				day_offset = 0;   /* Sunday */
379
			else day_offset = 1;   /* Monday */
380
381
			/* Set the date to the first Sunday (or Monday)
382
			   of the specified week of the year.  */
383
384
			tm->tm_yday = (7 - first_wday_of(tm->tm_year+1900) +
385
				day_offset) % 7 + (i-1) * 7;
386
			i = 0;
387
			while (tm->tm_yday >=
388
				start_of_month[leapyear(tm->tm_year+1900)][i])
389
			{
390
				i++;
391
			}
392
			if (i > 12)
393
			{
394
				i = 1;
395
				tm->tm_yday -=
396
					start_of_month[leapyear(tm->tm_year+1900)][12];
397
				tm->tm_year++;
398
			}
399
			tm->tm_mon = i - 1;
400
			tm->tm_mday = tm->tm_yday -
401
				start_of_month[leapyear(tm->tm_year+1900)][i - 1] + 1;
402
			tm->tm_wday = day_offset;
348
			break;
403
			break;
349
404
350
		case 'w':
405
		case 'w':
(-)new/t_first_wday.c (+61 lines)
Line 0 Link Here
1
/* Beginning of modification history */
2
/* Written 2009-07-30 by Paul Green. */
3
/* End of modification history */
4
5
/* Program to test the calculation of the first day of a year.
6
   */
7
8
#define _POSIX_C_SOURCE 200112L
9
#include <stdio.h>
10
11
static char *day_name[7] = { "Sunday", "Monday", "Tuesday",
12
     "Wednesday", "Thursday", "Friday", "Saturday"};
13
14
static int known_wday [12] = {4, 5, 6, 1, 2, 3, 4, 6, 0, 1, 2, 4};
15
16
/* Returns 1 if y is a leap year, 0 otherwise.  */
17
18
#define leapyear(y) ((y) % 4 == 0 && ((y) % 100 != 0 || (y) % 400 == 0))
19
20
/* Calculate the week day of the first day of a year.  Valid for
21
   the Gregorian calendar, which began Sept 14, 1752 in the UK
22
   and its colonies.  Ref:
23
   http://en.wikipedia.org/wiki/Calculating_the_day_of_the_week
24
   */
25
26
static int first_wday_of(int year)
27
{
28
     return (
29
               (2 * (3 - (year / 100) % 4))
30
             + (year % 100)
31
             + ((year % 100) / 4)
32
             + (leapyear(year) ? 6 : 0)
33
             + 1
34
            ) % 7;
35
}
36
37
int main (int argc, char **argv)
38
{
39
     int wday,year;
40
     int errors=0;
41
42
     for (year=1998; year<2010; year++)
43
     {
44
          wday = first_wday_of (year);
45
          if (wday != known_wday [year-1998])
46
          {
47
               printf ("Error calculating first day of %4d.\n", year);
48
               printf ("Expected: January %d.\n", known_wday [year-1998]);
49
               printf ("Got:      January %d.\n", wday);
50
               errors++;
51
          }
52
          else printf ("The first day of %4d is a %s (%d)\n", 
53
                    year, day_name [wday], wday);
54
     }
55
56
     if (errors)
57
          printf ("Test failed.\n");
58
     else printf ("Test passed.\n");
59
60
     return errors;
61
}
(-)new/t_strptime.c (+349 lines)
Line 0 Link Here
1
/* Beginning of modification history */
2
/* Written 09-07-27 by Paul Green. */
3
/* End of modification history */
4
5
#define _XOPEN_SOURCE 600
6
#pragma longmap_check, no_default_mapping, system_programming;
7
8
#include <stdio.h>
9
#include <stddef.h>
10
#include <string.h>
11
#include <sys/types.h>
12
#include "time.h"
13
14
static int failures = 0;
15
16
static void explain (char *title, char *fmt, char *src)
17
{
18
	printf ("Testing:  %s\n", title);
19
	printf ("Format:   %s\n", fmt);
20
	printf ("Source:   %s\n", src);
21
}
22
23
static void try1 (char *title, char *fmt, char *src, off_t off, int answer)
24
{
25
struct tm r;
26
int       value;
27
28
	explain (title, fmt, src);
29
	memset (&r, 0, sizeof (r));
30
	strptime (src, fmt, &r);
31
32
	value = * (int *) ((char *)&r + off);
33
34
	if (value == answer)
35
		printf ("Result:   %d (ok)\n", answer);
36
	else
37
	{
38
		printf ("Result:   %d instead of %d (bad)\n", value, answer);
39
		failures++;
40
	}
41
	printf ("\n");
42
}
43
44
/* Special test for the %c format string.  Try to convert
45
   "Mon Mday HH:MM:SS YYYY".  */
46
47
static void try2 (char *title, char *fmt, char *src)
48
{
49
struct tm r;
50
51
	explain (title, fmt, src);
52
	memset (&r, 0, sizeof (r));
53
	strptime (src, fmt, &r);
54
55
	if (r.tm_mon == 11 &&
56
	    r.tm_mday == 31 &&
57
	    r.tm_year == 109 &&
58
	    r.tm_hour == 23 &&
59
	    r.tm_min == 59 &&
60
	    r.tm_sec == 59)
61
		printf ("Result:   December 31 23:59:59 2009 (ok)\n");
62
	else
63
	{
64
		failures++;
65
		printf ("Result:   failed. %d/%d/%d %02d:%02d:%02d %2d %2d\n",
66
			r.tm_mon+1, r.tm_mday, r.tm_year+1900, r.tm_hour,
67
			r.tm_min, r.tm_sec, r.tm_wday, r.tm_yday);
68
	}
69
	printf ("\n");
70
}
71
72
/* Special test for the %D format string.  Try to convert
73
   "MM/DD/YY".  */
74
75
static void try3 (char *title, char *fmt, char *src)
76
{
77
struct tm r;
78
79
	explain (title, fmt, src);
80
	memset (&r, 0, sizeof (r));
81
	strptime (src, fmt, &r);
82
83
	if (r.tm_mon == 11 &&
84
	    r.tm_mday == 31 &&
85
	    r.tm_year == 109)
86
		printf ("Result:   12/31/2009 (ok)\n");
87
	else
88
	{
89
		failures++;
90
		printf ("Result:   failed. %02d/%02d/%4d\n",
91
			r.tm_mon+1, r.tm_mday, r.tm_year+1900);
92
	}
93
	printf ("\n");
94
}
95
96
/* Special test for the %r format string.  Try to convert
97
   "HH:MM:SS XM".  */
98
99
static void try4 (char *title, char *fmt, char *src)
100
{
101
struct tm r;
102
103
	explain (title, fmt, src);
104
	memset (&r, 0, sizeof (r));
105
	strptime (src, fmt, &r);
106
107
	if (r.tm_hour == 23 &&
108
	    r.tm_min == 59 &&
109
	    r.tm_sec == 59)
110
		printf ("Result:   11:59:59 pm (ok)\n");
111
	else
112
	{
113
		failures++;
114
		printf ("Result:   failed. %02d:%02d:%02d\n",
115
			r.tm_hour, r.tm_min, r.tm_sec);
116
	}
117
	printf ("\n");
118
}
119
120
/* Special test for the %R format string.  Try to convert
121
   "HH:MM".  */
122
123
static void try5 (char *title, char *fmt, char *src)
124
{
125
struct tm r;
126
127
	explain (title, fmt, src);
128
	memset (&r, 0, sizeof (r));
129
	strptime (src, fmt, &r);
130
131
	if (r.tm_hour == 23 &&
132
	    r.tm_min == 59)
133
		printf ("Result:   23:59 (ok)\n");
134
	else
135
	{
136
		failures++;
137
		printf ("Result:   failed. %02d:%02d\n",
138
			r.tm_hour, r.tm_min);
139
	}
140
	printf ("\n");
141
}
142
143
/* Special test for the %T format string.  Try to convert
144
   "HH:MM:SS".  */
145
146
static void try6 (char *title, char *fmt, char *src)
147
{
148
struct tm r;
149
150
	explain (title, fmt, src);
151
	memset (&r, 0, sizeof (r));
152
	strptime (src, fmt, &r);
153
154
	if (r.tm_hour == 23 &&
155
	    r.tm_min == 59 &&
156
	    r.tm_sec == 59)
157
		printf ("Result:   23:59:59 (ok)\n");
158
	else
159
	{
160
		failures++;
161
		printf ("Result:   failed. %02d:%02d:%02d\n",
162
			r.tm_hour, r.tm_min, r.tm_sec);
163
	}
164
	printf ("\n");
165
}
166
167
/* Special test for the %U format string.  Try to convert
168
   "2009 21", which is 5/31/2009 */
169
170
static void try7 (char *title, char *fmt, char *src)
171
{
172
struct tm r;
173
174
	explain (title, fmt, src);
175
	memset (&r, 0, sizeof (r));
176
	strptime (src, fmt, &r);
177
178
	if (r.tm_mon == 4 &&
179
	    r.tm_mday == 31 &&
180
	    r.tm_year == 109 &&
181
	    r.tm_wday == 0 &&
182
	    r.tm_yday == 151)
183
		printf ("Result:   Sunday May 31 2009, yday 151 [week 21] (ok)\n");
184
	else
185
	{
186
		failures++;
187
		printf ("Result:   failed. %02d/%02d/%04d wday=%d yday=%d\n",
188
			r.tm_mon+1, r.tm_mday, r.tm_year+1900, r.tm_wday, r.tm_yday);
189
		printf ("Expected          05/31/2009 wday=0 yday=151\n");
190
	}
191
	printf ("\n");
192
}
193
194
/* Special test for the %W format string.  Try to convert
195
   "2009 21", which is 6/1/2009 */
196
197
static void try8 (char *title, char *fmt, char *src)
198
{
199
struct tm r;
200
201
	explain (title, fmt, src);
202
	memset (&r, 0, sizeof (r));
203
	strptime (src, fmt, &r);
204
205
	if (r.tm_mon == 5 &&
206
	    r.tm_mday == 1 &&
207
	    r.tm_year == 109 &&
208
	    r.tm_wday == 1 &&
209
	    r.tm_yday == 152)
210
		printf ("Result:   Monday June 1 2009, yday 152 [week 21] (ok)\n");
211
	else
212
	{
213
		failures++;
214
		printf ("Result:   failed. %02d/%02d/%04d wday=%d yday=%d\n",
215
			r.tm_mon+1, r.tm_mday, r.tm_year+1900, r.tm_wday, r.tm_yday);
216
		printf ("Expected:         06/01/2009 wday=1 yday=152\n");
217
	}
218
	printf ("\n");
219
}
220
221
/* Special test for the %U format string.  Try to convert
222
   a range of values. */
223
224
static void tryU (char *title, char *fmt, char *range)
225
{
226
/* automatic */
227
228
int mon, mday, w, yday, year, yr;
229
char *p;
230
char src[32];
231
struct tm r;
232
233
/* static */
234
235
/* The date in January of the first Sunday, for 1998-2004. */
236
static int first_sunday [7] = {4, 3, 2, 7, 6, 5, 4};
237
238
/* The month*100 + the date of Sunday, for 1998-2004. */
239
static int known_answer [7][54] = {
240
	{0,104,111,118,125,201,208,215,222,301,308,315,322,329,405,412,419,426,503,510,517,524,531,607,614,621,628,705,712,719,726,802,809,816,823,830,906,913,920,927,1004,1011,1018,1025,1101,1108,1115,1122,1129,1206,1213,1220,1227,103},  /* 1998 */
241
	{0,103,110,117,124,131,207,214,221,228,307,314,321,328,404,411,418,425,502,509,516,523,530,606,613,620,627,704,711,718,725,801,808,815,822,829,905,912,919,926,1003,1010,1017,1024,1031,1107,1114,1121,1128,1205,1212,1219,1226,102},  /* 1999 */
242
	{0,102,109,116,123,130,206,213,220,227,305,312,319,326,402,409,416,423,430,507,514,521,528,604,611,618,625,702,709,716,723,730,806,813,820,827,903,910,917,924,1001,1008,1015,1022,1029,1105,1112,1119,1126,1203,1210,1217,1224,1231}, /* 2000 */
243
	{0,107,114,121,128,204,211,218,225,304,311,318,325,401,408,415,422,429,506,513,520,527,603,610,617,624,701,708,715,722,729,805,812,819,826,902,909,916,923,930,1007,1014,1021,1028,1104,1111,1118,1125,1202,1209,1216,1223,1230,106},  /* 2001 */
244
	{0,106,113,120,127,203,210,217,224,303,310,317,324,331,407,414,421,428,505,512,519,526,602,609,616,623,630,707,714,721,728,804,811,818,825,901,908,915,922,929,1006,1013,1020,1027,1103,1110,1117,1124,1201,1208,1215,1222,1229,105},  /* 2002 */
245
	{0,105,112,119,126,202,209,216,223,302,309,316,323,330,406,413,420,427,504,511,518,525,601,608,615,622,629,706,713,720,727,803,810,817,824,831,907,914,921,928,1005,1012,1019,1026,1102,1109,1116,1123,1130,1207,1214,1221,1228,104},  /* 2003 */
246
	{0,104,111,118,125,201,208,215,222,229,307,314,321,328,404,411,418,425,502,509,516,523,530,606,613,620,627,704,711,718,725,801,808,815,822,829,905,912,919,926,1003,1010,1017,1024,1031,1107,1114,1121,1128,1205,1212,1219,1226,102}}; /* 2004 */
247
248
/* execution */
249
250
	explain (title, fmt, range);
251
	memset (&r, 0, sizeof (r));
252
253
	for (year=1998; year<2005; year++)
254
	{
255
		mday = first_sunday[year-1998];
256
		yday = mday;
257
		printf ("The first Sunday of %4d is Jan %d.\n", year, mday);
258
259
		for (w=1; w<54; w++)
260
		{
261
			sprintf (src, "%4d %d", year, w);
262
			p = strptime (src, fmt, &r);
263
			mon = (known_answer[year-1998][w] / 100) - 1;
264
			mday = (known_answer[year-1998][w] % 100);
265
266
			if (w == 53 && mon == 0)
267
			{
268
				yr = year + 1;
269
				yday = mday;
270
			}
271
			else yr = year;
272
273
			if (p == NULL ||
274
			    r.tm_mon  != mon ||
275
			    r.tm_mday != mday ||
276
			    r.tm_year != yr - 1900 ||
277
			    r.tm_wday != 0 ||
278
			    r.tm_yday != yday)
279
			{
280
				failures++;
281
				printf ("%4d week %d failed.\n", year, w);
282
				printf ("   got:      %02d/%02d/%04d wday=%d yday=%d\n",
283
					r.tm_mon+1, r.tm_mday, r.tm_year+1900, r.tm_wday, r.tm_yday);
284
				printf ("   expected: %02d/%02d/%04d wday=%d yday=%d\n",
285
					mon+1, mday, yr, 0, yday);
286
				printf ("\n");
287
			}
288
			yday += 7;
289
		}
290
	}
291
	printf ("\n");
292
}
293
294
/* Special test for the %W format string.  */
295
296
int main (int argc, char **argv)
297
{
298
struct tm t;
299
300
     t.tm_sec = 59;
301
     t.tm_min = 59;
302
     t.tm_hour = 23;
303
     t.tm_mday = 31;
304
     t.tm_mon = 12;
305
     t.tm_year = 2009;
306
     t.tm_wday = 6;
307
     t.tm_yday = 364;
308
     t.tm_isdst = 0;
309
310
     try1 ("Day of the week", "%a", "Sat",      offsetof (struct tm, tm_wday), 6);
311
     try1 ("Day of the week", "%A", "Saturday", offsetof (struct tm, tm_wday), 6);
312
     try1 ("Month name",      "%b", "Dec",      offsetof (struct tm, tm_mon), 11);
313
     try1 ("Month name",      "%B", "December", offsetof (struct tm, tm_mon), 11);
314
     try2 ("Date and time",   "%c", "December 31 23:59:59 2009");
315
     try1 ("Century",         "%C", "2009",     offsetof (struct tm, tm_year), 100);
316
     try1 ("Date of month",   "%d", "31",       offsetof (struct tm, tm_mday), 31);
317
     try3 ("MM/DD/YY",        "%D", "12/31/09");
318
     /* skip E codes */
319
     /* skip O codes */
320
     try1 ("Date of month",   "%e", "31",       offsetof (struct tm, tm_mday), 31);
321
     try1 ("Month name",      "%h", "Dec",      offsetof (struct tm, tm_mon), 11);
322
     try1 ("Hours, 24-hr",    "%H", "23",       offsetof (struct tm, tm_hour), 23);
323
     try1 ("Hours, 12-hr",    "%I", "12",       offsetof (struct tm, tm_hour), 12);
324
     try1 ("Day of year",     "%j", "365",      offsetof (struct tm, tm_yday), 364);
325
     try1 ("Month number",    "%m", "12",       offsetof (struct tm, tm_mon), 11);
326
     try1 ("Minute number",   "%M", "59",       offsetof (struct tm, tm_min), 59);
327
     try1 ("AM/PM 12-hr",     "%I %p", "11 AM", offsetof (struct tm, tm_hour), 11);
328
     try1 ("AM/PM 12-hr",     "%I %p", "11 PM", offsetof (struct tm, tm_hour), 23);
329
     try1 ("AM/PM 24-hr",     "%H", "11",       offsetof (struct tm, tm_hour), 11);
330
     try1 ("AM/PM 24-hr",     "%H", "23",       offsetof (struct tm, tm_hour), 23);
331
     try4 ("Time of day H:M:S XM", "%r", "11:59:59 pm");
332
     try5 ("Time of day H:M", "%R", "23:59");
333
     try1 ("Second number",   "%S", "59",       offsetof (struct tm, tm_sec), 59);
334
     try6 ("Time of day H:M:S", "%T", "23:59:59");
335
     try7 ("Week number Sun=0", "%Y %U", "2009 22");
336
     try1 ("Week day number", "%w", "4",        offsetof (struct tm, tm_wday), 4);
337
     try8 ("Week number Mon=0", "%Y %W", "2009 22");
338
     try1 ("Year in century",  "%y",  "9",      offsetof (struct tm, tm_year), 109);
339
     try1 ("Year in century",  "%Y",  "2009",   offsetof (struct tm, tm_year), 109);
340
341
     tryU ("U conversion", "%Y %U", "range");
342
343
     if (failures)
344
          printf ("%d tests failed.\n", failures);
345
     else printf ("All tests passed.\n");
346
347
     return failures;
348
}
349

Return to bug 137307