xref: /haiku/src/tests/system/libroot/os/ParseDateTest.cpp (revision 323b65468e5836bb27a5e373b14027d902349437)
1 /*
2  * Copyright 2003-2009, Axel Dörfler, axeld@pinc-software.de.
3  * Distributed under the terms of the MIT License.
4  */
5 
6 
7 #include <SupportDefs.h>
8 #include <parsedate.h>
9 
10 #include <stdio.h>
11 #include <stdlib.h>
12 
13 
14 #define ABSOLUTE		0
15 #define UNKNOWN			0
16 #define DAY_RELATIVE	PARSEDATE_RELATIVE_TIME
17 #define MINUTE_RELATIVE	(PARSEDATE_RELATIVE_TIME \
18 	| PARSEDATE_MINUTE_RELATIVE_TIME)
19 #define INVALID			PARSEDATE_INVALID_DATE
20 
21 
22 const char*
23 parsedate_flags_to_string(time_t result, int flags)
24 {
25 	if (result == -1) {
26 		if ((flags & PARSEDATE_INVALID_DATE) != 0)
27 			return "invalid";
28 		return "unknown";
29 	}
30 
31 	if ((flags & PARSEDATE_RELATIVE_TIME) != 0) {
32 		if ((flags & PARSEDATE_MINUTE_RELATIVE_TIME) != 0)
33 			return "minute relative";
34 
35 		return "day relative";
36 	}
37 
38 	return "absolute";
39 }
40 
41 
42 int
43 main(int argc, char** argv)
44 {
45 	time_t now = 1249471430;
46 		// August 5th, 2009, 11:23:50 GMT
47 
48 	struct test {
49 		time_t		result;
50 		const char*	date;
51 		int			flags;
52 		bool		uses_dst;
53 		bool		requires_zone_shift;
54 	};
55 	static const test kDates[] = {
56 		{1248739200, "last tuesday", DAY_RELATIVE, true, true},
57 		{1249430400, "today", DAY_RELATIVE, true, true},
58 		{1249948800, "next tuesday", DAY_RELATIVE, true, true},
59 		{1249344000, "tuesday", DAY_RELATIVE, true, true},
60 		{1249467830, "last hour", MINUTE_RELATIVE, true, false},
61 		{1249475030, "1 hour", MINUTE_RELATIVE, true, false},
62 		{now,		 "now", MINUTE_RELATIVE, true, false},
63 		{219456000,	 "1976-12-15", ABSOLUTE, false, true},
64 		{219456000,	 "12/15/1976", ABSOLUTE, false, true},
65 		{219456000,	 "1976/12/15", ABSOLUTE, false, true},
66 		{219456000,	 "15.12.1976", ABSOLUTE, false, true},
67 		{1061596800, "Sat, 08/23/2003", ABSOLUTE, true, true},
68 		{1061596800, "Sun, 08/23/2003", ABSOLUTE, true, true},
69 		{-1,		 "", INVALID, false, false},
70 		{1249873200, "next monday 3:00", DAY_RELATIVE, true, true},
71 		{1249533720, "thursday 4:42", DAY_RELATIVE, true, true},
72 		{1249533740, "thursday +4:42:20", DAY_RELATIVE, true, true},
73 		{1249533720, "this thursday 4:42", DAY_RELATIVE, true, true},
74 		{1249473950, "42 minutes", MINUTE_RELATIVE, true, false},
75 		{1250640000, "2 weeks", DAY_RELATIVE, true, true},
76 		{1249471730, "next 5 minutes", MINUTE_RELATIVE, true, false},
77 		{1249470530, "last 15 minutes", MINUTE_RELATIVE, true, false},
78 		{1249470530, "-15 minutes", MINUTE_RELATIVE, true, false},
79 		{1249486380, "3:33pm GMT", DAY_RELATIVE, true, false},
80 		{739706403,	 "Mon, June 10th, 1993 10:00:03 am GMT", ABSOLUTE, true, false},
81 		{-1,		 "Sat, 16 Aug   Ìîñêîâñêîå âðåìÿ (çèìà)", INVALID, false, false},
82 		{739706403,	 "Mon, June 10th, 1993 10:00:03 am UTC", ABSOLUTE, true, false},
83 		{739699203,	 "Mon, June 10th, 1993 10:00:03 am CEST", ABSOLUTE, true, false},
84 		{739706403,	 "Mon, June 10th, 1993 10:00:03 am +0000", ABSOLUTE, true, false},
85 		{-1,		 "Mon, June 10th, 1993 10:00:03 am 0000", UNKNOWN, true, false},
86 		{739702803,	 "Mon, June 10th, 1993 10:00:03 am +0100", ABSOLUTE, true, false},
87 		{739731603,	 "Mon, June 10th, 1993 10:00:03 am -0700", ABSOLUTE, true, false},
88 		{739654203,	 "Mon, June 10th, 1993 06:00:03 am ACDT", ABSOLUTE, true, false},
89 		{1291204800, "01 Dec 10 12:00", ABSOLUTE, false, true},
90 		{-1,		 NULL, 0, false}
91 	};
92 
93 	bool verbose = argc > 1;
94 
95 	if (verbose)
96 		printf("All times relative to: %s (%ld)\n", ctime(&now), now);
97 
98 	struct TzInfo {
99 		const char* timezone;
100 		time_t std_offset;
101 		time_t dst_offset;
102 	};
103 	TzInfo tzInfo[] = {
104 		{ "GMT", 0 },
105 		{ "Europe/Berlin", -1 * 3600, -2 * 3600 },
106 		{ "Asia/Tokyo", -9 * 3600, -9 * 3600 },
107 		{ "America/Los_Angeles", 8 * 3600, 7 * 3600 },
108 		{ NULL, 0, 0 }
109 	};
110 
111 	for (int tz = 0; tzInfo[tz].timezone != NULL; tz++) {
112 		printf("timezone: %s ...\n", tzInfo[tz].timezone);
113 		setenv("TZ", tzInfo[tz].timezone, 1);
114 		tzset();
115 
116 		for (int32 i = 0; kDates[i].date; i++) {
117 			int flags = 0;
118 			time_t result = parsedate_etc(kDates[i].date, now, &flags);
119 
120 			time_t expectedResult = kDates[i].result;
121 			if (kDates[i].requires_zone_shift) {
122 				expectedResult +=
123 					kDates[i].uses_dst
124 						? tzInfo[tz].dst_offset
125 						: tzInfo[tz].std_offset;
126 			}
127 			bool failure = false;
128 			if (flags != kDates[i].flags || result != expectedResult)
129 				failure = true;
130 			if (failure) {
131 				printf(
132 					"FAILURE: parsing time at index %ld (should be %ld, %s)\n",
133 					i, expectedResult,
134 					parsedate_flags_to_string(expectedResult, flags));
135 			}
136 
137 			if (verbose || failure) {
138 				printf("\"%s\" = %ld (%s) -> %s", kDates[i].date, result,
139 					parsedate_flags_to_string(result, flags), result == -1
140 						? "-\n" : ctime(&result));
141 			}
142 		}
143 	}
144 
145 	return 0;
146 }
147