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