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