File indexing completed on 2025-01-18 09:30:38
0001 #ifndef DATE_TIME_DST_RULES_HPP__
0002 #define DATE_TIME_DST_RULES_HPP__
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016 #include "boost/date_time/date_generators.hpp"
0017 #include "boost/date_time/period.hpp"
0018 #include "boost/date_time/date_defs.hpp"
0019 #include <stdexcept>
0020
0021 namespace boost {
0022 namespace date_time {
0023
0024 enum time_is_dst_result {is_not_in_dst, is_in_dst,
0025 ambiguous, invalid_time_label};
0026
0027
0028
0029 template<class date_type_,
0030 class time_duration_type_>
0031 class dst_calculator
0032 {
0033 public:
0034 typedef time_duration_type_ time_duration_type;
0035 typedef date_type_ date_type;
0036
0037
0038
0039
0040
0041
0042
0043
0044
0045
0046
0047 static time_is_dst_result
0048 process_local_dst_start_day(const time_duration_type& time_of_day,
0049 unsigned int dst_start_offset_minutes,
0050 long dst_length_minutes)
0051 {
0052
0053 if (time_of_day < time_duration_type(0,dst_start_offset_minutes,0)) {
0054 return is_not_in_dst;
0055 }
0056 long offset = dst_start_offset_minutes + dst_length_minutes;
0057 if (time_of_day >= time_duration_type(0,offset,0)) {
0058 return is_in_dst;
0059 }
0060 return invalid_time_label;
0061 }
0062
0063
0064
0065
0066
0067
0068
0069
0070
0071
0072 static time_is_dst_result
0073 process_local_dst_end_day(const time_duration_type& time_of_day,
0074 unsigned int dst_end_offset_minutes,
0075 long dst_length_minutes)
0076 {
0077
0078 int offset = dst_end_offset_minutes-dst_length_minutes;
0079 if (time_of_day < time_duration_type(0,offset,0)) {
0080 return is_in_dst;
0081 }
0082 if (time_of_day >= time_duration_type(0,dst_end_offset_minutes,0)) {
0083 return is_not_in_dst;
0084 }
0085 return ambiguous;
0086 }
0087
0088
0089
0090
0091
0092
0093
0094
0095
0096
0097
0098
0099
0100 static time_is_dst_result
0101 local_is_dst(const date_type& current_day,
0102 const time_duration_type& time_of_day,
0103 const date_type& dst_start_day,
0104 const time_duration_type& dst_start_offset,
0105 const date_type& dst_end_day,
0106 const time_duration_type& dst_end_offset,
0107 const time_duration_type& dst_length)
0108 {
0109 unsigned int start_minutes = static_cast<unsigned>(
0110 dst_start_offset.hours() * 60 + dst_start_offset.minutes());
0111 unsigned int end_minutes = static_cast<unsigned>(
0112 dst_end_offset.hours() * 60 + dst_end_offset.minutes());
0113 long length_minutes = static_cast<long>(
0114 dst_length.hours() * 60 + dst_length.minutes());
0115
0116 return local_is_dst(current_day, time_of_day,
0117 dst_start_day, start_minutes,
0118 dst_end_day, end_minutes,
0119 length_minutes);
0120 }
0121
0122
0123
0124
0125
0126
0127
0128
0129
0130
0131
0132
0133
0134
0135
0136 static time_is_dst_result
0137 local_is_dst(const date_type& current_day,
0138 const time_duration_type& time_of_day,
0139 const date_type& dst_start_day,
0140 unsigned int dst_start_offset_minutes,
0141 const date_type& dst_end_day,
0142 unsigned int dst_end_offset_minutes,
0143 long dst_length_minutes)
0144 {
0145
0146 if (dst_start_day < dst_end_day) {
0147 if ((current_day > dst_start_day) && (current_day < dst_end_day)) {
0148 return is_in_dst;
0149 }
0150 if ((current_day < dst_start_day) || (current_day > dst_end_day)) {
0151 return is_not_in_dst;
0152 }
0153 }
0154 else {
0155 if ((current_day < dst_start_day) && (current_day > dst_end_day)) {
0156 return is_not_in_dst;
0157 }
0158 if ((current_day > dst_start_day) || (current_day < dst_end_day)) {
0159 return is_in_dst;
0160 }
0161 }
0162
0163 if (current_day == dst_start_day) {
0164 return process_local_dst_start_day(time_of_day,
0165 dst_start_offset_minutes,
0166 dst_length_minutes);
0167 }
0168
0169 if (current_day == dst_end_day) {
0170 return process_local_dst_end_day(time_of_day,
0171 dst_end_offset_minutes,
0172 dst_length_minutes);
0173 }
0174
0175 return invalid_time_label;
0176 }
0177
0178 };
0179
0180
0181
0182
0183
0184
0185
0186
0187
0188
0189
0190
0191
0192
0193
0194
0195
0196
0197
0198
0199
0200
0201
0202
0203
0204
0205
0206
0207
0208 template<class date_type,
0209 class time_duration_type,
0210 class dst_traits>
0211 class dst_calc_engine
0212 {
0213 public:
0214 typedef typename date_type::year_type year_type;
0215 typedef typename date_type::calendar_type calendar_type;
0216 typedef dst_calculator<date_type, time_duration_type> dstcalc;
0217
0218
0219
0220
0221
0222
0223 static time_is_dst_result local_is_dst(const date_type& d,
0224 const time_duration_type& td)
0225 {
0226
0227 year_type y = d.year();
0228 date_type dst_start = local_dst_start_day(y);
0229 date_type dst_end = local_dst_end_day(y);
0230 return dstcalc::local_is_dst(d,td,
0231 dst_start,
0232 dst_traits::dst_start_offset_minutes(),
0233 dst_end,
0234 dst_traits::dst_end_offset_minutes(),
0235 dst_traits::dst_shift_length_minutes());
0236
0237 }
0238
0239 static bool is_dst_boundary_day(date_type d)
0240 {
0241 year_type y = d.year();
0242 return ((d == local_dst_start_day(y)) ||
0243 (d == local_dst_end_day(y)));
0244 }
0245
0246
0247 static time_duration_type dst_offset()
0248 {
0249 return time_duration_type(0,dst_traits::dst_shift_length_minutes(),0);
0250 }
0251
0252 static date_type local_dst_start_day(year_type year)
0253 {
0254 return dst_traits::local_dst_start_day(year);
0255 }
0256
0257 static date_type local_dst_end_day(year_type year)
0258 {
0259 return dst_traits::local_dst_end_day(year);
0260 }
0261
0262
0263 };
0264
0265
0266
0267
0268
0269
0270 template<class date_type_,
0271 class time_duration_type_,
0272 unsigned int dst_start_offset_minutes=120,
0273 short dst_length_minutes=60>
0274 class us_dst_rules
0275 {
0276 public:
0277 typedef time_duration_type_ time_duration_type;
0278 typedef date_type_ date_type;
0279 typedef typename date_type::year_type year_type;
0280 typedef typename date_type::calendar_type calendar_type;
0281 typedef date_time::last_kday_of_month<date_type> lkday;
0282 typedef date_time::first_kday_of_month<date_type> fkday;
0283 typedef date_time::nth_kday_of_month<date_type> nkday;
0284 typedef dst_calculator<date_type, time_duration_type> dstcalc;
0285
0286
0287
0288
0289
0290
0291 static time_is_dst_result local_is_dst(const date_type& d,
0292 const time_duration_type& td)
0293 {
0294
0295 year_type y = d.year();
0296 date_type dst_start = local_dst_start_day(y);
0297 date_type dst_end = local_dst_end_day(y);
0298 return dstcalc::local_is_dst(d,td,
0299 dst_start,dst_start_offset_minutes,
0300 dst_end, dst_start_offset_minutes,
0301 dst_length_minutes);
0302
0303 }
0304
0305
0306 static bool is_dst_boundary_day(date_type d)
0307 {
0308 year_type y = d.year();
0309 return ((d == local_dst_start_day(y)) ||
0310 (d == local_dst_end_day(y)));
0311 }
0312
0313 static date_type local_dst_start_day(year_type year)
0314 {
0315 if (year >= year_type(2007)) {
0316
0317 nkday ssim(nkday::second, Sunday, date_time::Mar);
0318 return ssim.get_date(year);
0319 } else {
0320
0321 fkday fsia(Sunday, date_time::Apr);
0322 return fsia.get_date(year);
0323 }
0324 }
0325
0326 static date_type local_dst_end_day(year_type year)
0327 {
0328 if (year >= year_type(2007)) {
0329
0330 fkday fsin(Sunday, date_time::Nov);
0331 return fsin.get_date(year);
0332 } else {
0333
0334 lkday lsio(Sunday, date_time::Oct);
0335 return lsio.get_date(year);
0336 }
0337 }
0338
0339 static time_duration_type dst_offset()
0340 {
0341 return time_duration_type(0,dst_length_minutes,0);
0342 }
0343
0344 private:
0345
0346
0347 };
0348
0349
0350 template<class date_type_, class time_duration_type_>
0351 class null_dst_rules
0352 {
0353 public:
0354 typedef time_duration_type_ time_duration_type;
0355 typedef date_type_ date_type;
0356
0357
0358
0359
0360
0361 static time_is_dst_result local_is_dst(const date_type&,
0362 const time_duration_type&)
0363 {
0364 return is_not_in_dst;
0365 }
0366
0367
0368 static time_is_dst_result utc_is_dst(const date_type&,
0369 const time_duration_type&)
0370 {
0371 return is_not_in_dst;
0372 }
0373
0374 static bool is_dst_boundary_day(date_type )
0375 {
0376 return false;
0377 }
0378
0379 static time_duration_type dst_offset()
0380 {
0381 return time_duration_type(0,0,0);
0382 }
0383
0384 };
0385
0386
0387 } }
0388
0389
0390
0391 #endif