testparse_date.cpp 12 KB

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