testlocal_time.cpp 15 KB

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