1 // Copyright (c) 1999-2018 David Muse
2 // See the file COPYING for more information
3 
4 #include <rudiments/datetime.h>
5 #include <rudiments/environment.h>
6 #include <rudiments/stdio.h>
7 #include <rudiments/private/config.h>
8 #include "test.cpp"
9 
10 const char	*nondstdatestring="02/08/2016 21:54:30 EST";
11 const char	*nondstdatestringwithzerousec="02/08/2016 21:54:30:000 EST";
12 time_t		nondstsecsinceepoch=1454986470;
13 
14 const char	*datestring="04/08/2016 21:54:30 EDT";
15 const char	*estdatestring="04/08/2016 21:54:30 EDT";
16 const char	*cstdatestring="04/08/2016 20:54:30 CDT";
17 const char	*mstdatestring="04/08/2016 19:54:30 MDT";
18 const char	*pstdatestring="04/08/2016 18:54:30 PDT";
19 const char	*datestringwithusec="04/08/2016 21:54:30:500 EDT";
20 const char	*datestringwithzerousec="04/08/2016 21:54:30:000 EDT";
21 time_t		secsinceepoch=1460166870;
22 
main(int argc,const char ** argv)23 int main(int argc, const char **argv) {
24 
25 	// set timezone so epoch to string will work correctly
26 	environment::setValue("TZ","EST5EDT");
27 
28 	header("datetime");
29 
30 	datetime	dt;
31 
32 	// init from string
33 	stdoutput.printf("non-dst date from string:\n");
34 	dt.initialize(nondstdatestring);
35 	test("hour",dt.getHour()==21);
36 	test("minutes",dt.getMinutes()==54);
37 	test("seconds",dt.getSeconds()==30);
38 	test("useconds",dt.getMicroseconds()==0);
39 	test("month",dt.getMonth()==2);
40 	test("month name",
41 		!charstring::compare(dt.getMonthName(),"February"));
42 	test("month abbr",
43 		!charstring::compare(dt.getMonthAbbreviation(),"Feb"));
44 	test("day of month",dt.getDayOfMonth()==8);
45 	test("day of week",dt.getDayOfWeek()==2);
46 	test("day of year",dt.getDayOfYear()==39);
47 	test("year",dt.getYear()==2016);
48 	test("daylight savings time",!dt.isDaylightSavingsTime());
49 
50 	// some platforms (haiku) convert EST to EST5EDT,
51 	// so we have to allow that
52 	test("time zone",
53 		!charstring::compare(dt.getTimeZoneString(),"EST") ||
54 		!charstring::compare(dt.getTimeZoneString(),"EST5EDT"));
55 
56 	test("offset from GMT",dt.getTimeZoneOffset()==-18000);
57 	test("seconds since 1970",dt.getEpoch()==nondstsecsinceepoch);
58 
59 	// some platforms (haiku) convert EST to EST5EDT, so we'll truncate
60 	// the 5EDT part during these comparisons
61 	test("date string",
62 		!charstring::compare(dt.getString(),nondstdatestring,
63 					charstring::length(nondstdatestring)));
64 	test("date string (with usec)",
65 		!charstring::compare(dt.getString(true),
66 			nondstdatestringwithzerousec,
67 			charstring::length(nondstdatestringwithzerousec)));
68 
69 	stdoutput.printf("\n");
70 
71 
72 	// init from string
73 	stdoutput.printf("date from string:\n");
74 	dt.initialize(datestringwithusec);
75 	test("hour",dt.getHour()==21);
76 	test("minutes",dt.getMinutes()==54);
77 	test("seconds",dt.getSeconds()==30);
78 	test("useconds",dt.getMicroseconds()==500);
79 	test("month",dt.getMonth()==4);
80 	test("month name",
81 		!charstring::compare(dt.getMonthName(),"April"));
82 	test("month abbr",
83 		!charstring::compare(dt.getMonthAbbreviation(),"Apr"));
84 	test("day of month",dt.getDayOfMonth()==8);
85 	test("day of week",dt.getDayOfWeek()==6);
86 	test("day of year",dt.getDayOfYear()==99);
87 	test("year",dt.getYear()==2016);
88 	test("daylight savings time",dt.isDaylightSavingsTime());
89 	test("time zone",
90 		!charstring::compare(dt.getTimeZoneString(),"EDT"));
91 	test("offset from GMT",dt.getTimeZoneOffset()==-14400);
92 	test("seconds since 1970",dt.getEpoch()==secsinceepoch);
93 	test("date string",
94 		!charstring::compare(dt.getString(),datestring));
95 	test("date string (with usec)",
96 		!charstring::compare(dt.getString(true),datestringwithusec));
97 	stdoutput.printf("\n");
98 
99 
100 	// init from epoch
101 	stdoutput.printf("date from epoch:\n");
102 	dt.initialize(secsinceepoch);
103 	test("hour",dt.getHour()==21);
104 	test("minutes",dt.getMinutes()==54);
105 	test("seconds",dt.getSeconds()==30);
106 	test("useconds",!dt.getMicroseconds());
107 	test("month",dt.getMonth()==4);
108 	test("month name",
109 		!charstring::compare(dt.getMonthName(),"April"));
110 	test("month abbr",
111 		!charstring::compare(dt.getMonthAbbreviation(),"Apr"));
112 	test("day of month",dt.getDayOfMonth()==8);
113 	test("day of week",dt.getDayOfWeek()==6);
114 	test("day of year",dt.getDayOfYear()==99);
115 	test("year",dt.getYear()==2016);
116 	test("daylight savings time",dt.isDaylightSavingsTime());
117 stdoutput.printf("%s\n",dt.getTimeZoneString());
118 	test("time zone",
119 		!charstring::compare(dt.getTimeZoneString(),"EDT"));
120 	test("offset from GMT",dt.getTimeZoneOffset()==-14400);
121 	test("seconds since 1970",dt.getEpoch()==secsinceepoch);
122 	test("date string",
123 		!charstring::compare(dt.getString(),datestring));
124 	test("date string (with usec)",
125 		!charstring::compare(dt.getString(true),
126 					datestringwithzerousec));
127 	stdoutput.printf("\n");
128 
129 
130 	// init from epoch+usec
131 	stdoutput.printf("date from epoch+usec:\n");
132 	dt.initialize(secsinceepoch,500);
133 	test("hour",dt.getHour()==21);
134 	test("minutes",dt.getMinutes()==54);
135 	test("seconds",dt.getSeconds()==30);
136 	test("useconds",dt.getMicroseconds()==500);
137 	test("month",dt.getMonth()==4);
138 	test("month name",
139 		!charstring::compare(dt.getMonthName(),"April"));
140 	test("month abbr",
141 		!charstring::compare(dt.getMonthAbbreviation(),"Apr"));
142 	test("day of month",dt.getDayOfMonth()==8);
143 	test("day of week",dt.getDayOfWeek()==6);
144 	test("day of year",dt.getDayOfYear()==99);
145 	test("year",dt.getYear()==2016);
146 	test("daylight savings time",dt.isDaylightSavingsTime());
147 	test("time zone",
148 		!charstring::compare(dt.getTimeZoneString(),"EDT"));
149 	test("offset from GMT",dt.getTimeZoneOffset()==-14400);
150 	test("seconds since 1970",dt.getEpoch()==secsinceepoch);
151 	test("date string",
152 		!charstring::compare(dt.getString(),datestring));
153 	test("date string (with usec)",
154 		!charstring::compare(dt.getString(true),datestringwithusec));
155 	stdoutput.printf("\n");
156 
157 
158 	// add/subtract time
159 	stdoutput.printf("add/subtract time:");
160 	dt.addMicroseconds(1);
161 	test("addSeconds(1) hour",dt.getHour()==21);
162 	test("addSeconds(1) minutes",dt.getMinutes()==54);
163 	test("addSeconds(1) seconds",dt.getSeconds()==30);
164 	test("addSeconds(1) useconds",dt.getMicroseconds()==501);
165 	test("addSeconds(1) month",dt.getMonth()==4);
166 	test("addSeconds(1) day of month",dt.getDayOfMonth()==8);
167 	test("addSeconds(1) year",dt.getYear()==2016);
168 	dt.addMicroseconds(-1);
169 	test("addSeconds(-1) hour",dt.getHour()==21);
170 	test("addSeconds(-1) minutes",dt.getMinutes()==54);
171 	test("addSeconds(-1) seconds",dt.getSeconds()==30);
172 	test("addSeconds(-1) useconds",dt.getMicroseconds()==500);
173 	test("addSeconds(-1) month",dt.getMonth()==4);
174 	test("addSeconds(-1) day of month",dt.getDayOfMonth()==8);
175 	test("addSeconds(-1) year",dt.getYear()==2016);
176 	dt.addSeconds(1);
177 	test("addSeconds(1) hour",dt.getHour()==21);
178 	test("addSeconds(1) minutes",dt.getMinutes()==54);
179 	test("addSeconds(1) seconds",dt.getSeconds()==31);
180 	test("addSeconds(1) useconds",dt.getMicroseconds()==500);
181 	test("addSeconds(1) month",dt.getMonth()==4);
182 	test("addSeconds(1) day of month",dt.getDayOfMonth()==8);
183 	test("addSeconds(1) year",dt.getYear()==2016);
184 	dt.addSeconds(-1);
185 	test("addSeconds(-1) hour",dt.getHour()==21);
186 	test("addSeconds(-1) minutes",dt.getMinutes()==54);
187 	test("addSeconds(-1) seconds",dt.getSeconds()==30);
188 	test("addSeconds(-1) useconds",dt.getMicroseconds()==500);
189 	test("addSeconds(-1) month",dt.getMonth()==4);
190 	test("addSeconds(-1) day of month",dt.getDayOfMonth()==8);
191 	test("addSeconds(-1) year",dt.getYear()==2016);
192 	dt.addMinutes(1);
193 	test("addMinutes(1) hour",dt.getHour()==21);
194 	test("addMinutes(1) minutes",dt.getMinutes()==55);
195 	test("addMinutes(1) seconds",dt.getSeconds()==30);
196 	test("addMinutes(1) useconds",dt.getMicroseconds()==500);
197 	test("addMinutes(1) month",dt.getMonth()==4);
198 	test("addMinutes(1) day of month",dt.getDayOfMonth()==8);
199 	test("addMinutes(1) year",dt.getYear()==2016);
200 	dt.addMinutes(-1);
201 	test("addMinutes(-1) hour",dt.getHour()==21);
202 	test("addMinutes(-1) minutes",dt.getMinutes()==54);
203 	test("addMinutes(-1) seconds",dt.getSeconds()==30);
204 	test("addMinutes(-1) useconds",dt.getMicroseconds()==500);
205 	test("addMinutes(-1) month",dt.getMonth()==4);
206 	test("addMinutes(-1) day of month",dt.getDayOfMonth()==8);
207 	test("addMinutes(-1) year",dt.getYear()==2016);
208 	dt.addHours(1);
209 	test("addHours(1) hour",dt.getHour()==22);
210 	test("addHours(1) minutes",dt.getMinutes()==54);
211 	test("addHours(1) seconds",dt.getSeconds()==30);
212 	test("addHours(1) useconds",dt.getMicroseconds()==500);
213 	test("addHours(1) month",dt.getMonth()==4);
214 	test("addHours(1) day of month",dt.getDayOfMonth()==8);
215 	test("addHours(1) year",dt.getYear()==2016);
216 	dt.addHours(-1);
217 	test("addHours(-1) hour",dt.getHour()==21);
218 	test("addHours(-1) minutes",dt.getMinutes()==54);
219 	test("addHours(-1) seconds",dt.getSeconds()==30);
220 	test("addHours(-1) useconds",dt.getMicroseconds()==500);
221 	test("addHours(-1) month",dt.getMonth()==4);
222 	test("addHours(-1) day of month",dt.getDayOfMonth()==8);
223 	test("addHours(-1) year",dt.getYear()==2016);
224 	dt.addDays(1);
225 	test("addDays(1) hour",dt.getHour()==21);
226 	test("addDays(1) minutes",dt.getMinutes()==54);
227 	test("addDays(1) seconds",dt.getSeconds()==30);
228 	test("addDays(1) useconds",dt.getMicroseconds()==500);
229 	test("addDays(1) month",dt.getMonth()==4);
230 	test("addDays(1) day of month",dt.getDayOfMonth()==9);
231 	test("addDays(1) year",dt.getYear()==2016);
232 	dt.addDays(-1);
233 	test("addDays(-1) hour",dt.getHour()==21);
234 	test("addDays(-1) minutes",dt.getMinutes()==54);
235 	test("addDays(-1) seconds",dt.getSeconds()==30);
236 	test("addDays(-1) useconds",dt.getMicroseconds()==500);
237 	test("addDays(-1) month",dt.getMonth()==4);
238 	test("addDays(-1) day of month",dt.getDayOfMonth()==8);
239 	test("addDays(-1) year",dt.getYear()==2016);
240 	dt.addMonths(1);
241 	test("addMonths(1) hour",dt.getHour()==21);
242 	test("addMonths(1) minutes",dt.getMinutes()==54);
243 	test("addMonths(1) seconds",dt.getSeconds()==30);
244 	test("addMonths(1) useconds",dt.getMicroseconds()==500);
245 	test("addMonths(1) month",dt.getMonth()==5);
246 	//test("addMonths(1) day of month",dt.getDayOfMonth()==9);
247 	test("addMonths(1) year",dt.getYear()==2016);
248 	dt.addMonths(-1);
249 	test("addMonths(-1) hour",dt.getHour()==21);
250 	test("addMonths(-1) minutes",dt.getMinutes()==54);
251 	test("addMonths(-1) seconds",dt.getSeconds()==30);
252 	test("addMonths(-1) useconds",dt.getMicroseconds()==500);
253 	test("addMonths(-1) month",dt.getMonth()==4);
254 	test("addMonths(-1) day of month",dt.getDayOfMonth()==8);
255 	test("addMonths(-1) year",dt.getYear()==2016);
256 	dt.addYears(1);
257 	test("addYears(1) hour",dt.getHour()==21);
258 	test("addYears(1) minutes",dt.getMinutes()==54);
259 	test("addYears(1) seconds",dt.getSeconds()==30);
260 	test("addYears(1) useconds",dt.getMicroseconds()==500);
261 	test("addYears(1) month",dt.getMonth()==4);
262 	//test("addYears(1) day of month",dt.getDayOfMonth()==9);
263 	test("addYears(1) year",dt.getYear()==2017);
264 	dt.addYears(-1);
265 	test("addYears(-1) hour",dt.getHour()==21);
266 	test("addYears(-1) minutes",dt.getMinutes()==54);
267 	test("addYears(-1) seconds",dt.getSeconds()==30);
268 	test("addYears(-1) useconds",dt.getMicroseconds()==500);
269 	test("addYears(-1) month",dt.getMonth()==4);
270 	test("addYears(-1) day of month",dt.getDayOfMonth()==8);
271 	test("addYears(-1) year",dt.getYear()==2016);
272 	stdoutput.printf("\n");
273 
274 
275 	// conversions
276 	stdoutput.printf("conversions:\n");
277 	char	*string=datetime::getString(secsinceepoch);
278 	test("string from epoch",!charstring::compare(string,datestring));
279 	delete[] string;
280 	time_t	epoch=datetime::getEpoch(datestring);
281 	test("epoch from string",epoch==secsinceepoch);
282 	string=datetime::getString(secsinceepoch,500);
283 	test("string+usec from epoch",
284 			!charstring::compare(string,datestringwithusec));
285 	delete[] string;
286 	epoch=datetime::getEpoch(datestringwithusec);
287 	test("epoch from string+usec",epoch==secsinceepoch);
288 	stdoutput.printf("\n");
289 
290 
291 	// get time
292 	stdoutput.printf("dates from various sources:\n");
293 	test("system clock",dt.getSystemDateAndTime());
294 	// getHardwareDateAndTime/getAdjustedHardwareDateAndTime
295 	// aren't reliable on most systems
296 	stdoutput.printf("\n");
297 
298 
299 	// time zones
300 	stdoutput.printf("time zones:\n");
301 	const char * const *tz=datetime::getTimeZoneAbbreviations();
302 	uint32_t	i=0;
303 	test("",!charstring::compare(tz[i++],"ACST"));
304 	test("",!charstring::compare(tz[i++],"ACDT"));
305 	test("",!charstring::compare(tz[i++],"ACST-10:30ACDT"));
306 	test("",!charstring::compare(tz[i++],"AST"));
307 	test("",!charstring::compare(tz[i++],"ADT"));
308 	test("",!charstring::compare(tz[i++],"AST4ADT"));
309 	test("",!charstring::compare(tz[i++],"AEST"));
310 	test("",!charstring::compare(tz[i++],"AEDT"));
311 	test("",!charstring::compare(tz[i++],"AEST10AEDT"));
312 	test("",!charstring::compare(tz[i++],"AKST"));
313 	test("",!charstring::compare(tz[i++],"AKDT"));
314 	test("",!charstring::compare(tz[i++],"AKST-9AKDT"));
315 	test("",!charstring::compare(tz[i++],"CST"));
316 	test("",!charstring::compare(tz[i++],"CDT"));
317 	test("",!charstring::compare(tz[i++],"CST6CDT"));
318 	test("",!charstring::compare(tz[i++],"CET"));
319 	test("",!charstring::compare(tz[i++],"CEST"));
320 	test("",!charstring::compare(tz[i++],"CET-1CST"));
321 	test("",!charstring::compare(tz[i++],"EST"));
322 	test("",!charstring::compare(tz[i++],"EDT"));
323 	test("",!charstring::compare(tz[i++],"EST5EDT"));
324 	test("",!charstring::compare(tz[i++],"EET"));
325 	test("",!charstring::compare(tz[i++],"EEST"));
326 	test("",!charstring::compare(tz[i++],"EET-2EEST"));
327 	test("",!charstring::compare(tz[i++],"GMT"));
328 	test("",!charstring::compare(tz[i++],"BST"));
329 	test("",!charstring::compare(tz[i++],"GMT0BST"));
330 	test("",!charstring::compare(tz[i++],"HNA"));
331 	test("",!charstring::compare(tz[i++],"HAA"));
332 	test("",!charstring::compare(tz[i++],"HNA4HAA"));
333 	test("",!charstring::compare(tz[i++],"HNC"));
334 	test("",!charstring::compare(tz[i++],"HAC"));
335 	test("",!charstring::compare(tz[i++],"HNC6HAC"));
336 	test("",!charstring::compare(tz[i++],"HAST"));
337 	test("",!charstring::compare(tz[i++],"HADT"));
338 	test("",!charstring::compare(tz[i++],"HAST10HADT"));
339 	test("",!charstring::compare(tz[i++],"HNE"));
340 	test("",!charstring::compare(tz[i++],"HAE"));
341 	test("",!charstring::compare(tz[i++],"HNE5HAE"));
342 	test("",!charstring::compare(tz[i++],"HNP"));
343 	test("",!charstring::compare(tz[i++],"HAP"));
344 	test("",!charstring::compare(tz[i++],"HNP8HAP"));
345 	test("",!charstring::compare(tz[i++],"HNR"));
346 	test("",!charstring::compare(tz[i++],"HAR"));
347 	test("",!charstring::compare(tz[i++],"HNR7HAR"));
348 	test("",!charstring::compare(tz[i++],"HNT"));
349 	test("",!charstring::compare(tz[i++],"HAT"));
350 	test("",!charstring::compare(tz[i++],"HNT3:30HAT"));
351 	test("",!charstring::compare(tz[i++],"HNY"));
352 	test("",!charstring::compare(tz[i++],"HAY"));
353 	test("",!charstring::compare(tz[i++],"HNY9HAY"));
354 	test("",!charstring::compare(tz[i++],"MST"));
355 	test("",!charstring::compare(tz[i++],"MDT"));
356 	test("",!charstring::compare(tz[i++],"MST7MDT"));
357 	test("",!charstring::compare(tz[i++],"MEZ"));
358 	test("",!charstring::compare(tz[i++],"MESZ"));
359 	test("",!charstring::compare(tz[i++],"MEZ-1MESZ"));
360 	test("",!charstring::compare(tz[i++],"NST"));
361 	test("",!charstring::compare(tz[i++],"NDT"));
362 	test("",!charstring::compare(tz[i++],"NST3:30NDT"));
363 	test("",!charstring::compare(tz[i++],"PST"));
364 	test("",!charstring::compare(tz[i++],"PDT"));
365 	test("",!charstring::compare(tz[i++],"PST8PDT"));
366 	test("",!charstring::compare(tz[i++],"WET"));
367 	test("",!charstring::compare(tz[i++],"WEST"));
368 	test("",!charstring::compare(tz[i++],"WET-1WEST"));
369 	stdoutput.printf("\n");
370 
371 	stdoutput.printf("time zone offsets:\n");
372 	const int32_t *tzo=datetime::getTimeZoneOffsets();
373 	i=0;
374 	test("",tzo[i++]==34200);
375 	test("",tzo[i++]==37800);
376 	test("",tzo[i++]==34200);
377 	test("",tzo[i++]==-14400);
378 	test("",tzo[i++]==-10800);
379 	test("",tzo[i++]==-14400);
380 	test("",tzo[i++]==36000);
381 	test("",tzo[i++]==39600);
382 	test("",tzo[i++]==36000);
383 	test("",tzo[i++]==-32400);
384 	test("",tzo[i++]==-28800);
385 	test("",tzo[i++]==-32400);
386 	test("",tzo[i++]==-21600);
387 	test("",tzo[i++]==-18000);
388 	test("",tzo[i++]==-21600);
389 	test("",tzo[i++]==3600);
390 	test("",tzo[i++]==7200);
391 	test("",tzo[i++]==3600);
392 	test("",tzo[i++]==-18000);
393 	test("",tzo[i++]==-14400);
394 	test("",tzo[i++]==-18000);
395 	test("",tzo[i++]==7200);
396 	test("",tzo[i++]==10800);
397 	test("",tzo[i++]==7200);
398 	test("",tzo[i++]==0);
399 	test("",tzo[i++]==3600);
400 	test("",tzo[i++]==0);
401 	test("",tzo[i++]==-14400);
402 	test("",tzo[i++]==-10800);
403 	test("",tzo[i++]==-14400);
404 	test("",tzo[i++]==-21600);
405 	test("",tzo[i++]==-18000);
406 	test("",tzo[i++]==-21600);
407 	test("",tzo[i++]==-36000);
408 	test("",tzo[i++]==-32400);
409 	test("",tzo[i++]==-36000);
410 	test("",tzo[i++]==-18000);
411 	test("",tzo[i++]==-14400);
412 	test("",tzo[i++]==-18000);
413 	test("",tzo[i++]==-28800);
414 	test("",tzo[i++]==-25200);
415 	test("",tzo[i++]==-28800);
416 	test("",tzo[i++]==-25200);
417 	test("",tzo[i++]==-21600);
418 	test("",tzo[i++]==-25200);
419 	test("",tzo[i++]==-12600);
420 	test("",tzo[i++]==-9000);
421 	test("",tzo[i++]==-12600);
422 	test("",tzo[i++]==-32400);
423 	test("",tzo[i++]==-28800);
424 	test("",tzo[i++]==-32400);
425 	test("",tzo[i++]==-25200);
426 	test("",tzo[i++]==-21600);
427 	test("",tzo[i++]==-25200);
428 	test("",tzo[i++]==3600);
429 	test("",tzo[i++]==7200);
430 	test("",tzo[i++]==3600);
431 	test("",tzo[i++]==-12600);
432 	test("",tzo[i++]==-9000);
433 	test("",tzo[i++]==-12600);
434 	test("",tzo[i++]==-28800);
435 	test("",tzo[i++]==-25200);
436 	test("",tzo[i++]==-28800);
437 	test("",tzo[i++]==0);
438 	test("",tzo[i++]==3600);
439 	stdoutput.printf("\n");
440 
441 
442 // FIXME: doesn't work with linux libc
443 #ifndef RUDIMENTS_HAVE_G_CONFIG_H
444 	// switch time zones
445 	stdoutput.printf("switch time zones:\n");
446 	dt.initialize(datestring);
447 	dt.adjustTimeZone("CST6CDT");
448 	test("CST",!charstring::compare(dt.getString(),cstdatestring));
449 	dt.adjustTimeZone("MST7MDT");
450 	test("MST",!charstring::compare(dt.getString(),mstdatestring));
451 	dt.adjustTimeZone("PST8PDT");
452 	test("PST",!charstring::compare(dt.getString(),pstdatestring));
453 	dt.adjustTimeZone("EST5EDT");
454 	test("EST",!charstring::compare(dt.getString(),estdatestring));
455 	stdoutput.printf("\n");
456 #endif
457 
458 
459 	// valid/invalid dates
460 	stdoutput.printf("valid/invalid dates:\n");
461 	const char	*str="02/20/1974 12:00:00";
462 	test("",datetime::validDateTime(str));
463 	str="02/30/1974 12:00:00";
464 	test("",!datetime::validDateTime(str));
465 	str="02/20/1974 12:00:00 EST5EDT";
466 	test("",datetime::validDateTime(str));
467 	str="02/30/1974 12:00:00 EST5EDT";
468 	test("",!datetime::validDateTime(str));
469 }
470