1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* This Source Code Form is subject to the terms of the Mozilla Public
3 * License, v. 2.0. If a copy of the MPL was not distributed with this
4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
8 * description: test time and date routines
10 /***********************************************************************
12 ***********************************************************************/
13 /* Used to get the command line option */
25 PRBool debug_mode
= PR_FALSE
;
27 static char *dayOfWeek
[] =
28 { "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "???" };
29 static char *month
[] =
30 { "Jan", "Feb", "Mar", "Apr", "May", "Jun",
31 "Jul", "Aug", "Sep", "Oct", "Nov", "Dec", "???" };
33 static void PrintExplodedTime(const PRExplodedTime
*et
) {
35 PRInt32 hourOffset
, minOffset
;
38 /* Print day of the week, month, day, hour, minute, and second */
39 if (debug_mode
) printf("%s %s %ld %02ld:%02ld:%02ld ",
40 dayOfWeek
[et
->tm_wday
], month
[et
->tm_month
], et
->tm_mday
,
41 et
->tm_hour
, et
->tm_min
, et
->tm_sec
);
44 totalOffset
= et
->tm_params
.tp_gmt_offset
+ et
->tm_params
.tp_dst_offset
;
45 if (totalOffset
== 0) {
46 if (debug_mode
) printf("UTC ");
49 if (totalOffset
< 0) {
50 totalOffset
= -totalOffset
;
53 hourOffset
= totalOffset
/ 3600;
54 minOffset
= (totalOffset
% 3600) / 60;
56 printf("%s%02ld%02ld ", sign
, hourOffset
, minOffset
);
60 if (debug_mode
) printf("%hd", et
->tm_year
);
63 static int ExplodedTimeIsEqual(const PRExplodedTime
*et1
,
64 const PRExplodedTime
*et2
)
66 if (et1
->tm_usec
== et2
->tm_usec
&&
67 et1
->tm_sec
== et2
->tm_sec
&&
68 et1
->tm_min
== et2
->tm_min
&&
69 et1
->tm_hour
== et2
->tm_hour
&&
70 et1
->tm_mday
== et2
->tm_mday
&&
71 et1
->tm_month
== et2
->tm_month
&&
72 et1
->tm_year
== et2
->tm_year
&&
73 et1
->tm_wday
== et2
->tm_wday
&&
74 et1
->tm_yday
== et2
->tm_yday
&&
75 et1
->tm_params
.tp_gmt_offset
== et2
->tm_params
.tp_gmt_offset
&&
76 et1
->tm_params
.tp_dst_offset
== et2
->tm_params
.tp_dst_offset
) {
84 testParseTimeString(PRTime t
)
91 PRInt32 hourOffset
, minOffset
;
95 /* Truncate the microsecond part of PRTime */
96 LL_I2L(usec_per_sec
, PR_USEC_PER_SEC
);
97 LL_DIV(t
, t
, usec_per_sec
);
98 LL_MUL(t
, t
, usec_per_sec
);
100 PR_ExplodeTime(t
, PR_LocalTimeParameters
, &et
);
102 /* Print day of the week, month, day, hour, minute, and second */
103 PR_snprintf(timeString
, 128, "%s %s %ld %02ld:%02ld:%02ld ",
104 dayOfWeek
[et
.tm_wday
], month
[et
.tm_month
], et
.tm_mday
,
105 et
.tm_hour
, et
.tm_min
, et
.tm_sec
);
106 /* Print time zone */
107 totalOffset
= et
.tm_params
.tp_gmt_offset
+ et
.tm_params
.tp_dst_offset
;
108 if (totalOffset
== 0) {
109 strcat(timeString
, "GMT "); /* I wanted to use "UTC" here, but
110 * PR_ParseTimeString doesn't
111 * understand "UTC". */
114 if (totalOffset
< 0) {
115 totalOffset
= -totalOffset
;
118 hourOffset
= totalOffset
/ 3600;
119 minOffset
= (totalOffset
% 3600) / 60;
120 PR_snprintf(buf
, 128, "%s%02ld%02ld ", sign
, hourOffset
, minOffset
);
121 strcat(timeString
, buf
);
124 PR_snprintf(buf
, 128, "%hd", et
.tm_year
);
125 strcat(timeString
, buf
);
127 if (PR_ParseTimeString(timeString
, PR_FALSE
, &t2
) == PR_FAILURE
) {
128 fprintf(stderr
, "PR_ParseTimeString() failed\n");
132 fprintf(stderr
, "PR_ParseTimeString() incorrect\n");
133 PR_snprintf(buf
, 128, "t is %lld, t2 is %lld, time string is %s\n",
135 fprintf(stderr
, "%s\n", buf
);
140 int main(int argc
, char** argv
)
142 /* The command line argument: -d is used to determine if the test is being run
143 in debug mode. The regress tool requires only one line output:PASS or FAIL.
144 All of the printfs associated with this test has been handled with a if (debug_mode)
152 opt
= PL_CreateOptState(argc
, argv
, "d");
153 while (PL_OPT_EOL
!= (os
= PL_GetNextOpt(opt
)))
155 if (PL_OPT_BAD
== os
) continue;
158 case 'd': /* debug mode */
159 debug_mode
= PR_TRUE
;
165 PL_DestroyOptState(opt
);
169 PR_Init(PR_USER_THREAD
, PR_PRIORITY_NORMAL
, 0);
171 /* Testing zero PRTime (the epoch) */
177 if (debug_mode
) printf("The NSPR epoch is:\n");
178 PR_ExplodeTime(t
, PR_LocalTimeParameters
, &et
);
179 PrintExplodedTime(&et
);
180 if (debug_mode
) printf("\n");
181 PR_ExplodeTime(t
, PR_GMTParameters
, &et
);
182 PrintExplodedTime(&et
);
183 if (debug_mode
) printf("\n\n");
184 testParseTimeString(t
);
188 *************************************************************
190 ** Testing PR_Now(), PR_ExplodeTime, and PR_ImplodeTime
191 ** on the current time
193 *************************************************************
201 printf("*********************************************\n");
203 printf("** Testing PR_Now(), PR_ExplodeTime, and **\n");
204 printf("** PR_ImplodeTime on the current time **\n");
206 printf("*********************************************\n\n");
210 /* First try converting to UTC */
212 PR_ExplodeTime(t1
, PR_GMTParameters
, &et
);
213 if (et
.tm_params
.tp_gmt_offset
|| et
.tm_params
.tp_dst_offset
) {
214 if (debug_mode
) printf("ERROR: UTC has nonzero gmt or dst offset.\n");
215 else failed_already
=1;
218 if (debug_mode
) printf("Current UTC is ");
219 PrintExplodedTime(&et
);
220 if (debug_mode
) printf("\n");
222 t2
= PR_ImplodeTime(&et
);
224 if (debug_mode
) printf("ERROR: Explode and implode are NOT inverse.\n");
225 else printf("FAIL\n");
229 /* Next, try converting to local (US Pacific) time */
231 PR_ExplodeTime(t1
, PR_LocalTimeParameters
, &et
);
232 if (debug_mode
) printf("Current local time is ");
233 PrintExplodedTime(&et
);
234 if (debug_mode
) printf("\n");
235 if (debug_mode
) printf("GMT offset is %ld, DST offset is %ld\n",
236 et
.tm_params
.tp_gmt_offset
, et
.tm_params
.tp_dst_offset
);
237 t2
= PR_ImplodeTime(&et
);
239 if (debug_mode
) printf("ERROR: Explode and implode are NOT inverse.\n");
243 if (debug_mode
) printf("Please examine the results\n");
244 testParseTimeString(t1
);
249 *******************************************
251 ** Testing PR_NormalizeTime()
253 *******************************************
256 /* July 4, 2001 is Wednesday */
262 printf("**********************************\n");
264 printf("** Testing PR_NormalizeTime() **\n");
266 printf("**********************************\n\n");
275 et
.tm_params
= PR_GMTParameters(&et
);
277 PR_NormalizeTime(&et
, PR_GMTParameters
);
279 if (debug_mode
) printf("July 4, 2001 is %s.\n", dayOfWeek
[et
.tm_wday
]);
280 if (et
.tm_wday
== 3) {
281 if (debug_mode
) printf("PASS\n");
283 if (debug_mode
) printf("ERROR: It should be Wednesday\n");
284 else failed_already
=1;
287 testParseTimeString(PR_ImplodeTime(&et
));
289 /* June 12, 1997 23:00 PST == June 13, 1997 00:00 PDT */
297 et
.tm_params
.tp_gmt_offset
= -8 * 3600;
298 et
.tm_params
.tp_dst_offset
= 0;
300 PR_NormalizeTime(&et
, PR_USPacificTimeParameters
);
303 printf("Thu Jun 12, 1997 23:00:00 PST is ");
305 PrintExplodedTime(&et
);
306 if (debug_mode
) printf(".\n");
307 if (et
.tm_wday
== 5) {
308 if (debug_mode
) printf("PASS\n");
310 if (debug_mode
) printf("ERROR: It should be Friday\n");
311 else failed_already
=1;
314 testParseTimeString(PR_ImplodeTime(&et
));
316 /* Feb 14, 1997 00:00:00 PDT == Feb 13, 1997 23:00:00 PST */
324 et
.tm_params
.tp_gmt_offset
= -8 * 3600;
325 et
.tm_params
.tp_dst_offset
= 3600;
327 PR_NormalizeTime(&et
, PR_USPacificTimeParameters
);
330 printf("Fri Feb 14, 1997 00:00:00 PDT is ");
332 PrintExplodedTime(&et
);
333 if (debug_mode
) printf(".\n");
334 if (et
.tm_wday
== 4) {
335 if (debug_mode
) printf("PASS\n");
337 if (debug_mode
) printf("ERROR: It should be Thursday\n");
338 else failed_already
=1;
341 testParseTimeString(PR_ImplodeTime(&et
));
343 /* What time is Nov. 7, 1996, 18:29:23 PDT? */
345 et
.tm_month
= 11 - 1;
351 et
.tm_params
.tp_gmt_offset
= -8 * 3600; /* PDT */
352 et
.tm_params
.tp_dst_offset
= 3600;
354 PR_NormalizeTime(&et
, PR_LocalTimeParameters
);
355 if (debug_mode
) printf("Nov 7 18:29:23 PDT 1996 is ");
356 PrintExplodedTime(&et
);
357 if (debug_mode
) printf(".\n");
358 testParseTimeString(PR_ImplodeTime(&et
));
360 /* What time is Oct. 7, 1995, 18:29:23 PST? */
362 et
.tm_month
= 10 - 1;
367 et
.tm_params
.tp_gmt_offset
= -8 * 3600; /* PST */
368 et
.tm_params
.tp_dst_offset
= 0;
370 PR_NormalizeTime(&et
, PR_LocalTimeParameters
);
371 if (debug_mode
) printf("Oct 7 18:29:23 PST 1995 is ");
372 PrintExplodedTime(&et
);
373 if (debug_mode
) printf(".\n");
374 testParseTimeString(PR_ImplodeTime(&et
));
376 if (debug_mode
) printf("Please examine the results\n");
380 **************************************************************
382 ** Testing range of years
384 **************************************************************
388 PRExplodedTime et1
, et2
;
394 printf("***************************************\n");
396 printf("** Testing range of years **\n");
398 printf("***************************************\n\n");
400 /* April 4, 1917 GMT */
406 et1
.tm_month
= 4 - 1;
408 et1
.tm_params
= PR_GMTParameters(&et1
);
409 PR_NormalizeTime(&et1
, PR_LocalTimeParameters
);
410 secs
= PR_ImplodeTime(&et1
);
411 if (LL_GE_ZERO(secs
)) {
413 printf("ERROR: April 4, 1917 GMT returns a nonnegative second count\n");
417 PR_ExplodeTime(secs
, PR_LocalTimeParameters
, &et2
);
418 if (!ExplodedTimeIsEqual(&et1
, &et2
)) {
420 printf("ERROR: PR_ImplodeTime and PR_ExplodeTime are not inverse for April 4, 1917 GMT\n");
424 ttt
= PR_ImplodeTime(&et1
);
425 testParseTimeString( ttt
);
427 if (debug_mode
) printf("Test passed for April 4, 1917\n");
435 et1
.tm_month
= 7 - 1;
437 et1
.tm_params
= PR_GMTParameters(&et1
);
438 PR_NormalizeTime(&et1
, PR_LocalTimeParameters
);
439 secs
= PR_ImplodeTime(&et1
);
440 if (!LL_GE_ZERO(secs
)) {
442 printf("ERROR: July 4, 2050 GMT returns a negative second count\n");
446 PR_ExplodeTime(secs
, PR_LocalTimeParameters
, &et2
);
447 if (!ExplodedTimeIsEqual(&et1
, &et2
)) {
449 printf("ERROR: PR_ImplodeTime and PR_ExplodeTime are not inverse for July 4, 2050 GMT\n");
453 testParseTimeString(PR_ImplodeTime(&et1
));
455 if (debug_mode
) printf("Test passed for July 4, 2050\n");
460 **************************************************************
464 ** Go through four years, starting from
465 ** 00:00:00 PST Jan. 1, 2005, incrementing
468 **************************************************************
472 PRExplodedTime et
, et1
, et2
;
473 PRInt64 usecPer10Min
;
480 printf("*******************************************************\n");
482 printf("** Stress test Pacific Time **\n");
483 printf("** Starting from midnight Jan. 1, 2005 PST, **\n");
484 printf("** going through four years in 10-minute increment **\n");
486 printf("*******************************************************\n\n");
488 LL_I2L(usecPer10Min
, 600000000L);
490 /* 00:00:00 PST Jan. 1, 2005 */
498 et
.tm_params
.tp_gmt_offset
= -8 * 3600;
499 et
.tm_params
.tp_dst_offset
= 0;
500 usecs
= PR_ImplodeTime(&et
);
502 for (day
= 0; day
< 4 * 365 + 1; day
++) {
503 for (hour
= 0; hour
< 24; hour
++) {
504 for (min
= 0; min
< 60; min
+= 10) {
505 LL_ADD(usecs
, usecs
, usecPer10Min
);
506 PR_ExplodeTime(usecs
, PR_USPacificTimeParameters
, &et1
);
509 et2
.tm_usec
+= 600000000L;
510 PR_NormalizeTime(&et2
, PR_USPacificTimeParameters
);
512 if (!ExplodedTimeIsEqual(&et1
, &et2
)) {
513 printf("ERROR: componentwise comparison failed\n");
514 PrintExplodedTime(&et1
);
516 PrintExplodedTime(&et2
);
522 if (LL_NE(usecs
, PR_ImplodeTime(&et1
))) {
523 printf("ERROR: PR_ExplodeTime and PR_ImplodeTime are not inverse\n");
524 PrintExplodedTime(&et1
);
529 testParseTimeString(usecs
);
531 if (!dstInEffect
&& et1
.tm_params
.tp_dst_offset
) {
534 printf("DST changeover from ");
535 PrintExplodedTime(&et
);
537 PrintExplodedTime(&et1
);
540 } else if (dstInEffect
&& !et1
.tm_params
.tp_dst_offset
) {
543 printf("DST changeover from ");
544 PrintExplodedTime(&et
);
546 PrintExplodedTime(&et1
);
555 if (debug_mode
) printf("Test passed\n");
559 /* Same stress test, but with PR_LocalTimeParameters */
562 PRExplodedTime et
, et1
, et2
;
563 PRInt64 usecPer10Min
;
570 printf("*******************************************************\n");
572 printf("** Stress test Local Time **\n");
573 printf("** Starting from midnight Jan. 1, 2005 PST, **\n");
574 printf("** going through four years in 10-minute increment **\n");
576 printf("*******************************************************\n\n");
579 LL_I2L(usecPer10Min
, 600000000L);
581 /* 00:00:00 PST Jan. 1, 2005 */
589 et
.tm_params
.tp_gmt_offset
= -8 * 3600;
590 et
.tm_params
.tp_dst_offset
= 0;
591 usecs
= PR_ImplodeTime(&et
);
593 for (day
= 0; day
< 4 * 365 + 1; day
++) {
594 for (hour
= 0; hour
< 24; hour
++) {
595 for (min
= 0; min
< 60; min
+= 10) {
596 LL_ADD(usecs
, usecs
, usecPer10Min
);
597 PR_ExplodeTime(usecs
, PR_LocalTimeParameters
, &et1
);
600 et2
.tm_usec
+= 600000000L;
601 PR_NormalizeTime(&et2
, PR_LocalTimeParameters
);
603 if (!ExplodedTimeIsEqual(&et1
, &et2
)) {
604 printf("ERROR: componentwise comparison failed\n");
605 PrintExplodedTime(&et1
);
607 PrintExplodedTime(&et2
);
612 if (LL_NE(usecs
, PR_ImplodeTime(&et1
))) {
613 printf("ERROR: PR_ExplodeTime and PR_ImplodeTime are not inverse\n");
614 PrintExplodedTime(&et1
);
619 testParseTimeString(usecs
);
621 if (!dstInEffect
&& et1
.tm_params
.tp_dst_offset
) {
624 printf("DST changeover from ");
625 PrintExplodedTime(&et
);
627 PrintExplodedTime(&et1
);
630 } else if (dstInEffect
&& !et1
.tm_params
.tp_dst_offset
) {
633 printf("DST changeover from ");
634 PrintExplodedTime(&et
);
636 PrintExplodedTime(&et1
);
645 if (debug_mode
) printf("Test passed\n");
648 /* Same stress test, but with PR_LocalTimeParameters and going backward */
651 PRExplodedTime et
, et1
, et2
;
652 PRInt64 usecPer10Min
;
659 printf("*******************************************************\n");
661 printf("** Stress test Local Time **\n");
662 printf("** Starting from midnight Jan. 1, 2009 PST, **\n");
663 printf("** going back four years in 10-minute increment **\n");
665 printf("*******************************************************\n\n");
668 LL_I2L(usecPer10Min
, 600000000L);
670 /* 00:00:00 PST Jan. 1, 2009 */
678 et
.tm_params
.tp_gmt_offset
= -8 * 3600;
679 et
.tm_params
.tp_dst_offset
= 0;
680 usecs
= PR_ImplodeTime(&et
);
682 for (day
= 0; day
< 4 * 365 + 1; day
++) {
683 for (hour
= 0; hour
< 24; hour
++) {
684 for (min
= 0; min
< 60; min
+= 10) {
685 LL_SUB(usecs
, usecs
, usecPer10Min
);
686 PR_ExplodeTime(usecs
, PR_LocalTimeParameters
, &et1
);
689 et2
.tm_usec
-= 600000000L;
690 PR_NormalizeTime(&et2
, PR_LocalTimeParameters
);
692 if (!ExplodedTimeIsEqual(&et1
, &et2
)) {
693 printf("ERROR: componentwise comparison failed\n");
694 PrintExplodedTime(&et1
);
696 PrintExplodedTime(&et2
);
701 if (LL_NE(usecs
, PR_ImplodeTime(&et1
))) {
702 printf("ERROR: PR_ExplodeTime and PR_ImplodeTime are not inverse\n");
703 PrintExplodedTime(&et1
);
708 testParseTimeString(usecs
);
710 if (!dstInEffect
&& et1
.tm_params
.tp_dst_offset
) {
713 printf("DST changeover from ");
714 PrintExplodedTime(&et
);
716 PrintExplodedTime(&et1
);
719 } else if (dstInEffect
&& !et1
.tm_params
.tp_dst_offset
) {
722 printf("DST changeover from ");
723 PrintExplodedTime(&et
);
725 PrintExplodedTime(&et1
);
736 if (failed_already
) return 1;