New URL for NEMO forge!   http://forge.nemo-ocean.eu

Since March 2022 along with NEMO 4.2 release, the code development moved to a self-hosted GitLab.
This present forge is now archived and remained online for history.
dst_rules.hpp in vendors/XIOS/current/extern/boost/include/boost/date_time – NEMO

source: vendors/XIOS/current/extern/boost/include/boost/date_time/dst_rules.hpp @ 3408

Last change on this file since 3408 was 3408, checked in by rblod, 12 years ago

importing initial XIOS vendor drop

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