• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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
tm_out(const tm & ptr)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
main()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 dx(2004, Apr, 4);
126       time_duration td(2,30,0); // invalid local time in ny_tz
127       local_date_time calcop(dx, 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 dx(2004, Apr, 4);
132       time_duration td(2,30,0); // invalid local time in ny_tz
133       try{
134         local_date_time calcop(dx, 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 dx(2004, Oct, 31);
144       time_duration td(1,30,0); // ambig local time in ny_tz
145       local_date_time calcop(dx, 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 dx(2004, Oct, 31);
150       time_duration td(1,30,0); // ambig local time in ny_tz
151       try{
152         local_date_time calcop(dx, 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& e){
185       check(std::string("Caught expected exception (dst_not_valid) ") + e.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 dx(2004,Apr,4);
203       time_duration td(1,15,0); // local
204       local_date_time lt1(dx,td,ny_tz,false);
205       local_date_time lt2(ptime(dx,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 dx(2004,Oct,31);
216       time_duration td(1,15,0); // local
217       local_date_time lt1(dx,td,ny_tz,true);
218       /*try{
219         //local_date_time lt1(dx,td,ny_tz,false);
220         local_date_time lt1(dx,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(dx,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 dx(2004,Oct,31);
236       time_duration td(1,15,0); // local
237       local_date_time lt1(dx,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 dx(2004,Mar,28);
244       time_duration td(2,15,0); // local; sydney has a weird trans time
245       local_date_time lt1(dx,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 dx(2003, Aug, 28);
270       ptime sv_pt(pos_infin);
271       local_date_time sv_lt(sv_pt, ny_tz);
272       ptime utc_pt(dx, 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(dx, hours(5), az_tz, false);  // 5am local std
277       local_date_time ny_lt(dx, hours(8), ny_tz, true);   // 8am local dst
278       local_date_time au_lt(dx, 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;
293       }catch(std::out_of_range&){
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 
371