annotate DEPENDENCIES/generic/include/boost/date_time/dst_rules.hpp @ 125:34e428693f5d vext

Vext -> Repoint
author Chris Cannam
date Thu, 14 Jun 2018 11:15:39 +0100
parents c530137014c0
children
rev   line source
Chris@16 1 #ifndef DATE_TIME_DST_RULES_HPP__
Chris@16 2 #define DATE_TIME_DST_RULES_HPP__
Chris@16 3
Chris@16 4 /* Copyright (c) 2002,2003, 2007 CrystalClear Software, Inc.
Chris@16 5 * Use, modification and distribution is subject to the
Chris@16 6 * Boost Software License, Version 1.0. (See accompanying
Chris@16 7 * file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
Chris@16 8 * Author: Jeff Garland, Bart Garst
Chris@101 9 * $Date$
Chris@16 10 */
Chris@16 11
Chris@16 12 /*! @file dst_rules.hpp
Chris@16 13 Contains template class to provide static dst rule calculations
Chris@16 14 */
Chris@16 15
Chris@16 16 #include "boost/date_time/date_generators.hpp"
Chris@16 17 #include "boost/date_time/period.hpp"
Chris@16 18 #include "boost/date_time/date_defs.hpp"
Chris@16 19 #include <stdexcept>
Chris@16 20
Chris@16 21 namespace boost {
Chris@16 22 namespace date_time {
Chris@16 23
Chris@16 24 enum time_is_dst_result {is_not_in_dst, is_in_dst,
Chris@16 25 ambiguous, invalid_time_label};
Chris@16 26
Chris@16 27
Chris@16 28 //! Dynamic class used to caluclate dst transition information
Chris@16 29 template<class date_type_,
Chris@16 30 class time_duration_type_>
Chris@16 31 class dst_calculator
Chris@16 32 {
Chris@16 33 public:
Chris@16 34 typedef time_duration_type_ time_duration_type;
Chris@16 35 typedef date_type_ date_type;
Chris@16 36
Chris@16 37 //! Check the local time offset when on dst start day
Chris@16 38 /*! On this dst transition, the time label between
Chris@16 39 * the transition boundary and the boudary + the offset
Chris@16 40 * are invalid times. If before the boundary then still
Chris@16 41 * not in dst.
Chris@16 42 *@param time_of_day Time offset in the day for the local time
Chris@16 43 *@param dst_start_offset_minutes Local day offset for start of dst
Chris@16 44 *@param dst_length_minutes Number of minutes to adjust clock forward
Chris@16 45 *@retval status of time label w.r.t. dst
Chris@16 46 */
Chris@16 47 static time_is_dst_result
Chris@16 48 process_local_dst_start_day(const time_duration_type& time_of_day,
Chris@16 49 unsigned int dst_start_offset_minutes,
Chris@16 50 long dst_length_minutes)
Chris@16 51 {
Chris@16 52 //std::cout << "here" << std::endl;
Chris@16 53 if (time_of_day < time_duration_type(0,dst_start_offset_minutes,0)) {
Chris@16 54 return is_not_in_dst;
Chris@16 55 }
Chris@16 56 long offset = dst_start_offset_minutes + dst_length_minutes;
Chris@16 57 if (time_of_day >= time_duration_type(0,offset,0)) {
Chris@16 58 return is_in_dst;
Chris@16 59 }
Chris@16 60 return invalid_time_label;
Chris@16 61 }
Chris@16 62
Chris@16 63 //! Check the local time offset when on the last day of dst
Chris@16 64 /*! This is the calculation for the DST end day. On that day times
Chris@16 65 * prior to the conversion time - dst_length (1 am in US) are still
Chris@16 66 * in dst. Times between the above and the switch time are
Chris@16 67 * ambiguous. Times after the start_offset are not in dst.
Chris@16 68 *@param time_of_day Time offset in the day for the local time
Chris@16 69 *@param dst_end_offset_minutes Local time of day for end of dst
Chris@16 70 *@retval status of time label w.r.t. dst
Chris@16 71 */
Chris@16 72 static time_is_dst_result
Chris@16 73 process_local_dst_end_day(const time_duration_type& time_of_day,
Chris@16 74 unsigned int dst_end_offset_minutes,
Chris@16 75 long dst_length_minutes)
Chris@16 76 {
Chris@16 77 //in US this will be 60 so offset in day is 1,0,0
Chris@16 78 int offset = dst_end_offset_minutes-dst_length_minutes;
Chris@16 79 if (time_of_day < time_duration_type(0,offset,0)) {
Chris@16 80 return is_in_dst;
Chris@16 81 }
Chris@16 82 if (time_of_day >= time_duration_type(0,dst_end_offset_minutes,0)) {
Chris@16 83 return is_not_in_dst;
Chris@16 84 }
Chris@16 85 return ambiguous;
Chris@16 86 }
Chris@16 87
Chris@16 88 //! Calculates if the given local time is dst or not
Chris@16 89 /*! Determines if the time is really in DST or not. Also checks for
Chris@16 90 * invalid and ambiguous.
Chris@16 91 * @param current_day The day to check for dst
Chris@16 92 * @param time_of_day Time offset within the day to check
Chris@16 93 * @param dst_start_day Starting day of dst for the given locality
Chris@16 94 * @param dst_start_offset Time offset within day for dst boundary
Chris@16 95 * @param dst_end_day Ending day of dst for the given locality
Chris@16 96 * @param dst_end_offset Time offset within day given in dst for dst boundary
Chris@16 97 * @param dst_length lenght of dst adjusment
Chris@16 98 * @retval The time is either ambiguous, invalid, in dst, or not in dst
Chris@16 99 */
Chris@16 100 static time_is_dst_result
Chris@16 101 local_is_dst(const date_type& current_day,
Chris@16 102 const time_duration_type& time_of_day,
Chris@16 103 const date_type& dst_start_day,
Chris@16 104 const time_duration_type& dst_start_offset,
Chris@16 105 const date_type& dst_end_day,
Chris@16 106 const time_duration_type& dst_end_offset,
Chris@16 107 const time_duration_type& dst_length_minutes)
Chris@16 108 {
Chris@16 109 unsigned int start_minutes =
Chris@16 110 dst_start_offset.hours() * 60 + dst_start_offset.minutes();
Chris@16 111 unsigned int end_minutes =
Chris@16 112 dst_end_offset.hours() * 60 + dst_end_offset.minutes();
Chris@16 113 long length_minutes =
Chris@16 114 dst_length_minutes.hours() * 60 + dst_length_minutes.minutes();
Chris@16 115
Chris@16 116 return local_is_dst(current_day, time_of_day,
Chris@16 117 dst_start_day, start_minutes,
Chris@16 118 dst_end_day, end_minutes,
Chris@16 119 length_minutes);
Chris@16 120 }
Chris@16 121
Chris@16 122 //! Calculates if the given local time is dst or not
Chris@16 123 /*! Determines if the time is really in DST or not. Also checks for
Chris@16 124 * invalid and ambiguous.
Chris@16 125 * @param current_day The day to check for dst
Chris@16 126 * @param time_of_day Time offset within the day to check
Chris@16 127 * @param dst_start_day Starting day of dst for the given locality
Chris@16 128 * @param dst_start_offset_minutes Offset within day for dst
Chris@16 129 * boundary (eg 120 for US which is 02:00:00)
Chris@16 130 * @param dst_end_day Ending day of dst for the given locality
Chris@16 131 * @param dst_end_offset_minutes Offset within day given in dst for dst
Chris@16 132 * boundary (eg 120 for US which is 02:00:00)
Chris@16 133 * @param dst_length_minutes Length of dst adjusment (eg: 60 for US)
Chris@16 134 * @retval The time is either ambiguous, invalid, in dst, or not in dst
Chris@16 135 */
Chris@16 136 static time_is_dst_result
Chris@16 137 local_is_dst(const date_type& current_day,
Chris@16 138 const time_duration_type& time_of_day,
Chris@16 139 const date_type& dst_start_day,
Chris@16 140 unsigned int dst_start_offset_minutes,
Chris@16 141 const date_type& dst_end_day,
Chris@16 142 unsigned int dst_end_offset_minutes,
Chris@16 143 long dst_length_minutes)
Chris@16 144 {
Chris@16 145 //in northern hemisphere dst is in the middle of the year
Chris@16 146 if (dst_start_day < dst_end_day) {
Chris@16 147 if ((current_day > dst_start_day) && (current_day < dst_end_day)) {
Chris@16 148 return is_in_dst;
Chris@16 149 }
Chris@16 150 if ((current_day < dst_start_day) || (current_day > dst_end_day)) {
Chris@16 151 return is_not_in_dst;
Chris@16 152 }
Chris@16 153 }
Chris@16 154 else {//southern hemisphere dst is at begining /end of year
Chris@16 155 if ((current_day < dst_start_day) && (current_day > dst_end_day)) {
Chris@16 156 return is_not_in_dst;
Chris@16 157 }
Chris@16 158 if ((current_day > dst_start_day) || (current_day < dst_end_day)) {
Chris@16 159 return is_in_dst;
Chris@16 160 }
Chris@16 161 }
Chris@16 162
Chris@16 163 if (current_day == dst_start_day) {
Chris@16 164 return process_local_dst_start_day(time_of_day,
Chris@16 165 dst_start_offset_minutes,
Chris@16 166 dst_length_minutes);
Chris@16 167 }
Chris@16 168
Chris@16 169 if (current_day == dst_end_day) {
Chris@16 170 return process_local_dst_end_day(time_of_day,
Chris@16 171 dst_end_offset_minutes,
Chris@16 172 dst_length_minutes);
Chris@16 173 }
Chris@16 174 //you should never reach this statement
Chris@16 175 return invalid_time_label;
Chris@16 176 }
Chris@16 177
Chris@16 178 };
Chris@16 179
Chris@16 180
Chris@16 181 //! Compile-time configurable daylight savings time calculation engine
Chris@16 182 /* This template provides the ability to configure a daylight savings
Chris@16 183 * calculation at compile time covering all the cases. Unfortunately
Chris@16 184 * because of the number of dimensions related to daylight savings
Chris@16 185 * calculation the number of parameters is high. In addition, the
Chris@16 186 * start and end transition rules are complex types that specify
Chris@16 187 * an algorithm for calculation of the starting day and ending
Chris@16 188 * day of daylight savings time including the month and day
Chris@16 189 * specifications (eg: last sunday in October).
Chris@16 190 *
Chris@16 191 * @param date_type A type that represents dates, typically gregorian::date
Chris@16 192 * @param time_duration_type Used for the offset in the day calculations
Chris@16 193 * @param dst_traits A set of traits that define the rules of dst
Chris@16 194 * calculation. The dst_trait must include the following:
Chris@16 195 * start_rule_functor - Rule to calculate the starting date of a
Chris@16 196 * dst transition (eg: last_kday_of_month).
Chris@16 197 * start_day - static function that returns month of dst start for
Chris@16 198 * start_rule_functor
Chris@16 199 * start_month -static function that returns day or day of week for
Chris@16 200 * dst start of dst
Chris@16 201 * end_rule_functor - Rule to calculate the end of dst day.
Chris@16 202 * end_day - static fucntion that returns end day for end_rule_functor
Chris@16 203 * end_month - static function that returns end month for end_rule_functor
Chris@16 204 * dst_start_offset_minutes - number of minutes from start of day to transition to dst -- 120 (or 2:00 am) is typical for the U.S. and E.U.
Chris@16 205 * dst_start_offset_minutes - number of minutes from start of day to transition off of dst -- 180 (or 3:00 am) is typical for E.U.
Chris@16 206 * dst_length_minutes - number of minutes that dst shifts clock
Chris@16 207 */
Chris@16 208 template<class date_type,
Chris@16 209 class time_duration_type,
Chris@16 210 class dst_traits>
Chris@16 211 class dst_calc_engine
Chris@16 212 {
Chris@16 213 public:
Chris@16 214 typedef typename date_type::year_type year_type;
Chris@16 215 typedef typename date_type::calendar_type calendar_type;
Chris@16 216 typedef dst_calculator<date_type, time_duration_type> dstcalc;
Chris@16 217
Chris@16 218 //! Calculates if the given local time is dst or not
Chris@16 219 /*! Determines if the time is really in DST or not. Also checks for
Chris@16 220 * invalid and ambiguous.
Chris@16 221 * @retval The time is either ambiguous, invalid, in dst, or not in dst
Chris@16 222 */
Chris@16 223 static time_is_dst_result local_is_dst(const date_type& d,
Chris@16 224 const time_duration_type& td)
Chris@16 225 {
Chris@16 226
Chris@16 227 year_type y = d.year();
Chris@16 228 date_type dst_start = local_dst_start_day(y);
Chris@16 229 date_type dst_end = local_dst_end_day(y);
Chris@16 230 return dstcalc::local_is_dst(d,td,
Chris@16 231 dst_start,
Chris@16 232 dst_traits::dst_start_offset_minutes(),
Chris@16 233 dst_end,
Chris@16 234 dst_traits::dst_end_offset_minutes(),
Chris@16 235 dst_traits::dst_shift_length_minutes());
Chris@16 236
Chris@16 237 }
Chris@16 238
Chris@16 239 static bool is_dst_boundary_day(date_type d)
Chris@16 240 {
Chris@16 241 year_type y = d.year();
Chris@16 242 return ((d == local_dst_start_day(y)) ||
Chris@16 243 (d == local_dst_end_day(y)));
Chris@16 244 }
Chris@16 245
Chris@16 246 //! The time of day for the dst transition (eg: typically 01:00:00 or 02:00:00)
Chris@16 247 static time_duration_type dst_offset()
Chris@16 248 {
Chris@16 249 return time_duration_type(0,dst_traits::dst_shift_length_minutes(),0);
Chris@16 250 }
Chris@16 251
Chris@16 252 static date_type local_dst_start_day(year_type year)
Chris@16 253 {
Chris@16 254 return dst_traits::local_dst_start_day(year);
Chris@16 255 }
Chris@16 256
Chris@16 257 static date_type local_dst_end_day(year_type year)
Chris@16 258 {
Chris@16 259 return dst_traits::local_dst_end_day(year);
Chris@16 260 }
Chris@16 261
Chris@16 262
Chris@16 263 };
Chris@16 264
Chris@16 265 //! Depricated: Class to calculate dst boundaries for US time zones
Chris@16 266 /* Use dst_calc_engine instead.
Chris@16 267 * In 2007 US/Canada DST rules changed
Chris@16 268 * (http://en.wikipedia.org/wiki/Energy_Policy_Act_of_2005#Change_to_daylight_saving_time).
Chris@16 269 */
Chris@16 270 template<class date_type_,
Chris@16 271 class time_duration_type_,
Chris@16 272 unsigned int dst_start_offset_minutes=120, //from start of day
Chris@16 273 short dst_length_minutes=60> //1 hour == 60 min in US
Chris@16 274 class us_dst_rules
Chris@16 275 {
Chris@16 276 public:
Chris@16 277 typedef time_duration_type_ time_duration_type;
Chris@16 278 typedef date_type_ date_type;
Chris@16 279 typedef typename date_type::year_type year_type;
Chris@16 280 typedef typename date_type::calendar_type calendar_type;
Chris@16 281 typedef date_time::last_kday_of_month<date_type> lkday;
Chris@16 282 typedef date_time::first_kday_of_month<date_type> fkday;
Chris@16 283 typedef date_time::nth_kday_of_month<date_type> nkday;
Chris@16 284 typedef dst_calculator<date_type, time_duration_type> dstcalc;
Chris@16 285
Chris@16 286 //! Calculates if the given local time is dst or not
Chris@16 287 /*! Determines if the time is really in DST or not. Also checks for
Chris@16 288 * invalid and ambiguous.
Chris@16 289 * @retval The time is either ambiguous, invalid, in dst, or not in dst
Chris@16 290 */
Chris@16 291 static time_is_dst_result local_is_dst(const date_type& d,
Chris@16 292 const time_duration_type& td)
Chris@16 293 {
Chris@16 294
Chris@16 295 year_type y = d.year();
Chris@16 296 date_type dst_start = local_dst_start_day(y);
Chris@16 297 date_type dst_end = local_dst_end_day(y);
Chris@16 298 return dstcalc::local_is_dst(d,td,
Chris@16 299 dst_start,dst_start_offset_minutes,
Chris@16 300 dst_end, dst_start_offset_minutes,
Chris@16 301 dst_length_minutes);
Chris@16 302
Chris@16 303 }
Chris@16 304
Chris@16 305
Chris@16 306 static bool is_dst_boundary_day(date_type d)
Chris@16 307 {
Chris@16 308 year_type y = d.year();
Chris@16 309 return ((d == local_dst_start_day(y)) ||
Chris@16 310 (d == local_dst_end_day(y)));
Chris@16 311 }
Chris@16 312
Chris@16 313 static date_type local_dst_start_day(year_type year)
Chris@16 314 {
Chris@16 315 if (year >= year_type(2007)) {
Chris@16 316 //second sunday in march
Chris@16 317 nkday ssim(nkday::second, Sunday, gregorian::Mar);
Chris@16 318 return ssim.get_date(year);
Chris@16 319 } else {
Chris@16 320 //first sunday in april
Chris@16 321 fkday fsia(Sunday, gregorian::Apr);
Chris@16 322 return fsia.get_date(year);
Chris@16 323 }
Chris@16 324 }
Chris@16 325
Chris@16 326 static date_type local_dst_end_day(year_type year)
Chris@16 327 {
Chris@16 328 if (year >= year_type(2007)) {
Chris@16 329 //first sunday in november
Chris@16 330 fkday fsin(Sunday, gregorian::Nov);
Chris@16 331 return fsin.get_date(year);
Chris@16 332 } else {
Chris@16 333 //last sunday in october
Chris@16 334 lkday lsio(Sunday, gregorian::Oct);
Chris@16 335 return lsio.get_date(year);
Chris@16 336 }
Chris@16 337 }
Chris@16 338
Chris@16 339 static time_duration_type dst_offset()
Chris@16 340 {
Chris@16 341 return time_duration_type(0,dst_length_minutes,0);
Chris@16 342 }
Chris@16 343
Chris@16 344 private:
Chris@16 345
Chris@16 346
Chris@16 347 };
Chris@16 348
Chris@16 349 //! Used for local time adjustments in places that don't use dst
Chris@16 350 template<class date_type_, class time_duration_type_>
Chris@16 351 class null_dst_rules
Chris@16 352 {
Chris@16 353 public:
Chris@16 354 typedef time_duration_type_ time_duration_type;
Chris@16 355 typedef date_type_ date_type;
Chris@16 356
Chris@16 357
Chris@16 358 //! Calculates if the given local time is dst or not
Chris@16 359 /*! @retval Always is_not_in_dst since this is for zones without dst
Chris@16 360 */
Chris@16 361 static time_is_dst_result local_is_dst(const date_type&,
Chris@16 362 const time_duration_type&)
Chris@16 363 {
Chris@16 364 return is_not_in_dst;
Chris@16 365 }
Chris@16 366
Chris@16 367 //! Calculates if the given utc time is in dst
Chris@16 368 static time_is_dst_result utc_is_dst(const date_type&,
Chris@16 369 const time_duration_type&)
Chris@16 370 {
Chris@16 371 return is_not_in_dst;
Chris@16 372 }
Chris@16 373
Chris@16 374 static bool is_dst_boundary_day(date_type /*d*/)
Chris@16 375 {
Chris@16 376 return false;
Chris@16 377 }
Chris@16 378
Chris@16 379 static time_duration_type dst_offset()
Chris@16 380 {
Chris@16 381 return time_duration_type(0,0,0);
Chris@16 382 }
Chris@16 383
Chris@16 384 };
Chris@16 385
Chris@16 386
Chris@16 387 } } //namespace date_time
Chris@16 388
Chris@16 389
Chris@16 390
Chris@16 391 #endif