testposix_time_zone.cpp 9.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221
  1. /* Copyright (c) 2003-2004 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/gregorian/gregorian.hpp"
  8. //#include "boost/date_time/local_time/time_zone.hpp"
  9. #include "../testfrmwk.hpp"
  10. #include "boost/date_time/local_time/posix_time_zone.hpp"
  11. #include <string>
  12. #include <iostream>
  13. int main(){
  14. using namespace boost::local_time;
  15. using namespace boost::posix_time;
  16. using namespace boost::gregorian;
  17. std::string specs[] = {"MST-07", "MST-07:00:00","EST-05EDT,M4.1.0,M10.5.0", "EST-05:00:00EDT+01:00:00,M4.1.0/02:00:00,M10.5.0/02:00:00","PST-08PDT,J46/1:30,J310","PST-08PDT,45,310/0:30:00"};
  18. posix_time_zone nyc1(specs[2]);
  19. posix_time_zone nyc2(specs[3]);
  20. time_duration td = hours(-5);
  21. check("Has DST", nyc1.has_dst() && nyc2.has_dst());
  22. check("UTC offset", nyc1.base_utc_offset() == td);
  23. check("UTC offsets match", nyc1.base_utc_offset() == nyc2.base_utc_offset());
  24. check("Abbrevs", nyc1.std_zone_abbrev() == std::string("EST"));
  25. check("Abbrevs", nyc2.std_zone_abbrev() == std::string("EST"));
  26. check("Abbrevs", nyc1.dst_zone_abbrev() == std::string("EDT"));
  27. check("Abbrevs", nyc2.dst_zone_abbrev() == std::string("EDT"));
  28. // names not available for posix_time_zone, abbrevs used in their place
  29. check("Names", nyc1.std_zone_name() == std::string("EST"));
  30. check("Names", nyc2.std_zone_name() == std::string("EST"));
  31. check("Names", nyc1.dst_zone_name() == std::string("EDT"));
  32. check("Names", nyc2.dst_zone_name() == std::string("EDT"));
  33. td = hours(1);
  34. check("dst offset", nyc1.dst_offset() == td);
  35. check("dst offsets match", nyc1.dst_offset() == nyc2.dst_offset());
  36. check("dst start", nyc1.dst_local_start_time(2003) ==
  37. ptime(date(2003,Apr,6),time_duration(2,0,0)));
  38. check("dst starts match", nyc1.dst_local_start_time(2003) ==
  39. nyc2.dst_local_start_time(2003));
  40. check("dst end", nyc1.dst_local_end_time(2003) ==
  41. ptime(date(2003,Oct,26),time_duration(2,0,0)));
  42. check("dst ends match", nyc1.dst_local_end_time(2003) ==
  43. nyc2.dst_local_end_time(2003));
  44. check("to posix string",
  45. nyc1.to_posix_string() == std::string("EST-05EDT+01,M4.1.0/02:00,M10.5.0/02:00"));
  46. check("to posix string",
  47. nyc2.to_posix_string() == std::string("EST-05EDT+01,M4.1.0/02:00,M10.5.0/02:00"));
  48. posix_time_zone az1(specs[0]);
  49. posix_time_zone az2(specs[1]);
  50. td = hours(-7);
  51. check("Has DST", !az1.has_dst() && !az2.has_dst());
  52. check("UTC offset", az1.base_utc_offset() == td);
  53. check("UTC offsets match", az1.base_utc_offset() == az2.base_utc_offset());
  54. check("dst start in non-dst zone",
  55. az1.dst_local_start_time(2005) == ptime(not_a_date_time));
  56. check("dst end in non-dst zone",
  57. az2.dst_local_end_time(2005) == ptime(not_a_date_time));
  58. check("Abbrevs", az1.std_zone_abbrev() == std::string("MST"));
  59. check("Abbrevs", az2.std_zone_abbrev() == std::string("MST"));
  60. // non-dst zones default to empty strings for dst names & abbrevs
  61. check("Abbrevs", az1.dst_zone_abbrev() == std::string(""));
  62. check("Abbrevs", az2.dst_zone_abbrev() == std::string(""));
  63. check("Names", az1.std_zone_name() == std::string("MST"));
  64. check("Names", az2.std_zone_name() == std::string("MST"));
  65. check("Names", az1.dst_zone_name() == std::string(""));
  66. check("Names", az2.dst_zone_name() == std::string(""));
  67. check("to posix string",
  68. az1.to_posix_string() == std::string("MST-07"));
  69. check("to posix string",
  70. az2.to_posix_string() == std::string("MST-07"));
  71. // bizzar time zone spec to fully test parsing
  72. std::cout << "\nFictitious time zone" << std::endl;
  73. posix_time_zone bz("BST+11:21:15BDT-00:28,M2.2.4/03:15:42,M11.5.2/01:08:53");
  74. check("hast dst", bz.has_dst());
  75. check("UTC offset", bz.base_utc_offset() == time_duration(11,21,15));
  76. check("Abbrev", bz.std_zone_abbrev() == std::string("BST"));
  77. check("Abbrev", bz.dst_zone_abbrev() == std::string("BDT"));
  78. check("dst offset", bz.dst_offset() == time_duration(0,-28,0));
  79. check("dst start", bz.dst_local_start_time(1962) ==
  80. ptime(date(1962,Feb,8),time_duration(3,15,42)));
  81. check("dst end", bz.dst_local_end_time(1962) ==
  82. ptime(date(1962,Nov,27),time_duration(1,8,53)));
  83. // only checking start & end rules w/ 'J' notation
  84. std::cout << "\n'J' notation Start/End rule tests..." << std::endl;
  85. posix_time_zone la1(specs[4]); // "PST-08PDT,J124,J310"
  86. //posix_time_zone la1("PST-08PDT,J1,J365");// Jan1/Dec31
  87. check("dst start", la1.dst_local_start_time(2003) ==
  88. ptime(date(2003,Feb,15),time_duration(1,30,0)));
  89. check("dst end", la1.dst_local_end_time(2003) ==
  90. ptime(date(2003,Nov,6),time_duration(2,0,0)));
  91. /* NOTE: la1 was created from a 'J' notation string but to_posix_string
  92. * returns an 'n' notation string. The difference between the two
  93. * is Feb-29 is always counted in an 'n' notation string and numbering
  94. * starts at zero ('J' notation starts at one).
  95. * Every possible date spec that can be written in 'J' notation can also
  96. * be written in 'n' notation. The reverse is not true so 'n' notation
  97. * is used as the output for to_posix_string(). */
  98. check("to posix string",
  99. la1.to_posix_string() == std::string("PST-08PDT+01,45/01:30,310/02:00"));
  100. // only checking start & end rules w/ 'n' notation
  101. std::cout << "\n'n' notation Start/End rule tests..." << std::endl;
  102. posix_time_zone la2(specs[5]); // "PST-08PDT,124,310"
  103. //posix_time_zone la2("PST-08PDT,0,365");// Jan1/Dec31
  104. check("dst start", la2.dst_local_start_time(2003) ==
  105. ptime(date(2003,Feb,15),time_duration(2,0,0)));
  106. check("dst end", la2.dst_local_end_time(2003) ==
  107. ptime(date(2003,Nov,6),time_duration(0,30,0)));
  108. check("to posix string",
  109. la2.to_posix_string() == std::string("PST-08PDT+01,45/02:00,310/00:30"));
  110. // bad posix time zone strings tests
  111. std::cout << "\nInvalid time zone string tests..." << std::endl;
  112. try {
  113. posix_time_zone badz("EST-13");
  114. check("Exception not thrown: bad UTC offset", false);
  115. }catch(bad_offset& boff){
  116. std::string msg(boff.what());
  117. check("Exception caught: "+msg , true);
  118. }
  119. try {
  120. posix_time_zone badz("EST-5EDT24:00:01,J124/1:30,J310");
  121. check("Exception not thrown: bad DST adjust", false);
  122. }catch(bad_adjustment& badj){
  123. std::string msg(badj.what());
  124. check("Exception caught: "+msg , true);
  125. }
  126. try {
  127. posix_time_zone badz("EST-5EDT01:00:00,J124/-1:30,J310");
  128. check("Exception not thrown: bad DST start/end offset", false);
  129. }catch(bad_offset& boff){
  130. std::string msg(boff.what());
  131. check("Exception caught: "+msg , true);
  132. }
  133. try {
  134. posix_time_zone badz("EST-5EDT01:00:00,J124/1:30,J370");
  135. check("Exception not thrown: invalid date spec", false);
  136. }catch(boost::gregorian::bad_day_of_month& boff){
  137. std::string msg(boff.what());
  138. check("Exception caught: "+msg , true);
  139. }catch(boost::gregorian::bad_month& boff){
  140. std::string msg(boff.what());
  141. check("Exception caught: "+msg , true);
  142. }catch(...){
  143. check("Unexpected exception caught: ", false);
  144. }
  145. std::cout << "\nTest some Central Europe specs" << std::endl;
  146. //Test a timezone spec on the positive side of the UTC line.
  147. //This is the time for central europe which is one hour in front of UTC
  148. //Note these Summer time transition rules aren't actually correct.
  149. posix_time_zone cet_tz("CET+01:00:00EDT+01:00:00,M4.1.0/02:00:00,M10.5.0/02:00:00");
  150. check("Has DST", cet_tz.has_dst());
  151. check("UTC offset", cet_tz.base_utc_offset() == hours(1));
  152. check("Abbrevs", cet_tz.std_zone_abbrev() == std::string("CET"));
  153. // check("Abbrevs", nyc2.std_zone_abbrev() == std::string("EST"));
  154. std::cout << "\nTest some Central Austrialia UTC+8:30" << std::endl;
  155. //Test a timezone spec on the positive side of the UTC line.
  156. //This is the time for central europe which is one hour in front of UTC
  157. //Note these Summer time transition rules aren't actually correct.
  158. posix_time_zone caus_tz("CAS+08:30:00CDT+01:00:00,M4.1.0/02:00:00,M10.5.0/02:00:00");
  159. check("Has DST", caus_tz.has_dst());
  160. check("UTC offset", caus_tz.base_utc_offset() == hours(8)+minutes(30));
  161. check("Abbrevs", caus_tz.std_zone_abbrev() == std::string("CAS"));
  162. // check("Abbrevs", nyc2.std_zone_abbrev() == std::string("EST"));
  163. {
  164. /**** first/last of month Julian & non-Julian tests ****/
  165. // Mar-01 & Oct-31, count begins at 1
  166. std::string spec("FST+3FDT,J60,J304");
  167. posix_time_zone fl_1(spec);
  168. check("Julian First/last of month", fl_1.dst_local_start_time(2003) ==
  169. ptime(date(2003,Mar,1),hours(2)));
  170. check("Julian First/last of month", fl_1.dst_local_end_time(2003) ==
  171. ptime(date(2003,Oct,31),hours(2)));
  172. check("Julian First/last of month", fl_1.dst_local_start_time(2004) ==
  173. ptime(date(2004,Mar,1),hours(2)));
  174. check("Julian First/last of month", fl_1.dst_local_end_time(2004) ==
  175. ptime(date(2004,Oct,31),hours(2)));
  176. // Mar-01 & Oct-31 Non-leap year, count begins at 0
  177. spec = "FST+3FDT,59,304"; // "304" is not a mistake here, see posix_time_zone docs
  178. posix_time_zone fl_2(spec);
  179. try{
  180. check("Non-Julian First/last of month", fl_2.dst_local_start_time(2003) ==
  181. ptime(date(2003,Mar,1),hours(2)));
  182. }catch(std::exception&){
  183. check("Expected exception caught for Non-Julian day of 59, in non-leap year (Feb-29)", true);
  184. }
  185. check("Non-Julian First/last of month", fl_2.dst_local_end_time(2003) ==
  186. ptime(date(2003,Oct,31),hours(2)));
  187. // Mar-01 & Oct-31 leap year, count begins at 0
  188. spec = "FST+3FDT,60,304";
  189. posix_time_zone fl_3(spec);
  190. check("Non-Julian First/last of month", fl_3.dst_local_start_time(2004) ==
  191. ptime(date(2004,Mar,1),hours(2)));
  192. check("Non-Julian First/last of month", fl_3.dst_local_end_time(2004) ==
  193. ptime(date(2004,Oct,31),hours(2)));
  194. }
  195. printTestStats();
  196. return 0;
  197. }