]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
1 | /* Copyright (c) 2003-2005 CrystalClear Software, Inc. |
2 | * Subject to the Boost Software License, Version 1.0. | |
3 | * (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt) | |
4 | * Author: Jeff Garland, Bart Garst | |
5 | * $Date$ | |
6 | */ | |
7 | ||
8 | ||
9 | #include "boost/date_time/local_time/custom_time_zone.hpp" | |
10 | #include "boost/date_time/posix_time/posix_time.hpp" | |
11 | #include "boost/date_time/local_time/local_time.hpp" | |
12 | // #include "boost/date_time/local_time/posix_time_zone.hpp" | |
13 | #include "../testfrmwk.hpp" | |
14 | //#include "boost/date_time/c_time.hpp" | |
15 | #include <iostream> | |
16 | ||
17 | #include <sstream> | |
18 | // function eases testing | |
19 | std::string tm_out(const tm& ptr){ | |
20 | std::stringstream ss; | |
21 | ||
22 | ss | |
23 | << ptr.tm_wday << ' ' << ptr.tm_yday << ' ' | |
24 | << std::setw(2) << std::setfill('0') << ptr.tm_mon + 1 << '/' | |
25 | << std::setw(2) << std::setfill('0') << ptr.tm_mday << '/' | |
26 | << std::setw(2) << std::setfill('0') << ptr.tm_year + 1900 << ' ' | |
27 | << std::setw(2) << std::setfill('0') << ptr.tm_hour << ':' | |
28 | << std::setw(2) << std::setfill('0') << ptr.tm_min << ':' | |
29 | << std::setw(2) << std::setfill('0') << ptr.tm_sec << ' '; | |
30 | if(ptr.tm_isdst >= 0){ | |
31 | ss << (ptr.tm_isdst ? "DST" : "STD"); | |
32 | } | |
33 | else{ | |
34 | ss << "DST/STD unknown"; | |
35 | } | |
36 | return ss.str(); | |
37 | } | |
38 | ||
39 | int | |
40 | main() | |
41 | { | |
42 | ||
43 | using namespace boost::gregorian; | |
44 | using namespace boost::posix_time; | |
45 | using namespace boost::local_time; | |
46 | ||
47 | // since local_date_time inherits it's math operations from time, the | |
48 | // tests here only show that the operations work. The thorough testing | |
49 | // of these operations is done in the posix_time tests | |
50 | ||
51 | try { | |
52 | time_zone_ptr az_tz(new posix_time_zone("MST-07")); | |
53 | time_zone_ptr ny_tz(new posix_time_zone("EST-05EDT,M4.1.0,M10.5.0")); | |
54 | // EST & EST for sydney is correct, according to zoneinfo files | |
55 | time_zone_ptr sydney(new posix_time_zone("EST+10EST,M10.5.0,M3.5.0/03:00")); | |
56 | time_zone_ptr null_tz; | |
57 | date d(2003, 12, 20); | |
58 | hours h(12); | |
59 | ptime t(d,h); | |
60 | local_date_time az_time(t, az_tz); // ptime constructor is a UTC time | |
61 | ||
62 | check("Zone abbreviation", az_time.zone()->std_zone_abbrev() == std::string("MST")); | |
63 | check("base offset", az_time.zone()->base_utc_offset() == hours(-7)); | |
64 | check("zone has dst", az_time.zone()->has_dst() == false); | |
65 | check("is_dst check", az_time.is_dst() == false); | |
66 | check("to_string: " + az_time.to_string(), | |
67 | az_time.to_string() == "2003-Dec-20 05:00:00 MST"); | |
68 | ||
69 | ||
70 | ||
71 | std::cout << "\nChecking copy construction" << std::endl; | |
72 | local_date_time az_time2(az_time); //copy constructor | |
73 | // Now test the copy | |
74 | check("is_dst check", az_time2.is_dst() == false); | |
75 | check("to_string: " + az_time2.to_string(), | |
76 | az_time2.to_string() == "2003-Dec-20 05:00:00 MST"); | |
77 | check("zone has dst", az_time2.zone()->has_dst() == false); | |
78 | check("base offset", az_time2.zone()->base_utc_offset() == hours(-7)); | |
79 | ||
80 | ||
81 | std::cout << "\nChecking special_value construction" << std::endl; | |
82 | // since local_date_time inherits its special value operatorations | |
83 | // from time, we only need to show here that they work as thorough | |
84 | // testing is done in the posix_time tests | |
85 | ptime svpt(not_a_date_time); | |
86 | local_date_time sv_time(svpt, ny_tz); | |
87 | check("is special_value", sv_time.is_not_a_date_time()); | |
88 | check("to_string: " + sv_time.to_string(), | |
89 | sv_time.to_string() == "not-a-date-time"); | |
90 | check("is_dst", sv_time.is_dst() == false); | |
91 | local_date_time sv_time2(pos_infin); | |
92 | check("is special_value", sv_time2.is_pos_infinity()); | |
93 | check("to_string: " + sv_time2.to_string(), | |
94 | sv_time2.to_string() == "+infinity"); | |
95 | check("is_dst", sv_time2.is_dst() == false); | |
96 | sv_time2 += days(12); // add a duration to a special value | |
97 | check("Add a duration to a special value", sv_time2.is_pos_infinity()); | |
98 | ||
99 | local_date_time sv_time3(max_date_time, ny_tz); | |
100 | #ifdef BOOST_DATE_TIME_POSIX_TIME_STD_CONFIG | |
101 | check("max_date_time to_string: " + sv_time3.to_string(), | |
102 | sv_time3.to_string() == "9999-Dec-31 18:59:59.999999999 EST"); | |
103 | #else | |
104 | check("max_date_time to_string: " + sv_time3.to_string(), | |
105 | sv_time3.to_string() == "9999-Dec-31 18:59:59.999999 EST"); | |
106 | #endif | |
107 | ||
108 | try { | |
109 | local_date_time sv_time4(min_date_time); | |
110 | check("min_date_time to_string: " + sv_time4.to_string(), | |
111 | sv_time4.to_string() == "1400-Jan-01 00:00:00 UTC"); | |
112 | } | |
113 | catch (std::exception& e) { | |
114 | check("min_date_time to_string -- exception" , false); | |
115 | std::cout << "Exception is : " << e.what() << std::endl; | |
116 | } | |
117 | ||
118 | /** todo -- this will cause an out of range when min_date is adjusted for ny_tz | |
119 | local_date_time sv_time5(min_date_time, ny_tz); | |
120 | std::cout << sv_time5.to_string() << std::endl; | |
121 | **/ | |
122 | ||
123 | std::cout << "\nChecking calc_options construction" << std::endl; | |
124 | { // invalid NADT | |
125 | date d(2004, Apr, 4); | |
126 | time_duration td(2,30,0); // invalid local time in ny_tz | |
127 | local_date_time calcop(d, td, ny_tz, local_date_time::NOT_DATE_TIME_ON_ERROR); | |
128 | check("is NADT", calcop.is_not_a_date_time()); | |
129 | } | |
130 | { // invalid exception | |
131 | date d(2004, Apr, 4); | |
132 | time_duration td(2,30,0); // invalid local time in ny_tz | |
133 | try{ | |
134 | local_date_time calcop(d, td, ny_tz, local_date_time::EXCEPTION_ON_ERROR); | |
135 | check("Did not catch expected exception", false); | |
136 | }catch(time_label_invalid& /*i*/){ | |
137 | check("Caught expected exception", true); | |
138 | }catch(...){ | |
139 | check("Caught unexpected exception", false); | |
140 | } | |
141 | } | |
142 | { // ambig NADT | |
143 | date d(2004, Oct, 31); | |
144 | time_duration td(1,30,0); // ambig local time in ny_tz | |
145 | local_date_time calcop(d, td, ny_tz, local_date_time::NOT_DATE_TIME_ON_ERROR); | |
146 | check("is NADT", calcop.is_not_a_date_time()); | |
147 | } | |
148 | { // ambig exception | |
149 | date d(2004, Oct, 31); | |
150 | time_duration td(1,30,0); // ambig local time in ny_tz | |
151 | try{ | |
152 | local_date_time calcop(d, td, ny_tz, local_date_time::EXCEPTION_ON_ERROR); | |
153 | check("Did not catch expected exception", false); | |
154 | }catch(ambiguous_result& /*a*/){ | |
155 | check("Caught expected exception", true); | |
156 | }catch(...){ | |
157 | check("Caught unexpected exception", false); | |
158 | } | |
159 | } | |
160 | ||
161 | ||
162 | //Now construct with a date and time | |
163 | std::cout << "\nChecking construct with date and time_duration" << std::endl; | |
164 | local_date_time az_time3(d, h, az_tz, false); | |
165 | check("Zone abbreviation", az_time3.zone()->std_zone_abbrev() == std::string("MST")); | |
166 | check("base offset", az_time3.zone()->base_utc_offset() == hours(-7)); | |
167 | check("base offset", az_time3.zone()->has_dst() == false); | |
168 | check("is_dst check", az_time3.is_dst() == false); | |
169 | check("to_string: " + az_time3.to_string(), | |
170 | az_time3.to_string() == "2003-Dec-20 12:00:00 MST"); | |
171 | ||
172 | // construct with a null tz | |
173 | //local_date_time null_tz_time(d, h, null_tz, false); | |
174 | local_date_time null_tz_time(d, h, null_tz, true); | |
175 | // TODO: how to handle calls to null_tz_time.zone()->... | |
176 | check("is_dst check", null_tz_time.is_dst() == false); | |
177 | check("to_string: " + null_tz_time.to_string(), | |
178 | null_tz_time.to_string() == "2003-Dec-20 12:00:00 UTC"); | |
179 | ||
180 | //Now construct with a date and time - invalid parameters | |
181 | try{ | |
182 | local_date_time blt(d, h, ny_tz, true); | |
183 | check("Did not catch expected exception (dst_not_valid)", false); | |
184 | }catch(dst_not_valid& d){ | |
185 | check(std::string("Caught expected exception (dst_not_valid) ") + d.what(), true); | |
186 | }catch(std::exception& e){ | |
187 | check(std::string("Caught unexpected exception ") + e.what(), false); | |
188 | } | |
189 | try{ | |
190 | local_date_time blt(date(2004,Apr,4), time_duration(2,30,0), ny_tz, true); | |
191 | check("Did not catch expected exception (Invalid_Time_Label)", false); | |
192 | }catch(time_label_invalid& e){ | |
193 | check(std::string("Caught expected exception (Invalid_Time_Label) ") + e.what(), true); | |
194 | }catch(std::exception& e){ | |
195 | check(std::string("Caught unexpected exception ") + e.what(), false); | |
196 | } | |
197 | ||
198 | ||
199 | // thorough is_dst() tests, tests againts null_tz and non dst tz are | |
200 | // done where those local times were tested | |
201 | { | |
202 | date d(2004,Apr,4); | |
203 | time_duration td(1,15,0); // local | |
204 | local_date_time lt1(d,td,ny_tz,false); | |
205 | local_date_time lt2(ptime(d,time_duration(6,15,0)), ny_tz); | |
206 | check("are local_times equal", lt1.utc_time() == lt2.utc_time()); | |
207 | check("is_dst - transition in 1", lt1.is_dst() == false); | |
208 | check("is_dst - transition in 2", lt2.is_dst() == false); | |
209 | lt1 += hours(1); | |
210 | lt2 += hours(1); | |
211 | check("is_dst - transition in 1", lt1.is_dst() == true); | |
212 | check("is_dst - transition in 2", lt2.is_dst() == true); | |
213 | } | |
214 | { | |
215 | date d(2004,Oct,31); | |
216 | time_duration td(1,15,0); // local | |
217 | local_date_time lt1(d,td,ny_tz,true); | |
218 | /*try{ | |
219 | //local_date_time lt1(d,td,ny_tz,false); | |
220 | local_date_time lt1(d,td,ny_tz,true); | |
221 | std::cout << "no exception thrown" << std::endl; | |
222 | }catch(time_label_invalid& e){ | |
223 | std::cout << "caught: " << e.what() << std::endl; | |
224 | }*/ | |
225 | local_date_time lt2(ptime(d,time_duration(5,15,0)), ny_tz); | |
226 | check("are local_times equal", lt1.utc_time() == lt2.utc_time()); | |
227 | check("is_dst - transition out 1", lt1.is_dst() == true); | |
228 | check("is_dst - transition out 2", lt2.is_dst() == true); | |
229 | lt1 += hours(1); | |
230 | lt2 += hours(1); | |
231 | check("is_dst - transition out 1", lt1.is_dst() == false); | |
232 | check("is_dst - transition out 2", lt2.is_dst() == false); | |
233 | } | |
234 | { // southern hemisphere | |
235 | date d(2004,Oct,31); | |
236 | time_duration td(1,15,0); // local | |
237 | local_date_time lt1(d,td,sydney,false); | |
238 | check("is_dst - transition in (sydney)", lt1.is_dst() == false); | |
239 | lt1 += hours(1); | |
240 | check("is_dst - transition in (sydney)", lt1.is_dst() == true); | |
241 | } | |
242 | { | |
243 | date d(2004,Mar,28); | |
244 | time_duration td(2,15,0); // local; sydney has a weird trans time | |
245 | local_date_time lt1(d,td,sydney,true); | |
246 | check("is_dst - transition out (sydney)", lt1.is_dst() == true); | |
247 | lt1 += hours(1); | |
248 | check("is_dst - transition out (sydney)", lt1.is_dst() == false); | |
249 | } | |
250 | ||
251 | ||
252 | ||
253 | std::cout << "\nTest conversion of time zone from Arizona to New York" << std::endl; | |
254 | local_date_time ny_time = az_time.local_time_in(ny_tz); | |
255 | check("Zone abbreviation", ny_time.zone()->std_zone_abbrev() == std::string("EST")); | |
256 | check("base offset", ny_time.zone()->base_utc_offset() == hours(-5)); | |
257 | check("base offset", ny_time.zone()->has_dst() == true); | |
258 | check("to_string: " + ny_time.to_string(), | |
259 | ny_time.to_string() == "2003-Dec-20 07:00:00 EST"); | |
260 | ny_time += hours(3); | |
261 | check("to_string after add 3 hours: " + ny_time.to_string(), | |
262 | ny_time.to_string() == "2003-Dec-20 10:00:00 EST"); | |
263 | ny_time += days(3); | |
264 | check("to_string after add 3 days: " + ny_time.to_string(), | |
265 | ny_time.to_string() == "2003-Dec-23 10:00:00 EST"); | |
266 | ||
267 | ||
268 | { // test comparisons & math operations | |
269 | date d(2003, Aug, 28); | |
270 | ptime sv_pt(pos_infin); | |
271 | local_date_time sv_lt(sv_pt, ny_tz); | |
272 | ptime utc_pt(d, hours(12)); | |
273 | // all 4 of the following local times happen at the same instant | |
274 | // so they are all equal | |
275 | local_date_time utc_lt(utc_pt, null_tz); // noon in utc | |
276 | local_date_time az_lt(d, hours(5), az_tz, false); // 5am local std | |
277 | local_date_time ny_lt(d, hours(8), ny_tz, true); // 8am local dst | |
278 | local_date_time au_lt(d, hours(22), sydney, false);// 10pm local std | |
279 | ||
280 | check("local_date_time to tm", | |
281 | std::string("4 239 08/28/2003 05:00:00 STD") == tm_out(to_tm(az_lt))); | |
282 | check("local_date_time to tm", | |
283 | std::string("4 239 08/28/2003 08:00:00 DST") == tm_out(to_tm(ny_lt))); | |
284 | check("local_date_time to tm", | |
285 | std::string("4 239 08/28/2003 22:00:00 STD") == tm_out(to_tm(au_lt))); | |
286 | ||
287 | try{ | |
288 | local_date_time ldt(not_a_date_time); | |
289 | tm ldt_tm = to_tm(ldt); | |
290 | check("Exception not thrown (special_value to_tm)", false); | |
291 | //does nothing useful but stops compiler from complaining about unused ldt_tm | |
292 | std::cout << ldt_tm.tm_sec << std::endl; | |
b32b8144 | 293 | }catch(std::out_of_range&){ |
7c673cae FG |
294 | check("Caught expected exception (special_value to_tm)", true); |
295 | }catch(...){ | |
296 | check("Caught un-expected exception (special_value to_tm)", false); | |
297 | } | |
298 | // check that all are equal to sv_pt | |
299 | check("local == utc", az_lt == utc_lt); | |
300 | check("local == utc", ny_lt == utc_lt); | |
301 | check("local == utc", au_lt == utc_lt); | |
302 | check("local <= utc", au_lt <= utc_lt); | |
303 | check("local >= utc", au_lt >= utc_lt); | |
304 | check("local == local", az_lt == ny_lt); | |
305 | check("local < local", az_lt < ny_lt+seconds(1)); | |
306 | check("local > local", az_lt+seconds(1) > ny_lt); | |
307 | check("local <= local", az_lt <= ny_lt); | |
308 | check("local >= local", az_lt >= ny_lt); | |
309 | check("local != local", az_lt+seconds(1) != ny_lt); | |
310 | ||
311 | au_lt += hours(1); | |
312 | check("local != after +=", au_lt != utc_lt); | |
313 | check("local <= after +=", utc_lt <= au_lt); | |
314 | check("local >= after +=", au_lt >= utc_lt); | |
315 | check("local < after +=", utc_lt < au_lt); | |
316 | check("local > after +=", au_lt > utc_lt); | |
317 | au_lt -= hours(1); | |
318 | check("local == utc after -=", au_lt == utc_lt); | |
319 | ||
320 | check("local + days", | |
321 | (az_lt + days(2)).to_string() == "2003-Aug-30 05:00:00 MST"); | |
322 | check("local - days", | |
323 | (az_lt - days(2)).to_string() == "2003-Aug-26 05:00:00 MST"); | |
324 | check("local += days", | |
325 | (az_lt += days(2)).to_string() == "2003-Aug-30 05:00:00 MST"); | |
326 | check("local -= days", | |
327 | (az_lt -= days(2)).to_string() == "2003-Aug-28 05:00:00 MST"); | |
328 | check("local + time_duration", | |
329 | (az_lt + hours(2)).to_string() == "2003-Aug-28 07:00:00 MST"); | |
330 | check("local - time_duration", | |
331 | (az_lt - hours(2)).to_string() == "2003-Aug-28 03:00:00 MST"); | |
332 | // special_values is more thoroughly tested in posix_time | |
333 | check("pos_infinity > local", sv_lt > au_lt); | |
334 | local_date_time sv_lt2(sv_lt + days(2)); | |
335 | check("pos_infin + duration == pos_infin", sv_lt2 == sv_lt); | |
336 | ||
337 | #if defined(BOOST_DATE_TIME_OPTIONAL_GREGORIAN_TYPES) | |
338 | months m(2); | |
339 | years y(2); | |
340 | check("Local + months", | |
341 | (az_lt + m).to_string() == "2003-Oct-28 05:00:00 MST"); | |
342 | az_lt += m; | |
343 | check("Local += months", | |
344 | az_lt.to_string() == "2003-Oct-28 05:00:00 MST"); | |
345 | check("Local - months", | |
346 | (az_lt - m).to_string() == "2003-Aug-28 05:00:00 MST"); | |
347 | az_lt -= m; | |
348 | check("Local -= months", | |
349 | az_lt.to_string() == "2003-Aug-28 05:00:00 MST"); | |
350 | check("Local + years", | |
351 | (az_lt + y).to_string() == "2005-Aug-28 05:00:00 MST"); | |
352 | az_lt += y; | |
353 | check("Local += years", | |
354 | az_lt.to_string() == "2005-Aug-28 05:00:00 MST"); | |
355 | check("Local - years", | |
356 | (az_lt - y).to_string() == "2003-Aug-28 05:00:00 MST"); | |
357 | az_lt -= y; | |
358 | check("Local -= years", | |
359 | az_lt.to_string() == "2003-Aug-28 05:00:00 MST"); | |
360 | ||
361 | #endif // BOOST_DATE_TIME_OPTIONAL_GREGORIAN_TYPES | |
362 | } | |
363 | } | |
364 | catch(std::exception& e) { | |
365 | check(std::string("test failed due to exception: ") + e.what(), false); | |
366 | } | |
367 | ||
368 | return printTestStats(); | |
369 | } | |
370 |