]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
1 | /* Copyright (c) 2002,2003,2005 CrystalClear Software, Inc. |
2 | * Use, modification and distribution is subject to the | |
3 | * Boost Software License, Version 1.0. (See accompanying | |
4 | * file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt) | |
5 | * Author: Jeff Garland, Bart Garst | |
6 | */ | |
7 | ||
8 | #include "boost/date_time/gregorian/gregorian.hpp" | |
9 | #include "../testfrmwk.hpp" | |
10 | #include "boost/lexical_cast.hpp" | |
11 | #include <iostream> | |
12 | #include <string> | |
13 | ||
14 | // missing or misspelled parts of date string tests | |
15 | // 'output_str' will be overwritten with what() from caught exception | |
16 | bool failure_tests(std::string date_spec, | |
17 | std::string& output_str) | |
18 | { | |
19 | using namespace boost::gregorian; | |
20 | bool result = false; | |
21 | date d(not_a_date_time); | |
22 | try { | |
23 | d = from_simple_string(date_spec); | |
24 | } | |
25 | catch(bad_year& by){ // ex: "205-Jan-15" | |
26 | result = true; | |
27 | output_str = by.what(); | |
28 | } | |
29 | catch(bad_month& bm){ // ex: "2005-Jsn-15" | |
30 | result = true; | |
31 | output_str = bm.what(); | |
32 | } | |
33 | catch(bad_day_of_month& bd){ // ex: "2005-Jan-51" | |
34 | result = true; | |
35 | output_str = bd.what(); | |
36 | } | |
37 | catch(...){ | |
38 | // test failed - unexpected exception, leave result set to false | |
39 | } | |
40 | return result; | |
41 | } | |
42 | ||
43 | int | |
44 | main() | |
45 | { | |
46 | ||
47 | ||
48 | // Examples from 8601 | |
49 | // Full date | |
50 | // Extended CCYY-MM-DD | |
51 | std::string s("2001-10-5"); | |
52 | ||
53 | //This one aborts gcc2.95.3 on mandrake 8.1 linux with | |
54 | //bad lexical cast? | |
55 | try { | |
56 | boost::gregorian::date d(boost::gregorian::from_string(s)); | |
57 | check("check year", d.year() == 2001); | |
58 | check("check month", d.month() == 10); | |
59 | check("check day", d.day() == 5); | |
60 | } | |
61 | catch(std::exception& e) { | |
62 | check("parse 2001-10-5", false); | |
63 | std::cout << "Fail: " << e.what() << std::endl; | |
64 | } | |
65 | ||
66 | { | |
67 | using namespace boost::gregorian; | |
68 | // date objects from strings & strings to date objects | |
69 | date d(2000, 2, 29); | |
70 | date d2 = from_string("2000-2-29"); | |
71 | check("2000-2-29", d2 == d); | |
72 | date d3 = from_string("2000-FEB-29"); | |
73 | check("2000-FEB-29 (uppercase)", d3 == d); | |
74 | date d4 = from_string("2000-february-29"); | |
75 | check("2000-february-29 (lowercase)", d4 == d); | |
76 | date d5 = from_string(to_simple_string(d)); | |
77 | check("date to string to date", d5 == d); | |
78 | date d6 = from_string(to_iso_extended_string(d)); | |
79 | check("date to string to date", d6 == d); | |
80 | date d7 = from_us_string("Feb-29-2000"); | |
81 | check("date from month-day-year string", d7 == d); | |
82 | date d8 = from_uk_string("29-Feb-2000"); | |
83 | check("date from day-month-year string", d8 == d); | |
84 | { | |
85 | std::string s("20050229"); // no Feb-29 in 2005 | |
86 | date d(not_a_date_time); | |
87 | try { | |
88 | d = date_from_iso_string(s); | |
89 | check("Expected exception not thrown: from ISO string (bad_day_of_month)", false); | |
90 | std::cout << date_from_iso_string(s) << std::endl; | |
91 | } | |
b32b8144 | 92 | catch(bad_day_of_month&) { |
7c673cae FG |
93 | check("Caught expected exception: bad_day_of_month ", true); |
94 | } | |
95 | catch(...) { | |
96 | check("Caught unexpected exception", false); | |
97 | } | |
98 | /* not currently passing due to a bug in boost::offset_separator (reported 2005-Aug-02) | |
99 | s = "2005022"; // missing a digit | |
100 | try { | |
101 | d = date_from_iso_string(s); | |
102 | check("Expected exception not thrown: from ISO string (missing digit)", false); | |
103 | std::cout << date_from_iso_string(s) << std::endl; | |
104 | } | |
105 | catch(bad_day_of_month& e) { | |
106 | check("Caught expected exception: bad_day_of_month ", true); | |
107 | } | |
108 | catch(...) { | |
109 | check("Caught unexpected exception", false); | |
110 | } | |
111 | */ | |
112 | s = "20050228"; // now it's correct | |
113 | d = date_from_iso_string(s); | |
114 | check("from ISO string", date(2005,Feb,28) == d); | |
115 | } | |
116 | ||
117 | date d9 = from_us_string(__DATE__); | |
118 | std::cout << "Today's date: " << to_simple_string(d9) << std::endl; | |
119 | date d10 = from_us_string("Feb 29, 2000"); | |
120 | std::cout << "With comma: " << to_simple_string(d10) << std::endl; | |
121 | check("american date with comma: Feb 29, 2000 ", d10 == d); | |
122 | ||
123 | date d11 = from_us_string("feb 29 2000"); | |
124 | check("american date with comma: feb 29 2000 ", d11 == d); | |
125 | ||
126 | // test for missing or misspelled date spec components | |
127 | std::string output_str("unexpected exception caught"); | |
128 | check("Year misspelled/out of range: " + output_str, | |
129 | failure_tests("205-Jan-15", output_str)); | |
130 | output_str = "unexpected exception caught"; | |
131 | check("Month misspelled: " + output_str, | |
132 | failure_tests("2005-Jsn-15", output_str)); | |
133 | output_str = "unexpected exception caught"; | |
134 | check("Day out of range: " + output_str, | |
135 | failure_tests("2005-Jan-55", output_str)); | |
136 | output_str = "unexpected exception caught"; | |
137 | check("Missing month and day: " + output_str, | |
138 | failure_tests("2005", output_str)); | |
139 | output_str = "unexpected exception caught"; | |
140 | check("Missing day: " + output_str, | |
141 | failure_tests("2005-Jan", output_str)); | |
142 | ||
143 | ||
144 | #if defined(BOOST_DATE_TIME_NO_LOCALE) || defined(BOOST_NO_STD_ITERATOR_TRAITS) || !defined(USE_DATE_TIME_PRE_1_33_FACET_IO) | |
145 | ||
146 | //TODO -- all these PRE_1_33 exclusions need to be removed. In the meantime, don't make | |
147 | //this stuff fail. | |
148 | #if defined(USE_DATE_TIME_PRE_1_33_FACET_IO) | |
149 | check("input streaming for date not available", false); // force a failure | |
150 | #endif | |
151 | #else | |
152 | { | |
153 | std::stringstream ss("2000-2-29"); | |
154 | ss >> d2; | |
155 | check("2000-2-29 stream-in", d2 == d); | |
156 | } | |
157 | { | |
158 | std::stringstream ss("2000-FEB-29"); | |
159 | ss >> d2; | |
160 | //std::cout << d2 << std::endl; | |
161 | check("2000-FEB-29 stream-in (uppercase)", d2 == d); | |
162 | } | |
163 | { | |
164 | std::stringstream ss("2000-february-29"); | |
165 | ss >> d2; | |
166 | check("2000-february-29 stream-in (lowercase)", d2 == d); | |
167 | } | |
168 | // the removed (3) tests require a stream manipulator for date_order | |
169 | // and date_separator (not yet implemented) | |
170 | /*{ | |
171 | std::stringstream ss("Feb-29-2000"); | |
172 | ss >> d2; | |
173 | check("date from month-day-year string stream-in", d2 == d); | |
174 | } | |
175 | { | |
176 | std::stringstream ss("29-Feb-2000"); | |
177 | ss >> d2; | |
178 | check("date from day-month-year string stream-in", d2 == d); | |
179 | } | |
180 | { | |
181 | std::stringstream ss("Feb 29, 2000"); | |
182 | ss >> d2; | |
183 | check("american date with comma: Feb 29, 2000 stream-in", d2 == d); | |
184 | }*/ | |
185 | #endif //BOOST_DATE_TIME_NO_LOCALE | |
186 | ||
187 | ||
188 | ||
189 | // check proper range | |
190 | d = date(2001, 1, 1); | |
191 | d2 = from_string("2001-Jan-1"); | |
192 | d3 = from_string("2001-January-1"); | |
193 | check("January", d == d2); | |
194 | check("January", d == d3); | |
195 | d = date(2001, 12, 1); | |
196 | d2 = from_string("2001-Dec-1"); | |
197 | d3 = from_string("2001-December-1"); | |
198 | check("December", d == d2); | |
199 | check("December", d == d3); | |
200 | #if defined(BOOST_NO_STD_ITERATOR_TRAITS) | |
201 | check("date from stream not available: no std iterator traits", false); | |
202 | #else | |
203 | // from stream | |
204 | d = date(2000, 10, 31); | |
205 | std::stringstream ss(""); | |
206 | ss << "2000-Oct-31 is Halloween 2k!"; | |
207 | std::istream_iterator<std::string> iter(ss), eos; | |
208 | check("from stream - stringstream", d == from_stream(iter, eos)); | |
209 | #if !(defined(BOOST_NO_STD_WSTRING)) | |
210 | #if !(defined(BOOST_DATE_TIME_NO_WISTREAM_ITERATOR)) | |
211 | std::wstringstream ws; | |
212 | ws << "2000-Oct-31 is Halloween 2k!"; | |
213 | std::istream_iterator<std::wstring, wchar_t> witer(ws), weos; | |
214 | check("from stream - wstringstream", d == from_stream(witer, weos)); | |
215 | #endif // NO_WSTREAM_ITERATOR | |
216 | #endif // BOOST_NO_WSTRING | |
217 | char d2_string[] = {"2000-10-31 is Halloween 2k!"}; | |
218 | char* end = d2_string + sizeof(d2_string) - 1; | |
219 | check("from stream - char[]", d == from_stream(d2_string, end)); | |
220 | ||
221 | std::string s1_string("2000-Oct-31 is Halloween 2k!"); | |
222 | std::string::iterator s1_start = s1_string.begin(); | |
223 | std::string::iterator s1_end = s1_string.end(); | |
224 | check("from stream - string", d == from_stream(s1_start, s1_end)); | |
225 | #ifndef BOOST_NO_STD_WSTRING | |
226 | std::wstring w1_string(boost::lexical_cast<std::wstring>("2000-Oct-31 is Halloween 2k!")); | |
227 | std::wstring::iterator w1_start = w1_string.begin(); | |
228 | std::wstring::iterator w1_end = w1_string.end(); | |
229 | check("from stream - wstring", d == from_stream(w1_start, w1_end)); | |
230 | #endif // BOOST_NO_STD_WSTRING | |
231 | #endif // BOOST_NO_STD_ITERATOR_TRAITS | |
232 | /* date objects from strings & strings to date objects | |
233 | * with misspelled months */ | |
234 | try { | |
235 | date bd = from_string("2002-Jull-4"); | |
236 | std::cout << "Shouldn't be reached." << | |
237 | boost::gregorian::to_simple_string(bd) << std::endl; | |
238 | } | |
239 | catch(boost::gregorian::bad_month&){ | |
240 | check("bad spelling 'Jull'", true); | |
241 | } | |
242 | catch(std::exception& e){ | |
243 | check("bad spelling", false); | |
244 | std::cout << "Fail: " << e.what() << std::endl; | |
245 | } | |
246 | } | |
247 | ||
248 | ||
249 | try { | |
250 | std::string s2("2001-12-41"); //oops should be 31 | |
251 | boost::gregorian::date bad_day(boost::gregorian::from_string(s2)); //won't construct | |
252 | check("check bad day", false); | |
253 | //The line below won't execute, but make the compiler think | |
254 | //we are using bad day.... | |
255 | std::cout << "Oh oh, this shouldn't be reached: " | |
256 | << boost::gregorian::to_iso_string(bad_day) << std::endl; | |
257 | ||
258 | } | |
259 | catch(boost::gregorian::bad_day_of_month&) { //expected | |
260 | check("check bad day", true); | |
261 | } | |
262 | catch(std::exception& e) { | |
263 | //oops wrong exception | |
264 | check("check bad day", false); | |
265 | std::cout << "Fail: " << e.what() << std::endl; | |
266 | } | |
267 | ||
268 | try { | |
269 | std::string s2("2001-02-29"); //oops should be 28 | |
270 | boost::gregorian::date bad_day(boost::gregorian::from_string(s2)); //won't construct | |
271 | check("check bad leap year", false); | |
272 | //The line below won't execute, but make the compiler think | |
273 | //we are using bad day.... | |
274 | std::cout << "Oh oh, this shouldn't be reached: " | |
275 | << boost::gregorian::to_iso_string(bad_day) << std::endl; | |
276 | ||
277 | } | |
278 | catch(boost::gregorian::bad_day_of_month&) { //expected | |
279 | check("check bad leap year", true); | |
280 | } | |
281 | catch(std::exception& e) { | |
282 | //oops wrong exception | |
283 | check("check bad leap year", false); | |
284 | std::cout << "Fail: " << e.what() << std::endl; | |
285 | } | |
286 | ||
287 | try { | |
288 | std::string s2("2001-14-1"); //oops should be <= 12 | |
289 | boost::gregorian::date bad_month(boost::date_time::parse_date<boost::gregorian::date>(s2)); | |
290 | check("check bad month", false); //fail the test | |
291 | //The line below won't execute, but make the compiler think | |
292 | //we are using bad day.... | |
293 | std::cout << "Oh oh, this shouldn't be reached: " | |
294 | << boost::gregorian::to_iso_string(bad_month) << std::endl; | |
295 | ||
296 | } | |
297 | catch(boost::gregorian::bad_month&) { //expected | |
298 | check("check bad month", true); | |
299 | } | |
300 | catch(std::exception& e) { | |
301 | //oops wrong exception | |
302 | check("check bad month", false); | |
303 | std::cout << "Fail: " << e.what() << std::endl; | |
304 | } | |
305 | ||
306 | //This one aborts gcc2.95.3 on mandrake 8.1 linux with | |
307 | //bad lexical cast? | |
308 | try { | |
309 | //Example of ISO Standard -- CCYYMMDD | |
310 | using namespace boost::gregorian; | |
311 | std::string ud("20011009"); //2001-Oct-09 | |
312 | date d1(boost::gregorian::from_undelimited_string(ud)); | |
313 | // std::cout << to_string(d1) << std::endl; | |
314 | check("undelimited date string", d1 == date(2001,Oct,9)); | |
315 | ||
316 | ||
317 | std::string ad("2001/10/09"); | |
318 | date d2(boost::date_time::parse_date<date>(ad)); | |
319 | check("check american date", d2 == date(2001,Oct,9)); | |
320 | } | |
321 | catch(std::exception& e) { | |
322 | check("more parsing", false); | |
323 | std::cout << "Fail: " << e.what() << std::endl; | |
324 | } | |
325 | ||
326 | using namespace boost::gregorian; | |
327 | std::string s2("2003-07-28"); | |
328 | date d2(from_string(s2)); | |
329 | check("check date", d2.month() == 7 && | |
330 | d2.year() == 2003 && | |
331 | d2.day() == 28); | |
332 | // std::string s1("2001-Oct-5"); | |
333 | // gregorian::date d1(parse_date<gregorian::date>(s1)); | |
334 | // check("check month", d1.month() == 10); | |
335 | ||
336 | ||
337 | //Check that the from_string and to_string can be reversed | |
338 | date d10(2003, 10, 19); | |
339 | std::string d10s = to_simple_string(d10); | |
340 | date d11 = from_simple_string(d10s); | |
341 | check("to from string inversion", d10 == d11); | |
342 | ||
343 | try { | |
344 | using namespace boost::gregorian; | |
345 | std::string ud(""); //empty string error sf bug# 1155556 | |
346 | date d1(from_simple_string(ud)); | |
347 | check("empty string", false); //should never reach this piont | |
b32b8144 | 348 | (void)d1; |
7c673cae FG |
349 | } |
350 | catch(std::exception& e) { | |
351 | check(std::string("empty string parse (exception expected): ") + e.what(), true); | |
352 | } | |
353 | ||
354 | ||
355 | //Calendar Week + Day Number | |
356 | // CCYYWwwDThhmmss | |
357 | // 1986W105T | |
358 | // week == 10 day=5 | |
359 | // see page 5 | |
360 | ||
361 | ||
362 | //Duration rep | |
363 | //CCYYMMDDThhmmss/PnYnMnDTnHnMnS | |
364 | ||
365 | return printTestStats(); | |
366 | ||
367 | } | |
368 |