1 /* Copyright (c) 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 #include "boost/date_time/local_time/local_time.hpp"
9 #include "../testfrmwk.hpp"
10 #include <iostream>
11 #include <sstream>
12 #include <string>
13 
14 // for tests that are expected to fail and throw exceptions
15 template<class temporal_type, class exception_type>
failure_test(temporal_type component,const std::string & input,exception_type const &,boost::local_time::local_time_input_facet * facet)16 bool failure_test(temporal_type component,
17                   const std::string& input,
18                   exception_type const& /*except*/,
19                   boost::local_time::local_time_input_facet* facet)
20 {
21   using namespace boost::local_time;
22   bool result = false;
23   std::istringstream iss(input);
24   iss.exceptions(std::ios_base::failbit); // turn on exceptions
25   iss.imbue(std::locale(std::locale::classic(), facet));
26   try {
27     iss >> component;
28   }
29   catch(exception_type& e) {
30     std::cout << "Expected exception caught: \""
31               << e.what() << "\"" << std::endl;
32     result = iss.fail(); // failbit must be set to pass test
33   }
34   catch(...) {
35     result = false;
36   }
37 
38   return result;
39 }
40 
41 // for tests that are expected to fail quietly
42 template<class temporal_type>
failure_test(temporal_type component,const std::string & input,boost::local_time::local_time_input_facet * facet)43 bool failure_test(temporal_type component,
44                   const std::string& input,
45                   boost::local_time::local_time_input_facet* facet)
46 {
47   using namespace boost::local_time;
48   std::istringstream iss(input);
49   /* leave exceptions turned off
50    * iss.exceptions(std::ios_base::failbit); */
51   iss.imbue(std::locale(std::locale::classic(), facet));
52   try {
53     iss >> component;
54   }
55   catch(...) {
56     std::cout << "Caught unexpected exception" << std::endl;
57     return false;
58   }
59 
60   return iss.fail(); // failbit must be set to pass test
61 }
62 
main()63 int main() {
64   using namespace boost::gregorian;
65   using namespace boost::posix_time;
66   using namespace boost::local_time;
67   time_zone_ptr null_zone;
68   local_date_time ldt1(not_a_date_time, null_zone);
69 
70   // verify wide stream works, thorough tests done in narrow stream
71 #if !defined(BOOST_NO_STD_WSTRING)
72   {
73     std::wstringstream ws;
74     ws.str(L"2005-Feb-15 12:15:00 EST-05EDT,M4.1.0,M10.5.0");
75     ws >> ldt1;
76     check("Wide stream, Eastern US, daylight savings, winter, minimal input",
77           ldt1.local_time() == ptime(date(2005,2,15), time_duration(12,15,0)));
78     check("Wide stream, Eastern US, daylight savings, winter, minimal input",
79           ldt1.utc_time() == ptime(date(2005,2,15), time_duration(17,15,0)));
80     check("Wide stream, Eastern US, daylight savings, winter, minimal input", !ldt1.is_dst());
81     ws.str(L"");
82     wlocal_time_input_facet* wfacet = new wlocal_time_input_facet(L"%m/%d/%y %ZP");
83     std::locale loc(std::locale::classic(), wfacet);
84     ws.imbue(loc);
85     ws.str(L"10/31/04 PST-08PDT,M4.1.0,M10.5.0"); // midnight on end transition day, still in dst
86     ws >> ldt1;
87     std::wcout << ldt1.local_time() << std::endl;
88     check("Wide stream, Eastern US, daylight savings, winter, custom format",
89           ldt1.local_time() == ptime(date(2004,10,31), time_duration(0,0,0)));
90     check("Wide stream, Eastern US, daylight savings, winter, custom format",
91           ldt1.utc_time() == ptime(date(2004,10,31), time_duration(7,0,0)));
92     check("Wide stream, Eastern US, daylight savings, winter, custom format", ldt1.is_dst());
93   }
94 #endif // BOOST_NO_STD_WSTRING
95 
96   std::stringstream ss;
97   ss.str("2005-Feb-25 12:15:00 EST-05EDT,M4.1.0,M10.5.0");
98   ss >> ldt1;
99   check("Eastern US, daylight savings, winter, minimal input",
100         ldt1.local_time() == ptime(date(2005,2,25), time_duration(12,15,0)));
101   check("Eastern US, daylight savings, winter, minimal input",
102         ldt1.utc_time() == ptime(date(2005,2,25), time_duration(17,15,0)));
103   check("Eastern US, daylight savings, winter, minimal input", !ldt1.is_dst());
104   ss.str("");
105 
106   ss.str("2005-Aug-25 12:15:00 EST-05EDT,M4.1.0,M10.5.0");
107   ss >> ldt1;
108   check("Eastern US, daylight savings, summer, minimal input",
109         ldt1.local_time() == ptime(date(2005,8,25), time_duration(12,15,0)));
110   check("Eastern US, daylight savings, summer, minimal input",
111         ldt1.utc_time() == ptime(date(2005,8,25), time_duration(16,15,0)));
112   check("Eastern US, daylight savings, summer, minimal input", ldt1.is_dst());
113   ss.str("");
114 
115   ss.str("2005-Apr-03 01:15:00 EST-05EDT,M4.1.0,M10.5.0");
116   ss >> ldt1;
117   check("Eastern US, daylight savings, transition point", !ldt1.is_dst());
118   ldt1 += hours(1);
119   check("Eastern US, daylight savings, transition point", ldt1.is_dst());
120   ss.str("");
121   ss.str("2005-Apr-03 01:15:00 EST-05EDT,93,303");
122   ss >> ldt1;
123   check("Eastern US, daylight savings, transition point", !ldt1.is_dst());
124   ldt1 += hours(1);
125   check("Eastern US, daylight savings, transition point", ldt1.is_dst());
126   ss.str("");
127 
128   ss.str("2005-Oct-30 00:15:00 EST-05EDT,M4.1.0,M10.5.0");
129   ss >> ldt1;
130   check("Eastern US, daylight savings, transition point", ldt1.is_dst());
131   ldt1 += hours(1);
132   check("Eastern US, daylight savings, transition point", ldt1.is_dst());
133   ldt1 += hours(1);
134   check("Eastern US, daylight savings, transition point", !ldt1.is_dst());
135   ss.str("");
136   ss.str("2005-Oct-30 00:15:00 EST-05EDT,93,303");
137   ss >> ldt1;
138   check("Eastern US, daylight savings, transition point", ldt1.is_dst());
139   ldt1 += hours(1);
140   check("Eastern US, daylight savings, transition point", ldt1.is_dst());
141   ldt1 += hours(1);
142   check("Eastern US, daylight savings, transition point", !ldt1.is_dst());
143   ss.str("");
144 
145   ss.str("2005-Aug-25 12:15:00 MST-07");
146   ss >> ldt1;
147   check("Mountain US, no daylight savings",
148         ldt1.local_time() == ptime(date(2005,8,25), time_duration(12,15,0)));
149   check("Mountain US, no daylight savings",
150         ldt1.utc_time() == ptime(date(2005,8,25), time_duration(19,15,0)));
151   check("Mountain US, no daylight savings", !ldt1.is_dst());
152   ss.str("");
153 
154   // insure input & output formats match
155   local_time_facet* out_facet =
156     new local_time_facet(local_time_input_facet::default_time_input_format);
157   std::locale loc(std::locale::classic(), out_facet);
158   ss.imbue(loc);
159   time_zone_ptr syd_tz(new posix_time_zone("EST+10EST,M10.5.0,M3.5.0/03:00"));
160   ptime pt(date(2005,6,12), hours(0));
161   local_date_time ldt2(pt, syd_tz);
162   ss << ldt2;
163   ss >> ldt1;
164   check("Output as input makes match", ldt1 == ldt2);
165   check("Output as input makes match",
166       ldt1.zone()->dst_local_start_time(2004) == ldt2.zone()->dst_local_start_time(2004));
167   ss.str("");
168 
169   time_zone_ptr f_tz(new posix_time_zone("FST+03FDT,90,300"));
170   ldt2 = local_date_time(ptime(date(2005,6,12), hours(0)), f_tz);
171   ss << ldt2;
172   ss >> ldt1;
173   check("Output as input makes match", ldt1 == ldt2);
174   check("Output as input makes match",
175       ldt1.zone()->dst_local_start_time(2004) == ldt2.zone()->dst_local_start_time(2004));
176   ss.str("");
177 
178   // missing input & wrong format tests
179   ss.str("2005-Oct-30 00:15:00");
180   ss >> ldt1;
181   check("Missing time_zone spec makes UTC", ldt1.zone_as_posix_string() == std::string("UTC+00"));
182   check("Missing time_zone spec makes UTC", ldt1.utc_time() == ldt1.local_time());
183   ss.str("");
184   {
185     std::istringstream iss("2005-Aug-25 12:15:00 MST-07");
186     local_time_input_facet* f = new local_time_input_facet("%Y-%b-%d %H:%M:%S %z");
187     std::locale locx(std::locale::classic(), f);
188     iss.imbue(locx);
189     iss >> ldt1;
190     check("Wrong format flag makes UTC", ldt1.zone_as_posix_string() == std::string("UTC+00"));
191     check("Wrong format flag makes UTC", ldt1.utc_time() == ldt1.local_time());
192   }
193 
194 
195   // failure tests: (posix_time_zone) bad_offset, bad_adjustment,
196   // (local_date_time) ambiguous_result, time_label_invalid,
197   // time/date failures already tested
198   ambiguous_result amb_ex("default");
199   time_label_invalid inv_ex("default");
200   check("Failure test ambiguous time label (w/exceptions)",
201         failure_test(ldt1,
202                      "2005-Oct-30 01:15:00 EST-05EDT,M4.1.0,M10.5.0",
203                      amb_ex,
204                      new local_time_input_facet()));
205   check("Failure test ambiguous time label (no exceptions)",
206         failure_test(ldt1,
207                      "2005-Oct-30 01:15:00 EST-05EDT,M4.1.0,M10.5.0",
208                      new local_time_input_facet()));
209   check("Failure test ambiguous time label (w/exceptions)",
210         failure_test(ldt1,
211                      "2005-Oct-30 01:15:00 EST-05EDT,93,303",
212                      amb_ex,
213                      new local_time_input_facet()));
214   check("Failure test ambiguous time label (no exceptions)",
215         failure_test(ldt1,
216                      "2005-Oct-30 01:15:00 EST-05EDT,93,303",
217                      new local_time_input_facet()));
218   check("Failure test invalid time label (w/exceptions)",
219         failure_test(ldt1,
220                      "2005-Apr-03 02:15:00 EST-05EDT,M4.1.0,M10.5.0",
221                      inv_ex,
222                      new local_time_input_facet()));
223   check("Failure test invalid time label (no exceptions)",
224         failure_test(ldt1,
225                      "2005-Apr-03 02:15:00 EST-05EDT,M4.1.0,M10.5.0",
226                      new local_time_input_facet()));
227   check("Failure test invalid time label (w/exceptions)",
228         failure_test(ldt1,
229                      "2005-Apr-03 02:15:00 EST-05EDT,93,303",
230                      inv_ex,
231                      new local_time_input_facet()));
232   check("Failure test invalid time label (no exceptions)",
233         failure_test(ldt1,
234                      "2005-Apr-03 02:15:00 EST-05EDT,93,303",
235                      new local_time_input_facet()));
236 
237 
238   return printTestStats();
239 }
240