]>
Commit | Line | Data |
---|---|---|
ccd6aacd VZ |
1 | /////////////////////////////////////////////////////////////////////////////// |
2 | // Name: tests/datetime/datetime.cpp | |
3 | // Purpose: wxDateTime unit test | |
4 | // Author: Vadim Zeitlin | |
5 | // Created: 2004-06-23 (extracted from samples/console/console.cpp) | |
6 | // RCS-ID: $Id$ | |
7 | // Copyright: (c) 2004 Vadim Zeitlin <vadim@wxwindows.org> | |
8 | /////////////////////////////////////////////////////////////////////////////// | |
9 | ||
10 | // ---------------------------------------------------------------------------- | |
11 | // headers | |
12 | // ---------------------------------------------------------------------------- | |
13 | ||
8899b155 | 14 | #include "testprec.h" |
ccd6aacd VZ |
15 | |
16 | #ifdef __BORLANDC__ | |
17 | #pragma hdrstop | |
18 | #endif | |
19 | ||
20 | #ifndef WX_PRECOMP | |
21 | #endif // WX_PRECOMP | |
22 | ||
8605eb1a VZ |
23 | #if wxUSE_DATETIME |
24 | ||
ccd6aacd | 25 | #include "wx/datetime.h" |
1789c1c6 | 26 | #include "wx/wxcrt.h" // for wxStrstr() |
8605eb1a VZ |
27 | |
28 | // need this to be able to use CPPUNIT_ASSERT_EQUAL with wxDateTime objects | |
5098c258 | 29 | static std::ostream& operator<<(std::ostream& ostr, const wxDateTime& dt) |
8605eb1a | 30 | { |
f3f2e255 | 31 | ostr << dt.FormatISOCombined(' '); |
8605eb1a VZ |
32 | |
33 | return ostr; | |
34 | } | |
ccd6aacd | 35 | |
b2eabfe8 VZ |
36 | WX_CPPUNIT_ALLOW_EQUALS_TO_INT(wxDateTime::wxDateTime_t) |
37 | ||
a480d0ab VZ |
38 | // to test Today() meaningfully we must be able to change the system date which |
39 | // is not usually the case, but if we're under Win32 we can try it -- define | |
40 | // the macro below to do it | |
41 | //#define CHANGE_SYSTEM_DATE | |
42 | ||
43 | #ifndef __WINDOWS__ | |
44 | #undef CHANGE_SYSTEM_DATE | |
45 | #endif | |
46 | ||
47 | #ifdef CHANGE_SYSTEM_DATE | |
48 | ||
49 | class DateChanger | |
50 | { | |
51 | public: | |
52 | DateChanger(int year, int month, int day, int hour, int min, int sec) | |
53 | { | |
54 | SYSTEMTIME st; | |
55 | st.wDay = day; | |
56 | st.wMonth = month; | |
57 | st.wYear = year; | |
58 | st.wHour = hour; | |
59 | st.wMinute = min; | |
60 | st.wSecond = sec; | |
61 | st.wMilliseconds = 0; | |
62 | ||
63 | ::GetSystemTime(&m_savedTime); | |
64 | ::GetTimeZoneInformation(&m_tzi); | |
65 | ||
66 | m_changed = ::SetSystemTime(&st) != 0; | |
67 | } | |
68 | ||
69 | ~DateChanger() | |
70 | { | |
71 | if ( m_changed ) | |
72 | { | |
73 | ::SetSystemTime(&m_savedTime); | |
74 | ::SetTimeZoneInformation(&m_tzi); | |
75 | } | |
76 | } | |
77 | ||
78 | private: | |
79 | SYSTEMTIME m_savedTime; | |
80 | TIME_ZONE_INFORMATION m_tzi; | |
81 | bool m_changed; | |
82 | }; | |
83 | ||
84 | #endif // CHANGE_SYSTEM_DATE | |
85 | ||
ccd6aacd VZ |
86 | // ---------------------------------------------------------------------------- |
87 | // broken down date representation used for testing | |
88 | // ---------------------------------------------------------------------------- | |
89 | ||
90 | struct Date | |
91 | { | |
92 | wxDateTime::wxDateTime_t day; | |
93 | wxDateTime::Month month; | |
94 | int year; | |
95 | wxDateTime::wxDateTime_t hour, min, sec; | |
96 | double jdn; | |
97 | wxDateTime::WeekDay wday; | |
a669640b | 98 | time_t gmticks; |
1bf29a7a | 99 | |
ccd6aacd VZ |
100 | void Init(const wxDateTime::Tm& tm) |
101 | { | |
102 | day = tm.mday; | |
103 | month = tm.mon; | |
104 | year = tm.year; | |
105 | hour = tm.hour; | |
106 | min = tm.min; | |
107 | sec = tm.sec; | |
108 | jdn = 0.0; | |
a669640b | 109 | gmticks = -1; |
ccd6aacd VZ |
110 | } |
111 | ||
112 | wxDateTime DT() const | |
113 | { return wxDateTime(day, month, year, hour, min, sec); } | |
114 | ||
115 | bool SameDay(const wxDateTime::Tm& tm) const | |
116 | { | |
117 | return day == tm.mday && month == tm.mon && year == tm.year; | |
118 | } | |
119 | ||
120 | wxString Format() const | |
121 | { | |
122 | wxString s; | |
123 | s.Printf(_T("%02d:%02d:%02d %10s %02d, %4d%s"), | |
124 | hour, min, sec, | |
125 | wxDateTime::GetMonthName(month).c_str(), | |
126 | day, | |
127 | abs(wxDateTime::ConvertYearToBC(year)), | |
128 | year > 0 ? _T("AD") : _T("BC")); | |
129 | return s; | |
130 | } | |
131 | ||
132 | wxString FormatDate() const | |
133 | { | |
134 | wxString s; | |
135 | s.Printf(_T("%02d-%s-%4d%s"), | |
136 | day, | |
137 | wxDateTime::GetMonthName(month, wxDateTime::Name_Abbr).c_str(), | |
138 | abs(wxDateTime::ConvertYearToBC(year)), | |
139 | year > 0 ? _T("AD") : _T("BC")); | |
140 | return s; | |
141 | } | |
142 | }; | |
143 | ||
144 | // ---------------------------------------------------------------------------- | |
145 | // test data | |
146 | // ---------------------------------------------------------------------------- | |
147 | ||
148 | static const Date testDates[] = | |
149 | { | |
a669640b VZ |
150 | { 1, wxDateTime::Jan, 1970, 00, 00, 00, 2440587.5, wxDateTime::Thu, 0 }, |
151 | { 7, wxDateTime::Feb, 2036, 00, 00, 00, 2464730.5, wxDateTime::Thu, -1 }, | |
152 | { 8, wxDateTime::Feb, 2036, 00, 00, 00, 2464731.5, wxDateTime::Fri, -1 }, | |
153 | { 1, wxDateTime::Jan, 2037, 00, 00, 00, 2465059.5, wxDateTime::Thu, -1 }, | |
154 | { 1, wxDateTime::Jan, 2038, 00, 00, 00, 2465424.5, wxDateTime::Fri, -1 }, | |
155 | { 21, wxDateTime::Jan, 2222, 00, 00, 00, 2532648.5, wxDateTime::Mon, -1 }, | |
156 | { 29, wxDateTime::May, 1976, 12, 00, 00, 2442928.0, wxDateTime::Sat, 202219200 }, | |
157 | { 29, wxDateTime::Feb, 1976, 00, 00, 00, 2442837.5, wxDateTime::Sun, 194400000 }, | |
158 | { 1, wxDateTime::Jan, 1900, 12, 00, 00, 2415021.0, wxDateTime::Mon, -1 }, | |
159 | { 1, wxDateTime::Jan, 1900, 00, 00, 00, 2415020.5, wxDateTime::Mon, -1 }, | |
160 | { 15, wxDateTime::Oct, 1582, 00, 00, 00, 2299160.5, wxDateTime::Fri, -1 }, | |
161 | { 4, wxDateTime::Oct, 1582, 00, 00, 00, 2299149.5, wxDateTime::Mon, -1 }, | |
162 | { 1, wxDateTime::Mar, 1, 00, 00, 00, 1721484.5, wxDateTime::Thu, -1 }, | |
163 | { 1, wxDateTime::Jan, 1, 00, 00, 00, 1721425.5, wxDateTime::Mon, -1 }, | |
164 | { 31, wxDateTime::Dec, 0, 00, 00, 00, 1721424.5, wxDateTime::Sun, -1 }, | |
165 | { 1, wxDateTime::Jan, 0, 00, 00, 00, 1721059.5, wxDateTime::Sat, -1 }, | |
166 | { 12, wxDateTime::Aug, -1234, 00, 00, 00, 1270573.5, wxDateTime::Fri, -1 }, | |
167 | { 12, wxDateTime::Aug, -4000, 00, 00, 00, 260313.5, wxDateTime::Sat, -1 }, | |
168 | { 24, wxDateTime::Nov, -4713, 00, 00, 00, -0.5, wxDateTime::Mon, -1 }, | |
ccd6aacd VZ |
169 | }; |
170 | ||
171 | ||
172 | // ---------------------------------------------------------------------------- | |
173 | // test class | |
174 | // ---------------------------------------------------------------------------- | |
175 | ||
176 | class DateTimeTestCase : public CppUnit::TestCase | |
177 | { | |
178 | public: | |
179 | DateTimeTestCase() { } | |
180 | ||
181 | private: | |
182 | CPPUNIT_TEST_SUITE( DateTimeTestCase ); | |
183 | CPPUNIT_TEST( TestLeapYears ); | |
184 | CPPUNIT_TEST( TestTimeSet ); | |
185 | CPPUNIT_TEST( TestTimeJDN ); | |
186 | CPPUNIT_TEST( TestTimeWNumber ); | |
187 | CPPUNIT_TEST( TestTimeWDays ); | |
188 | CPPUNIT_TEST( TestTimeDST ); | |
189 | CPPUNIT_TEST( TestTimeFormat ); | |
1bf29a7a | 190 | CPPUNIT_TEST( TestTimeSpanFormat ); |
ccd6aacd | 191 | CPPUNIT_TEST( TestTimeTicks ); |
8605eb1a VZ |
192 | CPPUNIT_TEST( TestParceRFC822 ); |
193 | CPPUNIT_TEST( TestDateParse ); | |
f3f2e255 | 194 | CPPUNIT_TEST( TestDateParseISO ); |
804eeca5 | 195 | CPPUNIT_TEST( TestDateTimeParse ); |
ccd6aacd | 196 | CPPUNIT_TEST( TestTimeArithmetics ); |
a480d0ab | 197 | CPPUNIT_TEST( TestDSTBug ); |
fb96cf85 | 198 | CPPUNIT_TEST( TestDateOnly ); |
ccd6aacd VZ |
199 | CPPUNIT_TEST_SUITE_END(); |
200 | ||
201 | void TestLeapYears(); | |
202 | void TestTimeSet(); | |
203 | void TestTimeJDN(); | |
204 | void TestTimeWNumber(); | |
205 | void TestTimeWDays(); | |
206 | void TestTimeDST(); | |
207 | void TestTimeFormat(); | |
1bf29a7a | 208 | void TestTimeSpanFormat(); |
ccd6aacd | 209 | void TestTimeTicks(); |
8605eb1a VZ |
210 | void TestParceRFC822(); |
211 | void TestDateParse(); | |
f3f2e255 | 212 | void TestDateParseISO(); |
804eeca5 | 213 | void TestDateTimeParse(); |
ccd6aacd | 214 | void TestTimeArithmetics(); |
a480d0ab | 215 | void TestDSTBug(); |
fb96cf85 | 216 | void TestDateOnly(); |
ccd6aacd VZ |
217 | |
218 | DECLARE_NO_COPY_CLASS(DateTimeTestCase) | |
219 | }; | |
220 | ||
221 | // register in the unnamed registry so that these tests are run by default | |
222 | CPPUNIT_TEST_SUITE_REGISTRATION( DateTimeTestCase ); | |
223 | ||
224 | // also include in it's own registry so that these tests can be run alone | |
225 | CPPUNIT_TEST_SUITE_NAMED_REGISTRATION( DateTimeTestCase, "DateTimeTestCase" ); | |
226 | ||
227 | // ============================================================================ | |
228 | // implementation | |
229 | // ============================================================================ | |
230 | ||
231 | // test leap years detection | |
232 | void DateTimeTestCase::TestLeapYears() | |
233 | { | |
234 | static const struct LeapYearTestData | |
235 | { | |
236 | int year; | |
237 | bool isLeap; | |
238 | } years[] = | |
239 | { | |
240 | { 1900, false }, | |
241 | { 1990, false }, | |
242 | { 1976, true }, | |
243 | { 2000, true }, | |
244 | { 2030, false }, | |
245 | { 1984, true }, | |
246 | { 2100, false }, | |
247 | { 2400, true }, | |
248 | }; | |
249 | ||
250 | for ( size_t n = 0; n < WXSIZEOF(years); n++ ) | |
251 | { | |
252 | const LeapYearTestData& y = years[n]; | |
253 | ||
254 | CPPUNIT_ASSERT( wxDateTime::IsLeapYear(y.year) == y.isLeap ); | |
255 | } | |
256 | } | |
257 | ||
258 | // test constructing wxDateTime objects | |
259 | void DateTimeTestCase::TestTimeSet() | |
260 | { | |
261 | for ( size_t n = 0; n < WXSIZEOF(testDates); n++ ) | |
262 | { | |
263 | const Date& d1 = testDates[n]; | |
264 | wxDateTime dt = d1.DT(); | |
265 | ||
266 | Date d2; | |
267 | d2.Init(dt.GetTm()); | |
268 | ||
269 | wxString s1 = d1.Format(), | |
270 | s2 = d2.Format(); | |
271 | ||
272 | CPPUNIT_ASSERT( s1 == s2 ); | |
273 | } | |
274 | } | |
275 | ||
276 | // test conversions to JDN &c | |
277 | void DateTimeTestCase::TestTimeJDN() | |
278 | { | |
279 | for ( size_t n = 0; n < WXSIZEOF(testDates); n++ ) | |
280 | { | |
281 | const Date& d = testDates[n]; | |
282 | wxDateTime dt(d.day, d.month, d.year, d.hour, d.min, d.sec); | |
d26adb9d VZ |
283 | |
284 | // JDNs must be computed for UTC times | |
285 | double jdn = dt.FromUTC().GetJulianDayNumber(); | |
ccd6aacd | 286 | |
93a800a9 | 287 | CPPUNIT_ASSERT_EQUAL( d.jdn, jdn ); |
e3559425 VZ |
288 | |
289 | dt.Set(jdn); | |
93a800a9 | 290 | CPPUNIT_ASSERT_EQUAL( jdn, dt.GetJulianDayNumber() ); |
ccd6aacd VZ |
291 | } |
292 | } | |
293 | ||
294 | // test week days computation | |
295 | void DateTimeTestCase::TestTimeWDays() | |
296 | { | |
297 | // test GetWeekDay() | |
298 | size_t n; | |
299 | for ( n = 0; n < WXSIZEOF(testDates); n++ ) | |
300 | { | |
301 | const Date& d = testDates[n]; | |
302 | wxDateTime dt(d.day, d.month, d.year, d.hour, d.min, d.sec); | |
303 | ||
304 | wxDateTime::WeekDay wday = dt.GetWeekDay(); | |
305 | CPPUNIT_ASSERT( wday == d.wday ); | |
306 | } | |
307 | ||
308 | // test SetToWeekDay() | |
309 | struct WeekDateTestData | |
310 | { | |
311 | Date date; // the real date (precomputed) | |
312 | int nWeek; // its week index in the month | |
313 | wxDateTime::WeekDay wday; // the weekday | |
314 | wxDateTime::Month month; // the month | |
315 | int year; // and the year | |
316 | ||
317 | wxString Format() const | |
318 | { | |
319 | wxString s, which; | |
320 | switch ( nWeek < -1 ? -nWeek : nWeek ) | |
321 | { | |
322 | case 1: which = _T("first"); break; | |
323 | case 2: which = _T("second"); break; | |
324 | case 3: which = _T("third"); break; | |
325 | case 4: which = _T("fourth"); break; | |
326 | case 5: which = _T("fifth"); break; | |
327 | ||
328 | case -1: which = _T("last"); break; | |
329 | } | |
330 | ||
331 | if ( nWeek < -1 ) | |
332 | { | |
333 | which += _T(" from end"); | |
334 | } | |
335 | ||
336 | s.Printf(_T("The %s %s of %s in %d"), | |
337 | which.c_str(), | |
338 | wxDateTime::GetWeekDayName(wday).c_str(), | |
339 | wxDateTime::GetMonthName(month).c_str(), | |
340 | year); | |
341 | ||
342 | return s; | |
343 | } | |
344 | }; | |
345 | ||
346 | // the array data was generated by the following python program | |
347 | /* | |
348 | from DateTime import * | |
349 | from whrandom import * | |
350 | from string import * | |
351 | ||
352 | monthNames = [ 'Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec' ] | |
353 | wdayNames = [ 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun' ] | |
354 | ||
355 | week = DateTimeDelta(7) | |
356 | ||
357 | for n in range(20): | |
358 | year = randint(1900, 2100) | |
359 | month = randint(1, 12) | |
360 | day = randint(1, 28) | |
361 | dt = DateTime(year, month, day) | |
362 | wday = dt.day_of_week | |
363 | ||
364 | countFromEnd = choice([-1, 1]) | |
365 | weekNum = 0; | |
366 | ||
367 | while dt.month is month: | |
368 | dt = dt - countFromEnd * week | |
369 | weekNum = weekNum + countFromEnd | |
370 | ||
371 | data = { 'day': rjust(`day`, 2), 'month': monthNames[month - 1], 'year': year, 'weekNum': rjust(`weekNum`, 2), 'wday': wdayNames[wday] } | |
372 | ||
373 | print "{ { %(day)s, wxDateTime::%(month)s, %(year)d }, %(weekNum)d, "\ | |
374 | "wxDateTime::%(wday)s, wxDateTime::%(month)s, %(year)d }," % data | |
375 | */ | |
376 | ||
377 | static const WeekDateTestData weekDatesTestData[] = | |
378 | { | |
a669640b VZ |
379 | { { 20, wxDateTime::Mar, 2045, 0, 0, 0, 0.0, wxDateTime::Inv_WeekDay, 0 }, 3, wxDateTime::Mon, wxDateTime::Mar, 2045 }, |
380 | { { 5, wxDateTime::Jun, 1985, 0, 0, 0, 0.0, wxDateTime::Inv_WeekDay, 0 }, -4, wxDateTime::Wed, wxDateTime::Jun, 1985 }, | |
381 | { { 12, wxDateTime::Nov, 1961, 0, 0, 0, 0.0, wxDateTime::Inv_WeekDay, 0 }, -3, wxDateTime::Sun, wxDateTime::Nov, 1961 }, | |
382 | { { 27, wxDateTime::Feb, 2093, 0, 0, 0, 0.0, wxDateTime::Inv_WeekDay, 0 }, -1, wxDateTime::Fri, wxDateTime::Feb, 2093 }, | |
383 | { { 4, wxDateTime::Jul, 2070, 0, 0, 0, 0.0, wxDateTime::Inv_WeekDay, 0 }, -4, wxDateTime::Fri, wxDateTime::Jul, 2070 }, | |
384 | { { 2, wxDateTime::Apr, 1906, 0, 0, 0, 0.0, wxDateTime::Inv_WeekDay, 0 }, -5, wxDateTime::Mon, wxDateTime::Apr, 1906 }, | |
385 | { { 19, wxDateTime::Jul, 2023, 0, 0, 0, 0.0, wxDateTime::Inv_WeekDay, 0 }, -2, wxDateTime::Wed, wxDateTime::Jul, 2023 }, | |
386 | { { 5, wxDateTime::May, 1958, 0, 0, 0, 0.0, wxDateTime::Inv_WeekDay, 0 }, -4, wxDateTime::Mon, wxDateTime::May, 1958 }, | |
387 | { { 11, wxDateTime::Aug, 1900, 0, 0, 0, 0.0, wxDateTime::Inv_WeekDay, 0 }, 2, wxDateTime::Sat, wxDateTime::Aug, 1900 }, | |
388 | { { 14, wxDateTime::Feb, 1945, 0, 0, 0, 0.0, wxDateTime::Inv_WeekDay, 0 }, 2, wxDateTime::Wed, wxDateTime::Feb, 1945 }, | |
389 | { { 25, wxDateTime::Jul, 1967, 0, 0, 0, 0.0, wxDateTime::Inv_WeekDay, 0 }, -1, wxDateTime::Tue, wxDateTime::Jul, 1967 }, | |
390 | { { 9, wxDateTime::May, 1916, 0, 0, 0, 0.0, wxDateTime::Inv_WeekDay, 0 }, -4, wxDateTime::Tue, wxDateTime::May, 1916 }, | |
391 | { { 20, wxDateTime::Jun, 1927, 0, 0, 0, 0.0, wxDateTime::Inv_WeekDay, 0 }, 3, wxDateTime::Mon, wxDateTime::Jun, 1927 }, | |
392 | { { 2, wxDateTime::Aug, 2000, 0, 0, 0, 0.0, wxDateTime::Inv_WeekDay, 0 }, 1, wxDateTime::Wed, wxDateTime::Aug, 2000 }, | |
393 | { { 20, wxDateTime::Apr, 2044, 0, 0, 0, 0.0, wxDateTime::Inv_WeekDay, 0 }, 3, wxDateTime::Wed, wxDateTime::Apr, 2044 }, | |
394 | { { 20, wxDateTime::Feb, 1932, 0, 0, 0, 0.0, wxDateTime::Inv_WeekDay, 0 }, -2, wxDateTime::Sat, wxDateTime::Feb, 1932 }, | |
395 | { { 25, wxDateTime::Jul, 2069, 0, 0, 0, 0.0, wxDateTime::Inv_WeekDay, 0 }, 4, wxDateTime::Thu, wxDateTime::Jul, 2069 }, | |
396 | { { 3, wxDateTime::Apr, 1925, 0, 0, 0, 0.0, wxDateTime::Inv_WeekDay, 0 }, 1, wxDateTime::Fri, wxDateTime::Apr, 1925 }, | |
397 | { { 21, wxDateTime::Mar, 2093, 0, 0, 0, 0.0, wxDateTime::Inv_WeekDay, 0 }, 3, wxDateTime::Sat, wxDateTime::Mar, 2093 }, | |
398 | { { 3, wxDateTime::Dec, 2074, 0, 0, 0, 0.0, wxDateTime::Inv_WeekDay, 0 }, -5, wxDateTime::Mon, wxDateTime::Dec, 2074 } | |
ccd6aacd VZ |
399 | }; |
400 | ||
ccd6aacd VZ |
401 | wxDateTime dt; |
402 | for ( n = 0; n < WXSIZEOF(weekDatesTestData); n++ ) | |
403 | { | |
404 | const WeekDateTestData& wd = weekDatesTestData[n]; | |
405 | ||
406 | dt.SetToWeekDay(wd.wday, wd.nWeek, wd.month, wd.year); | |
407 | ||
408 | const Date& d = wd.date; | |
409 | CPPUNIT_ASSERT( d.SameDay(dt.GetTm()) ); | |
410 | } | |
411 | } | |
412 | ||
413 | // test the computation of (ISO) week numbers | |
414 | void DateTimeTestCase::TestTimeWNumber() | |
415 | { | |
416 | struct WeekNumberTestData | |
417 | { | |
418 | Date date; // the date | |
419 | wxDateTime::wxDateTime_t week; // the week number in the year | |
420 | wxDateTime::wxDateTime_t wmon; // the week number in the month | |
421 | wxDateTime::wxDateTime_t wmon2; // same but week starts with Sun | |
422 | wxDateTime::wxDateTime_t dnum; // day number in the year | |
423 | }; | |
424 | ||
425 | // data generated with the following python script: | |
426 | /* | |
427 | from DateTime import * | |
428 | from whrandom import * | |
429 | from string import * | |
430 | ||
431 | monthNames = [ 'Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec' ] | |
432 | wdayNames = [ 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun' ] | |
433 | ||
434 | def GetMonthWeek(dt): | |
435 | weekNumMonth = dt.iso_week[1] - DateTime(dt.year, dt.month, 1).iso_week[1] + 1 | |
436 | if weekNumMonth < 0: | |
437 | weekNumMonth = weekNumMonth + 53 | |
438 | return weekNumMonth | |
439 | ||
440 | def GetLastSundayBefore(dt): | |
441 | if dt.iso_week[2] == 7: | |
442 | return dt | |
443 | else: | |
444 | return dt - DateTimeDelta(dt.iso_week[2]) | |
445 | ||
446 | for n in range(20): | |
447 | year = randint(1900, 2100) | |
448 | month = randint(1, 12) | |
449 | day = randint(1, 28) | |
450 | dt = DateTime(year, month, day) | |
451 | dayNum = dt.day_of_year | |
452 | weekNum = dt.iso_week[1] | |
453 | weekNumMonth = GetMonthWeek(dt) | |
454 | ||
455 | weekNumMonth2 = 0 | |
456 | dtSunday = GetLastSundayBefore(dt) | |
457 | ||
458 | while dtSunday >= GetLastSundayBefore(DateTime(dt.year, dt.month, 1)): | |
459 | weekNumMonth2 = weekNumMonth2 + 1 | |
460 | dtSunday = dtSunday - DateTimeDelta(7) | |
461 | ||
462 | data = { 'day': rjust(`day`, 2), \ | |
463 | 'month': monthNames[month - 1], \ | |
464 | 'year': year, \ | |
465 | 'weekNum': rjust(`weekNum`, 2), \ | |
466 | 'weekNumMonth': weekNumMonth, \ | |
467 | 'weekNumMonth2': weekNumMonth2, \ | |
468 | 'dayNum': rjust(`dayNum`, 3) } | |
469 | ||
470 | print " { { %(day)s, "\ | |
471 | "wxDateTime::%(month)s, "\ | |
472 | "%(year)d }, "\ | |
473 | "%(weekNum)s, "\ | |
474 | "%(weekNumMonth)s, "\ | |
475 | "%(weekNumMonth2)s, "\ | |
476 | "%(dayNum)s }," % data | |
477 | ||
478 | */ | |
479 | static const WeekNumberTestData weekNumberTestDates[] = | |
480 | { | |
a669640b VZ |
481 | { { 27, wxDateTime::Dec, 1966, 0, 0, 0, 0.0, wxDateTime::Inv_WeekDay, 0 }, 52, 5, 5, 361 }, |
482 | { { 22, wxDateTime::Jul, 1926, 0, 0, 0, 0.0, wxDateTime::Inv_WeekDay, 0 }, 29, 4, 4, 203 }, | |
483 | { { 22, wxDateTime::Oct, 2076, 0, 0, 0, 0.0, wxDateTime::Inv_WeekDay, 0 }, 43, 4, 4, 296 }, | |
484 | { { 1, wxDateTime::Jul, 1967, 0, 0, 0, 0.0, wxDateTime::Inv_WeekDay, 0 }, 26, 1, 1, 182 }, | |
485 | { { 8, wxDateTime::Nov, 2004, 0, 0, 0, 0.0, wxDateTime::Inv_WeekDay, 0 }, 46, 2, 2, 313 }, | |
486 | { { 21, wxDateTime::Mar, 1920, 0, 0, 0, 0.0, wxDateTime::Inv_WeekDay, 0 }, 12, 3, 4, 81 }, | |
487 | { { 7, wxDateTime::Jan, 1965, 0, 0, 0, 0.0, wxDateTime::Inv_WeekDay, 0 }, 1, 2, 2, 7 }, | |
488 | { { 19, wxDateTime::Oct, 1999, 0, 0, 0, 0.0, wxDateTime::Inv_WeekDay, 0 }, 42, 4, 4, 292 }, | |
489 | { { 13, wxDateTime::Aug, 1955, 0, 0, 0, 0.0, wxDateTime::Inv_WeekDay, 0 }, 32, 2, 2, 225 }, | |
490 | { { 18, wxDateTime::Jul, 2087, 0, 0, 0, 0.0, wxDateTime::Inv_WeekDay, 0 }, 29, 3, 3, 199 }, | |
491 | { { 2, wxDateTime::Sep, 2028, 0, 0, 0, 0.0, wxDateTime::Inv_WeekDay, 0 }, 35, 1, 1, 246 }, | |
492 | { { 28, wxDateTime::Jul, 1945, 0, 0, 0, 0.0, wxDateTime::Inv_WeekDay, 0 }, 30, 5, 4, 209 }, | |
493 | { { 15, wxDateTime::Jun, 1901, 0, 0, 0, 0.0, wxDateTime::Inv_WeekDay, 0 }, 24, 3, 3, 166 }, | |
494 | { { 10, wxDateTime::Oct, 1939, 0, 0, 0, 0.0, wxDateTime::Inv_WeekDay, 0 }, 41, 3, 2, 283 }, | |
495 | { { 3, wxDateTime::Dec, 1965, 0, 0, 0, 0.0, wxDateTime::Inv_WeekDay, 0 }, 48, 1, 1, 337 }, | |
496 | { { 23, wxDateTime::Feb, 1940, 0, 0, 0, 0.0, wxDateTime::Inv_WeekDay, 0 }, 8, 4, 4, 54 }, | |
497 | { { 2, wxDateTime::Jan, 1987, 0, 0, 0, 0.0, wxDateTime::Inv_WeekDay, 0 }, 1, 1, 1, 2 }, | |
498 | { { 11, wxDateTime::Aug, 2079, 0, 0, 0, 0.0, wxDateTime::Inv_WeekDay, 0 }, 32, 2, 2, 223 }, | |
499 | { { 2, wxDateTime::Feb, 2063, 0, 0, 0, 0.0, wxDateTime::Inv_WeekDay, 0 }, 5, 1, 1, 33 }, | |
500 | { { 16, wxDateTime::Oct, 1942, 0, 0, 0, 0.0, wxDateTime::Inv_WeekDay, 0 }, 42, 3, 3, 289 }, | |
501 | { { 30, wxDateTime::Dec, 2003, 0, 0, 0, 0.0, wxDateTime::Inv_WeekDay, 0 }, 1, 5, 5, 364 }, | |
502 | { { 2, wxDateTime::Jan, 2004, 0, 0, 0, 0.0, wxDateTime::Inv_WeekDay, 0 }, 1, 1, 1, 2 }, | |
ccd6aacd VZ |
503 | }; |
504 | ||
505 | for ( size_t n = 0; n < WXSIZEOF(weekNumberTestDates); n++ ) | |
506 | { | |
507 | const WeekNumberTestData& wn = weekNumberTestDates[n]; | |
508 | const Date& d = wn.date; | |
509 | ||
510 | wxDateTime dt = d.DT(); | |
511 | ||
512 | wxDateTime::wxDateTime_t | |
513 | week = dt.GetWeekOfYear(wxDateTime::Monday_First), | |
514 | wmon = dt.GetWeekOfMonth(wxDateTime::Monday_First), | |
515 | wmon2 = dt.GetWeekOfMonth(wxDateTime::Sunday_First), | |
516 | dnum = dt.GetDayOfYear(); | |
517 | ||
518 | CPPUNIT_ASSERT( dnum == wn.dnum ); | |
519 | CPPUNIT_ASSERT( wmon == wn.wmon ); | |
520 | CPPUNIT_ASSERT( wmon2 == wn.wmon2 ); | |
521 | CPPUNIT_ASSERT( week == wn.week ); | |
522 | ||
4c27e2fa VZ |
523 | int year = d.year; |
524 | if ( week == 1 && d.month != wxDateTime::Jan ) | |
525 | { | |
526 | // this means we're in the first week of the next year | |
527 | year++; | |
528 | } | |
529 | ||
530 | wxDateTime | |
531 | dt2 = wxDateTime::SetToWeekOfYear(year, week, dt.GetWeekDay()); | |
ccd6aacd VZ |
532 | CPPUNIT_ASSERT( dt2 == dt ); |
533 | } | |
534 | } | |
535 | ||
536 | // test DST applicability | |
537 | void DateTimeTestCase::TestTimeDST() | |
538 | { | |
539 | // taken from http://www.energy.ca.gov/daylightsaving.html | |
6b522db5 | 540 | static const Date datesDST[2][2009 - 1990 + 1] = |
ccd6aacd VZ |
541 | { |
542 | { | |
a669640b VZ |
543 | { 1, wxDateTime::Apr, 1990, 0, 0, 0, 0.0, wxDateTime::Inv_WeekDay, 0 }, |
544 | { 7, wxDateTime::Apr, 1991, 0, 0, 0, 0.0, wxDateTime::Inv_WeekDay, 0 }, | |
545 | { 5, wxDateTime::Apr, 1992, 0, 0, 0, 0.0, wxDateTime::Inv_WeekDay, 0 }, | |
546 | { 4, wxDateTime::Apr, 1993, 0, 0, 0, 0.0, wxDateTime::Inv_WeekDay, 0 }, | |
547 | { 3, wxDateTime::Apr, 1994, 0, 0, 0, 0.0, wxDateTime::Inv_WeekDay, 0 }, | |
548 | { 2, wxDateTime::Apr, 1995, 0, 0, 0, 0.0, wxDateTime::Inv_WeekDay, 0 }, | |
549 | { 7, wxDateTime::Apr, 1996, 0, 0, 0, 0.0, wxDateTime::Inv_WeekDay, 0 }, | |
550 | { 6, wxDateTime::Apr, 1997, 0, 0, 0, 0.0, wxDateTime::Inv_WeekDay, 0 }, | |
551 | { 5, wxDateTime::Apr, 1998, 0, 0, 0, 0.0, wxDateTime::Inv_WeekDay, 0 }, | |
552 | { 4, wxDateTime::Apr, 1999, 0, 0, 0, 0.0, wxDateTime::Inv_WeekDay, 0 }, | |
553 | { 2, wxDateTime::Apr, 2000, 0, 0, 0, 0.0, wxDateTime::Inv_WeekDay, 0 }, | |
554 | { 1, wxDateTime::Apr, 2001, 0, 0, 0, 0.0, wxDateTime::Inv_WeekDay, 0 }, | |
555 | { 7, wxDateTime::Apr, 2002, 0, 0, 0, 0.0, wxDateTime::Inv_WeekDay, 0 }, | |
556 | { 6, wxDateTime::Apr, 2003, 0, 0, 0, 0.0, wxDateTime::Inv_WeekDay, 0 }, | |
557 | { 4, wxDateTime::Apr, 2004, 0, 0, 0, 0.0, wxDateTime::Inv_WeekDay, 0 }, | |
6b522db5 VZ |
558 | { 3, wxDateTime::Apr, 2005, 0, 0, 0, 0.0, wxDateTime::Inv_WeekDay, 0 }, |
559 | { 2, wxDateTime::Apr, 2006, 0, 0, 0, 0.0, wxDateTime::Inv_WeekDay, 0 }, | |
560 | {11, wxDateTime::Mar, 2007, 0, 0, 0, 0.0, wxDateTime::Inv_WeekDay, 0 }, | |
561 | { 9, wxDateTime::Mar, 2008, 0, 0, 0, 0.0, wxDateTime::Inv_WeekDay, 0 }, | |
562 | { 8, wxDateTime::Mar, 2009, 0, 0, 0, 0.0, wxDateTime::Inv_WeekDay, 0 }, | |
ccd6aacd VZ |
563 | }, |
564 | { | |
a669640b VZ |
565 | { 28, wxDateTime::Oct, 1990, 0, 0, 0, 0.0, wxDateTime::Inv_WeekDay, 0 }, |
566 | { 27, wxDateTime::Oct, 1991, 0, 0, 0, 0.0, wxDateTime::Inv_WeekDay, 0 }, | |
567 | { 25, wxDateTime::Oct, 1992, 0, 0, 0, 0.0, wxDateTime::Inv_WeekDay, 0 }, | |
568 | { 31, wxDateTime::Oct, 1993, 0, 0, 0, 0.0, wxDateTime::Inv_WeekDay, 0 }, | |
569 | { 30, wxDateTime::Oct, 1994, 0, 0, 0, 0.0, wxDateTime::Inv_WeekDay, 0 }, | |
570 | { 29, wxDateTime::Oct, 1995, 0, 0, 0, 0.0, wxDateTime::Inv_WeekDay, 0 }, | |
571 | { 27, wxDateTime::Oct, 1996, 0, 0, 0, 0.0, wxDateTime::Inv_WeekDay, 0 }, | |
572 | { 26, wxDateTime::Oct, 1997, 0, 0, 0, 0.0, wxDateTime::Inv_WeekDay, 0 }, | |
573 | { 25, wxDateTime::Oct, 1998, 0, 0, 0, 0.0, wxDateTime::Inv_WeekDay, 0 }, | |
574 | { 31, wxDateTime::Oct, 1999, 0, 0, 0, 0.0, wxDateTime::Inv_WeekDay, 0 }, | |
575 | { 29, wxDateTime::Oct, 2000, 0, 0, 0, 0.0, wxDateTime::Inv_WeekDay, 0 }, | |
576 | { 28, wxDateTime::Oct, 2001, 0, 0, 0, 0.0, wxDateTime::Inv_WeekDay, 0 }, | |
577 | { 27, wxDateTime::Oct, 2002, 0, 0, 0, 0.0, wxDateTime::Inv_WeekDay, 0 }, | |
578 | { 26, wxDateTime::Oct, 2003, 0, 0, 0, 0.0, wxDateTime::Inv_WeekDay, 0 }, | |
579 | { 31, wxDateTime::Oct, 2004, 0, 0, 0, 0.0, wxDateTime::Inv_WeekDay, 0 }, | |
6b522db5 VZ |
580 | { 30, wxDateTime::Oct, 2005, 0, 0, 0, 0.0, wxDateTime::Inv_WeekDay, 0 }, |
581 | { 29, wxDateTime::Oct, 2006, 0, 0, 0, 0.0, wxDateTime::Inv_WeekDay, 0 }, | |
582 | { 4, wxDateTime::Nov, 2007, 0, 0, 0, 0.0, wxDateTime::Inv_WeekDay, 0 }, | |
583 | { 2, wxDateTime::Nov, 2008, 0, 0, 0, 0.0, wxDateTime::Inv_WeekDay, 0 }, | |
584 | { 1, wxDateTime::Nov, 2009, 0, 0, 0, 0.0, wxDateTime::Inv_WeekDay, 0 }, | |
585 | ||
ccd6aacd VZ |
586 | } |
587 | }; | |
588 | ||
6b522db5 | 589 | for ( size_t n = 0; n < WXSIZEOF(datesDST[0]); n++ ) |
ccd6aacd | 590 | { |
6b522db5 | 591 | const int year = 1990 + n; |
ccd6aacd VZ |
592 | wxDateTime dtBegin = wxDateTime::GetBeginDST(year, wxDateTime::USA), |
593 | dtEnd = wxDateTime::GetEndDST(year, wxDateTime::USA); | |
594 | ||
ccd6aacd VZ |
595 | const Date& dBegin = datesDST[0][n]; |
596 | const Date& dEnd = datesDST[1][n]; | |
597 | ||
6b522db5 VZ |
598 | CPPUNIT_ASSERT_EQUAL( dBegin.DT().FormatDate(), dtBegin.FormatDate() ); |
599 | CPPUNIT_ASSERT_EQUAL( dEnd.DT().FormatDate(), dtEnd.FormatDate() ); | |
ccd6aacd VZ |
600 | } |
601 | } | |
602 | ||
603 | // test wxDateTime -> text conversion | |
604 | void DateTimeTestCase::TestTimeFormat() | |
605 | { | |
606 | // some information may be lost during conversion, so store what kind | |
607 | // of info should we recover after a round trip | |
608 | enum CompareKind | |
609 | { | |
610 | CompareNone, // don't try comparing | |
611 | CompareBoth, // dates and times should be identical | |
9807f995 | 612 | CompareYear, // don't compare centuries (fails for 2 digit years) |
ccd6aacd VZ |
613 | CompareDate, // dates only |
614 | CompareTime // time only | |
615 | }; | |
616 | ||
617 | static const struct | |
618 | { | |
619 | CompareKind compareKind; | |
71ebd60b | 620 | const char *format; |
ccd6aacd VZ |
621 | } formatTestFormats[] = |
622 | { | |
71ebd60b VZ |
623 | { CompareYear, "---> %c" }, // %c could use 2 digit years |
624 | { CompareDate, "Date is %A, %d of %B, in year %Y" }, | |
625 | { CompareYear, "Date is %x, time is %X" }, // %x could use 2 digits | |
626 | { CompareTime, "Time is %H:%M:%S or %I:%M:%S %p" }, | |
627 | { CompareNone, "The day of year: %j, the week of year: %W" }, | |
628 | { CompareDate, "ISO date without separators: %Y%m%d" }, | |
ccd6aacd VZ |
629 | }; |
630 | ||
631 | static const Date formatTestDates[] = | |
632 | { | |
9807f995 VZ |
633 | { 29, wxDateTime::May, 1976, 18, 30, 00, 0.0, wxDateTime::Inv_WeekDay }, |
634 | { 31, wxDateTime::Dec, 1999, 23, 30, 00, 0.0, wxDateTime::Inv_WeekDay }, | |
635 | { 6, wxDateTime::Feb, 1937, 23, 30, 00, 0.0, wxDateTime::Inv_WeekDay }, | |
636 | { 6, wxDateTime::Feb, 1856, 23, 30, 00, 0.0, wxDateTime::Inv_WeekDay }, | |
637 | { 6, wxDateTime::Feb, 1857, 23, 30, 00, 0.0, wxDateTime::Inv_WeekDay }, | |
638 | { 29, wxDateTime::May, 2076, 18, 30, 00, 0.0, wxDateTime::Inv_WeekDay }, | |
639 | { 29, wxDateTime::Feb, 2400, 02, 15, 25, 0.0, wxDateTime::Inv_WeekDay }, | |
ccd6aacd | 640 | #if 0 |
42b62acf | 641 | // Need to add support for BCE dates. |
9807f995 | 642 | { 01, wxDateTime::Jan, -52, 03, 16, 47, 0.0, wxDateTime::Inv_WeekDay }, |
ccd6aacd VZ |
643 | #endif |
644 | }; | |
645 | ||
9807f995 | 646 | for ( size_t d = 0; d < WXSIZEOF(formatTestDates); d++ ) |
ccd6aacd | 647 | { |
9807f995 | 648 | wxDateTime dt = formatTestDates[d].DT(); |
ccd6aacd VZ |
649 | for ( size_t n = 0; n < WXSIZEOF(formatTestFormats); n++ ) |
650 | { | |
71ebd60b | 651 | const char *fmt = formatTestFormats[n].format; |
a6121fc4 FM |
652 | |
653 | // skip the check with %p for those locales which have empty AM/PM strings: | |
654 | // for those locales it's impossible to pass the test with %p... | |
655 | wxString am, pm; | |
656 | wxDateTime::GetAmPmStrings(&am, &pm); | |
657 | if (am.empty() && pm.empty() && wxStrstr(fmt, "%p") != NULL) | |
658 | continue; | |
659 | ||
9807f995 | 660 | wxString s = dt.Format(fmt); |
1bf29a7a | 661 | |
ccd6aacd | 662 | // what can we recover? |
9807f995 | 663 | CompareKind kind = formatTestFormats[n].compareKind; |
ccd6aacd VZ |
664 | |
665 | // convert back | |
666 | wxDateTime dt2; | |
71ebd60b | 667 | const char *result = dt2.ParseFormat(s, fmt); |
ccd6aacd VZ |
668 | if ( !result ) |
669 | { | |
b5f85206 | 670 | // conversion failed - should it have? |
ccd6aacd VZ |
671 | CPPUNIT_ASSERT( kind == CompareNone ); |
672 | } | |
673 | else // conversion succeeded | |
674 | { | |
a6121fc4 FM |
675 | // ParseFormat() should have parsed the entire string or left |
676 | // some final useless strings (e.g. with Italian locale the | |
677 | // 's' string for the first test date looks like | |
678 | // "---> sab 29 mag 1976 18:30:00 CET" | |
679 | // so we just need to ignore CET) | |
680 | CPPUNIT_ASSERT( !*result || strcmp(result, "CET") == 0 ); | |
ccd6aacd VZ |
681 | |
682 | switch ( kind ) | |
683 | { | |
9807f995 VZ |
684 | case CompareYear: |
685 | if ( dt2.GetCentury() != dt.GetCentury() ) | |
686 | { | |
687 | CPPUNIT_ASSERT_EQUAL(dt.GetYear() % 100, | |
688 | dt2.GetYear() % 100); | |
689 | ||
690 | dt2.SetYear(dt.GetYear()); | |
691 | } | |
692 | // fall through and compare everything | |
693 | ||
ccd6aacd | 694 | case CompareBoth: |
9807f995 | 695 | CPPUNIT_ASSERT_EQUAL( dt, dt2 ); |
ccd6aacd VZ |
696 | break; |
697 | ||
698 | case CompareDate: | |
699 | CPPUNIT_ASSERT( dt.IsSameDate(dt2) ); | |
700 | break; | |
701 | ||
702 | case CompareTime: | |
703 | CPPUNIT_ASSERT( dt.IsSameTime(dt2) ); | |
704 | break; | |
d581cac5 VZ |
705 | |
706 | case CompareNone: | |
707 | wxFAIL_MSG( _T("unexpected") ); | |
708 | break; | |
ccd6aacd VZ |
709 | } |
710 | } | |
711 | } | |
712 | } | |
425eee41 | 713 | |
b5f85206 VZ |
714 | wxDateTime dt; |
715 | ||
716 | // test partially specified dates too | |
717 | wxDateTime dtDef(26, wxDateTime::Sep, 2008); | |
718 | CPPUNIT_ASSERT( dt.ParseFormat("17", "%d") ); | |
719 | CPPUNIT_ASSERT_EQUAL( 17, dt.GetDay() ); | |
720 | ||
425eee41 VZ |
721 | // test compilation of some calls which should compile (and not result in |
722 | // ambiguity because of char*<->wxCStrData<->wxString conversions) | |
425eee41 VZ |
723 | wxString s("foo"); |
724 | CPPUNIT_ASSERT( !dt.ParseFormat("foo") ); | |
725 | CPPUNIT_ASSERT( !dt.ParseFormat(wxT("foo")) ); | |
726 | CPPUNIT_ASSERT( !dt.ParseFormat(s) ); | |
727 | CPPUNIT_ASSERT( !dt.ParseFormat(s.c_str()) ); | |
728 | ||
729 | CPPUNIT_ASSERT( !dt.ParseFormat("foo", "%c") ); | |
730 | CPPUNIT_ASSERT( !dt.ParseFormat(wxT("foo"), "%c") ); | |
731 | CPPUNIT_ASSERT( !dt.ParseFormat(s, "%c") ); | |
732 | CPPUNIT_ASSERT( !dt.ParseFormat(s.c_str(), "%c") ); | |
733 | ||
734 | CPPUNIT_ASSERT( !dt.ParseFormat("foo", wxT("%c")) ); | |
735 | CPPUNIT_ASSERT( !dt.ParseFormat(wxT("foo"), wxT("%c")) ); | |
736 | CPPUNIT_ASSERT( !dt.ParseFormat(s, "%c") ); | |
737 | CPPUNIT_ASSERT( !dt.ParseFormat(s.c_str(), wxT("%c")) ); | |
738 | ||
739 | wxString spec("%c"); | |
740 | CPPUNIT_ASSERT( !dt.ParseFormat("foo", spec) ); | |
741 | CPPUNIT_ASSERT( !dt.ParseFormat(wxT("foo"), spec) ); | |
742 | CPPUNIT_ASSERT( !dt.ParseFormat(s, spec) ); | |
743 | CPPUNIT_ASSERT( !dt.ParseFormat(s.c_str(), spec) ); | |
ccd6aacd VZ |
744 | } |
745 | ||
1bf29a7a VZ |
746 | void DateTimeTestCase::TestTimeSpanFormat() |
747 | { | |
748 | static const struct TimeSpanFormatTestData | |
749 | { | |
750 | long h, min, sec, msec; | |
71ebd60b VZ |
751 | const char *fmt; |
752 | const char *result; | |
1bf29a7a VZ |
753 | } testSpans[] = |
754 | { | |
71ebd60b VZ |
755 | { 12, 34, 56, 789, "%H:%M:%S.%l", "12:34:56.789" }, |
756 | { 1, 2, 3, 0, "%H:%M:%S", "01:02:03" }, | |
757 | { 1, 2, 3, 0, "%S", "3723" }, | |
758 | { -1, -2, -3, 0, "%S", "-3723" }, | |
759 | { -1, -2, -3, 0, "%H:%M:%S", "-01:02:03" }, | |
760 | { 26, 0, 0, 0, "%H", "26" }, | |
761 | { 26, 0, 0, 0, "%D, %H", "1, 02" }, | |
762 | { -26, 0, 0, 0, "%H", "-26" }, | |
763 | { -26, 0, 0, 0, "%D, %H", "-1, 02" }, | |
764 | { 219, 0, 0, 0, "%H", "219" }, | |
765 | { 219, 0, 0, 0, "%D, %H", "9, 03" }, | |
766 | { 219, 0, 0, 0, "%E, %D, %H", "1, 2, 03" }, | |
c9e46dea VZ |
767 | { 0, -1, 0, 0, "%H:%M:%S", "-00:01:00" }, |
768 | { 0, 0, -1, 0, "%H:%M:%S", "-00:00:01" }, | |
1bf29a7a VZ |
769 | }; |
770 | ||
771 | for ( size_t n = 0; n < WXSIZEOF(testSpans); n++ ) | |
772 | { | |
773 | const TimeSpanFormatTestData& td = testSpans[n]; | |
774 | wxTimeSpan ts(td.h, td.min, td.sec, td.msec); | |
c9e46dea | 775 | CPPUNIT_ASSERT_EQUAL( td.result, ts.Format(td.fmt) ); |
1bf29a7a VZ |
776 | } |
777 | } | |
778 | ||
ccd6aacd VZ |
779 | void DateTimeTestCase::TestTimeTicks() |
780 | { | |
a669640b VZ |
781 | static const wxDateTime::TimeZone TZ_LOCAL(wxDateTime::Local); |
782 | static const wxDateTime::TimeZone TZ_TEST(wxDateTime::NZST); | |
c4e25288 | 783 | |
a669640b VZ |
784 | // this offset is needed to make the test work in any time zone when we |
785 | // only have expected test results in UTC in testDates | |
786 | static const long tzOffset = TZ_LOCAL.GetOffset() - TZ_TEST.GetOffset(); | |
c4e25288 | 787 | |
ccd6aacd VZ |
788 | for ( size_t n = 0; n < WXSIZEOF(testDates); n++ ) |
789 | { | |
790 | const Date& d = testDates[n]; | |
a669640b | 791 | if ( d.gmticks == -1 ) |
ccd6aacd VZ |
792 | continue; |
793 | ||
a669640b | 794 | wxDateTime dt = d.DT().MakeTimezone(TZ_TEST, true /* no DST */); |
c4e25288 | 795 | |
a669640b VZ |
796 | // GetValue() returns internal UTC-based representation, we need to |
797 | // convert it to local TZ before comparing | |
ece97e28 | 798 | time_t ticks = (dt.GetValue() / 1000).ToLong() + TZ_LOCAL.GetOffset(); |
a669640b VZ |
799 | if ( dt.IsDST() ) |
800 | ticks += 3600; | |
1de532f5 | 801 | CPPUNIT_ASSERT_EQUAL( d.gmticks, ticks + tzOffset ); |
ccd6aacd | 802 | |
c4e25288 | 803 | dt = d.DT().FromTimezone(wxDateTime::UTC); |
ccd6aacd | 804 | ticks = (dt.GetValue() / 1000).ToLong(); |
1de532f5 | 805 | CPPUNIT_ASSERT_EQUAL( d.gmticks, ticks ); |
ccd6aacd VZ |
806 | } |
807 | } | |
808 | ||
8605eb1a VZ |
809 | // test parsing dates in RFC822 format |
810 | void DateTimeTestCase::TestParceRFC822() | |
ccd6aacd VZ |
811 | { |
812 | static const struct ParseTestData | |
813 | { | |
71ebd60b | 814 | const char *rfc822; |
d26adb9d | 815 | Date date; // NB: this should be in UTC |
ccd6aacd VZ |
816 | bool good; |
817 | } parseTestDates[] = | |
818 | { | |
d26adb9d | 819 | { |
71ebd60b | 820 | "Sat, 18 Dec 1999 00:46:40 +0100", |
1cf57808 | 821 | { 17, wxDateTime::Dec, 1999, 23, 46, 40 }, |
d26adb9d VZ |
822 | true |
823 | }, | |
824 | { | |
71ebd60b | 825 | "Wed, 1 Dec 1999 05:17:20 +0300", |
1cf57808 | 826 | { 1, wxDateTime::Dec, 1999, 2, 17, 20 }, |
d26adb9d VZ |
827 | true |
828 | }, | |
829 | { | |
71ebd60b | 830 | "Sun, 28 Aug 2005 03:31:30 +0200", |
cf9f6737 | 831 | { 28, wxDateTime::Aug, 2005, 1, 31, 30 }, |
1cf57808 VZ |
832 | true |
833 | }, | |
834 | ||
835 | { | |
71ebd60b | 836 | "Sat, 18 Dec 1999 10:48:30 -0500", |
cf9f6737 | 837 | { 18, wxDateTime::Dec, 1999, 15, 48, 30 }, |
d26adb9d VZ |
838 | true |
839 | }, | |
cf9f6737 VZ |
840 | |
841 | // seconds are optional according to the RFC | |
842 | { | |
843 | "Sun, 01 Jun 2008 16:30 +0200", | |
844 | { 1, wxDateTime::Jun, 2008, 14, 30, 00 }, | |
845 | true | |
846 | }, | |
847 | ||
848 | // try some bogus ones too | |
849 | { | |
850 | "Sun, 01 Jun 2008 16:30: +0200", | |
851 | { 0 }, | |
852 | false | |
853 | }, | |
ccd6aacd VZ |
854 | }; |
855 | ||
b7c746d0 | 856 | for ( unsigned n = 0; n < WXSIZEOF(parseTestDates); n++ ) |
ccd6aacd | 857 | { |
71ebd60b | 858 | const char * const datestr = parseTestDates[n].rfc822; |
b7c746d0 | 859 | |
ccd6aacd | 860 | wxDateTime dt; |
b7c746d0 | 861 | if ( dt.ParseRfc822Date(datestr) ) |
ccd6aacd | 862 | { |
b7c746d0 VZ |
863 | WX_ASSERT_MESSAGE( |
864 | ("Erroneously parsed \"%s\"", datestr), | |
865 | parseTestDates[n].good | |
866 | ); | |
ccd6aacd | 867 | |
d26adb9d | 868 | wxDateTime dtReal = parseTestDates[n].date.DT().FromUTC(); |
8605eb1a VZ |
869 | CPPUNIT_ASSERT_EQUAL( dtReal, dt ); |
870 | } | |
871 | else // failed to parse | |
872 | { | |
b7c746d0 VZ |
873 | WX_ASSERT_MESSAGE( |
874 | ("Failed to parse \"%s\"", datestr), | |
875 | !parseTestDates[n].good | |
876 | ); | |
8605eb1a VZ |
877 | } |
878 | } | |
879 | } | |
880 | ||
881 | // test parsing dates in free format | |
882 | void DateTimeTestCase::TestDateParse() | |
883 | { | |
884 | static const struct ParseTestData | |
885 | { | |
71ebd60b | 886 | const char *str; |
8605eb1a VZ |
887 | Date date; // NB: this should be in UTC |
888 | bool good; | |
889 | } parseTestDates[] = | |
890 | { | |
71ebd60b VZ |
891 | { "21 Mar 2006", { 21, wxDateTime::Mar, 2006 }, true }, |
892 | { "29 Feb 1976", { 29, wxDateTime::Feb, 1976 }, true }, | |
893 | { "Feb 29 1976", { 29, wxDateTime::Feb, 1976 }, true }, | |
894 | { "31/03/06", { 31, wxDateTime::Mar, 6 }, true }, | |
895 | { "31/03/2006", { 31, wxDateTime::Mar, 2006 }, true }, | |
8605eb1a VZ |
896 | |
897 | // some invalid ones too | |
71ebd60b VZ |
898 | { "29 Feb 2006" }, |
899 | { "31/04/06" }, | |
900 | { "bloordyblop" }, | |
8605eb1a VZ |
901 | }; |
902 | ||
903 | // special cases | |
904 | wxDateTime dt; | |
905 | CPPUNIT_ASSERT( dt.ParseDate(_T("today")) ); | |
906 | CPPUNIT_ASSERT_EQUAL( wxDateTime::Today(), dt ); | |
907 | ||
908 | for ( size_t n = 0; n < WXSIZEOF(parseTestDates); n++ ) | |
909 | { | |
8605eb1a VZ |
910 | if ( dt.ParseDate(parseTestDates[n].str) ) |
911 | { | |
912 | CPPUNIT_ASSERT( parseTestDates[n].good ); | |
913 | ||
804eeca5 VZ |
914 | CPPUNIT_ASSERT_EQUAL( parseTestDates[n].date.DT(), dt ); |
915 | } | |
916 | else // failed to parse | |
917 | { | |
918 | CPPUNIT_ASSERT( !parseTestDates[n].good ); | |
919 | } | |
920 | } | |
921 | } | |
922 | ||
f3f2e255 VZ |
923 | void DateTimeTestCase::TestDateParseISO() |
924 | { | |
925 | static const struct | |
926 | { | |
927 | const char *str; | |
928 | Date date; // NB: this should be in UTC | |
929 | bool good; | |
930 | } parseTestDates[] = | |
931 | { | |
932 | { "2006-03-21", { 21, wxDateTime::Mar, 2006 }, true }, | |
933 | { "1976-02-29", { 29, wxDateTime::Feb, 1976 }, true }, | |
934 | { "0006-03-31", { 31, wxDateTime::Mar, 6 }, true }, | |
935 | ||
936 | // some invalid ones too | |
937 | { "2006:03:31" }, | |
938 | { "31/04/06" }, | |
939 | { "bloordyblop" }, | |
940 | { "" }, | |
941 | }; | |
942 | ||
943 | static const struct | |
944 | { | |
945 | const char *str; | |
946 | wxDateTime::wxDateTime_t hour, min, sec; | |
947 | bool good; | |
948 | } parseTestTimes[] = | |
949 | { | |
950 | { "13:42:17", 13, 42, 17, true }, | |
951 | { "02:17:01", 2, 17, 1, true }, | |
952 | ||
953 | // some invalid ones too | |
954 | { "66:03:31" }, | |
955 | { "31/04/06" }, | |
956 | { "bloordyblop" }, | |
957 | { "" }, | |
958 | }; | |
959 | ||
960 | for ( size_t n = 0; n < WXSIZEOF(parseTestDates); n++ ) | |
961 | { | |
962 | wxDateTime dt; | |
963 | if ( dt.ParseISODate(parseTestDates[n].str) ) | |
964 | { | |
965 | CPPUNIT_ASSERT( parseTestDates[n].good ); | |
966 | ||
967 | CPPUNIT_ASSERT_EQUAL( parseTestDates[n].date.DT(), dt ); | |
968 | ||
969 | for ( size_t m = 0; m < WXSIZEOF(parseTestTimes); m++ ) | |
970 | { | |
971 | wxString dtCombined; | |
972 | dtCombined << parseTestDates[n].str | |
973 | << 'T' | |
974 | << parseTestTimes[m].str; | |
975 | ||
976 | if ( dt.ParseISOCombined(dtCombined) ) | |
977 | { | |
978 | CPPUNIT_ASSERT( parseTestTimes[m].good ); | |
979 | ||
980 | CPPUNIT_ASSERT_EQUAL( parseTestTimes[m].hour, dt.GetHour()) ; | |
981 | CPPUNIT_ASSERT_EQUAL( parseTestTimes[m].min, dt.GetMinute()) ; | |
982 | CPPUNIT_ASSERT_EQUAL( parseTestTimes[m].sec, dt.GetSecond()) ; | |
983 | } | |
984 | else // failed to parse combined date/time | |
985 | { | |
986 | CPPUNIT_ASSERT( !parseTestTimes[m].good ); | |
987 | } | |
988 | } | |
989 | } | |
990 | else // failed to parse | |
991 | { | |
992 | CPPUNIT_ASSERT( !parseTestDates[n].good ); | |
993 | } | |
994 | } | |
995 | } | |
996 | ||
804eeca5 VZ |
997 | void DateTimeTestCase::TestDateTimeParse() |
998 | { | |
999 | static const struct ParseTestData | |
1000 | { | |
71ebd60b | 1001 | const char *str; |
804eeca5 VZ |
1002 | Date date; // NB: this should be in UTC |
1003 | bool good; | |
1004 | } parseTestDates[] = | |
1005 | { | |
71ebd60b | 1006 | { "Thu 22 Nov 2007 07:40:00 PM", |
804eeca5 VZ |
1007 | { 22, wxDateTime::Nov, 2007, 19, 40, 0}, true }, |
1008 | }; | |
1009 | ||
1010 | // special cases | |
1011 | wxDateTime dt; | |
1012 | for ( size_t n = 0; n < WXSIZEOF(parseTestDates); n++ ) | |
1013 | { | |
804eeca5 VZ |
1014 | if ( dt.ParseDateTime(parseTestDates[n].str) ) |
1015 | { | |
1016 | CPPUNIT_ASSERT( parseTestDates[n].good ); | |
1017 | ||
8605eb1a | 1018 | CPPUNIT_ASSERT_EQUAL( parseTestDates[n].date.DT(), dt ); |
ccd6aacd VZ |
1019 | } |
1020 | else // failed to parse | |
1021 | { | |
1022 | CPPUNIT_ASSERT( !parseTestDates[n].good ); | |
1023 | } | |
1024 | } | |
1025 | } | |
1026 | ||
1027 | void DateTimeTestCase::TestTimeArithmetics() | |
1028 | { | |
1029 | static const wxDateSpan testArithmData[] = | |
1030 | { | |
1031 | wxDateSpan::Day(), | |
1032 | wxDateSpan::Week(), | |
1033 | wxDateSpan::Month(), | |
1034 | wxDateSpan::Year(), | |
1035 | }; | |
1036 | ||
1037 | // the test will *not* work with arbitrary date! | |
1038 | wxDateTime dt(2, wxDateTime::Dec, 1999), | |
1039 | dt1, | |
1040 | dt2; | |
1041 | ||
1042 | for ( size_t n = 0; n < WXSIZEOF(testArithmData); n++ ) | |
1043 | { | |
1044 | const wxDateSpan& span = testArithmData[n]; | |
1045 | dt1 = dt + span; | |
1046 | dt2 = dt - span; | |
1047 | ||
1048 | CPPUNIT_ASSERT( dt1 - span == dt ); | |
1049 | CPPUNIT_ASSERT( dt2 + span == dt ); | |
1050 | CPPUNIT_ASSERT( dt2 + 2*span == dt1 ); | |
1051 | } | |
1052 | } | |
1053 | ||
a480d0ab VZ |
1054 | void DateTimeTestCase::TestDSTBug() |
1055 | { | |
1056 | ///////////////////////// | |
1057 | // Test GetEndDST() | |
c6a95dd6 | 1058 | wxDateTime dt = wxDateTime::GetEndDST(2004, wxDateTime::France); |
a480d0ab VZ |
1059 | CPPUNIT_ASSERT_EQUAL(31, (int)dt.GetDay()); |
1060 | CPPUNIT_ASSERT_EQUAL(wxDateTime::Oct, dt.GetMonth()); | |
1061 | CPPUNIT_ASSERT_EQUAL(2004, (int)dt.GetYear()); | |
770882a6 | 1062 | CPPUNIT_ASSERT_EQUAL(1, (int)dt.GetHour()); |
a480d0ab VZ |
1063 | CPPUNIT_ASSERT_EQUAL(0, (int)dt.GetMinute()); |
1064 | CPPUNIT_ASSERT_EQUAL(0, (int)dt.GetSecond()); | |
1065 | CPPUNIT_ASSERT_EQUAL(0, (int)dt.GetMillisecond()); | |
1066 | ||
1067 | ///////////////////////// | |
1068 | // Test ResetTime() | |
1069 | dt.SetHour(5); | |
1070 | CPPUNIT_ASSERT_EQUAL(5, (int)dt.GetHour()); | |
1071 | dt.ResetTime(); | |
1072 | CPPUNIT_ASSERT_EQUAL(31, (int)dt.GetDay()); | |
1073 | CPPUNIT_ASSERT_EQUAL(wxDateTime::Oct, dt.GetMonth()); | |
1074 | CPPUNIT_ASSERT_EQUAL(2004, (int)dt.GetYear()); | |
1075 | CPPUNIT_ASSERT_EQUAL(0, (int)dt.GetHour()); | |
1076 | CPPUNIT_ASSERT_EQUAL(0, (int)dt.GetMinute()); | |
1077 | CPPUNIT_ASSERT_EQUAL(0, (int)dt.GetSecond()); | |
1078 | CPPUNIT_ASSERT_EQUAL(0, (int)dt.GetMillisecond()); | |
1079 | ||
fcae7135 VZ |
1080 | dt.Set(1, 0, 0, 0); |
1081 | CPPUNIT_ASSERT_EQUAL(1, (int)dt.GetHour()); | |
1082 | ||
a480d0ab VZ |
1083 | ///////////////////////// |
1084 | // Test Today() | |
1085 | #ifdef CHANGE_SYSTEM_DATE | |
1086 | { | |
1087 | DateChanger change(2004, 10, 31, 5, 0, 0); | |
1088 | dt = wxDateTime::Today(); | |
1089 | } | |
1090 | ||
1091 | CPPUNIT_ASSERT_EQUAL(31, (int)dt.GetDay()); | |
1092 | CPPUNIT_ASSERT_EQUAL(wxDateTime::Oct, dt.GetMonth()); | |
1093 | CPPUNIT_ASSERT_EQUAL(2004, (int)dt.GetYear()); | |
1094 | CPPUNIT_ASSERT_EQUAL(0, (int)dt.GetHour()); | |
1095 | CPPUNIT_ASSERT_EQUAL(0, (int)dt.GetMinute()); | |
1096 | CPPUNIT_ASSERT_EQUAL(0, (int)dt.GetSecond()); | |
1097 | CPPUNIT_ASSERT_EQUAL(0, (int)dt.GetMillisecond()); | |
1098 | ||
1099 | ///////////////////////// | |
1100 | // Test Set(hour, minute, second, milli) | |
1101 | wxDateTime dt2; | |
1102 | { | |
1103 | DateChanger change(2004, 10, 31, 5, 0, 0); | |
1104 | dt.Set(1, 30, 0, 0); | |
1105 | dt2.Set(5, 30, 0, 0); | |
1106 | } | |
1107 | ||
1108 | CPPUNIT_ASSERT_EQUAL(31, (int)dt.GetDay()); | |
1109 | CPPUNIT_ASSERT_EQUAL(wxDateTime::Oct, dt.GetMonth()); | |
1110 | CPPUNIT_ASSERT_EQUAL(2004, (int)dt.GetYear()); | |
1111 | CPPUNIT_ASSERT_EQUAL(1, (int)dt.GetHour()); | |
1112 | CPPUNIT_ASSERT_EQUAL(30, (int)dt.GetMinute()); | |
1113 | CPPUNIT_ASSERT_EQUAL(0, (int)dt.GetSecond()); | |
1114 | CPPUNIT_ASSERT_EQUAL(0, (int)dt.GetMillisecond()); | |
1115 | ||
1116 | CPPUNIT_ASSERT_EQUAL(31, (int)dt2.GetDay()); | |
1117 | CPPUNIT_ASSERT_EQUAL(wxDateTime::Oct, dt2.GetMonth()); | |
1118 | CPPUNIT_ASSERT_EQUAL(2004, (int)dt2.GetYear()); | |
1119 | CPPUNIT_ASSERT_EQUAL(5, (int)dt2.GetHour()); | |
1120 | CPPUNIT_ASSERT_EQUAL(30, (int)dt2.GetMinute()); | |
1121 | CPPUNIT_ASSERT_EQUAL(0, (int)dt2.GetSecond()); | |
1122 | CPPUNIT_ASSERT_EQUAL(0, (int)dt2.GetMillisecond()); | |
1123 | #endif // CHANGE_SYSTEM_DATE | |
1124 | } | |
1125 | ||
fb96cf85 VZ |
1126 | void DateTimeTestCase::TestDateOnly() |
1127 | { | |
1128 | wxDateTime dt(19, wxDateTime::Jan, 2007, 15, 01, 00); | |
1129 | ||
1130 | static const wxDateTime::wxDateTime_t DATE_ZERO = 0; | |
1131 | CPPUNIT_ASSERT_EQUAL( DATE_ZERO, dt.GetDateOnly().GetHour() ); | |
1132 | CPPUNIT_ASSERT_EQUAL( DATE_ZERO, dt.GetDateOnly().GetMinute() ); | |
1133 | CPPUNIT_ASSERT_EQUAL( DATE_ZERO, dt.GetDateOnly().GetSecond() ); | |
1134 | CPPUNIT_ASSERT_EQUAL( DATE_ZERO, dt.GetDateOnly().GetMillisecond() ); | |
1135 | ||
1136 | dt.ResetTime(); | |
1137 | CPPUNIT_ASSERT_EQUAL( wxDateTime(19, wxDateTime::Jan, 2007), dt ); | |
1138 | ||
1139 | CPPUNIT_ASSERT_EQUAL( wxDateTime::Today(), wxDateTime::Now().GetDateOnly() ); | |
1140 | } | |
1141 | ||
34af0de4 | 1142 | #endif // wxUSE_DATETIME |