annotate DEPENDENCIES/generic/include/boost/date_time/local_time_adjustor.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_LOCAL_TIME_ADJUSTOR_HPP__
Chris@16 2 #define DATE_TIME_LOCAL_TIME_ADJUSTOR_HPP__
Chris@16 3
Chris@16 4 /* Copyright (c) 2002,2003 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
Chris@101 9 * $Date$
Chris@16 10 */
Chris@16 11
Chris@16 12 /*! @file local_time_adjustor.hpp
Chris@16 13 Time adjustment calculations for local times
Chris@16 14 */
Chris@16 15
Chris@16 16 #include <stdexcept>
Chris@16 17 #include <boost/throw_exception.hpp>
Chris@16 18 #include <boost/date_time/compiler_config.hpp>
Chris@16 19 #include <boost/date_time/date_generators.hpp>
Chris@16 20 #include <boost/date_time/dst_rules.hpp>
Chris@16 21 #include <boost/date_time/time_defs.hpp> // boost::date_time::dst_flags
Chris@16 22 #include <boost/date_time/special_defs.hpp> // not_a_date_time
Chris@16 23
Chris@16 24 namespace boost {
Chris@16 25 namespace date_time {
Chris@16 26
Chris@16 27
Chris@16 28 //! Provides a base offset adjustment from utc
Chris@16 29 template<class time_duration_type,
Chris@16 30 short hours, unsigned short minutes = 0>
Chris@16 31 class utc_adjustment
Chris@16 32 {
Chris@16 33 public:
Chris@16 34 static time_duration_type local_to_utc_base_offset()
Chris@16 35 {
Chris@16 36 time_duration_type td(hours,minutes,0);
Chris@16 37 return td.invert_sign();
Chris@16 38 }
Chris@16 39 static time_duration_type utc_to_local_base_offset()
Chris@16 40 {
Chris@16 41 return time_duration_type(hours,minutes,0);
Chris@16 42 }
Chris@16 43 };
Chris@16 44
Chris@16 45
Chris@16 46
Chris@16 47 //! Allow sliding utc adjustment with fixed dst rules
Chris@16 48 template<class time_type, class dst_rules>
Chris@16 49 class dynamic_local_time_adjustor : public dst_rules
Chris@16 50 {
Chris@16 51 public:
Chris@16 52 typedef typename time_type::time_duration_type time_duration_type;
Chris@16 53 typedef typename time_type::date_type date_type;
Chris@16 54
Chris@16 55 dynamic_local_time_adjustor(time_duration_type utc_offset) :
Chris@16 56 utc_offset_(utc_offset)
Chris@16 57 {}
Chris@16 58
Chris@16 59 //! Presumes local time
Chris@16 60 time_duration_type utc_offset(bool is_dst)
Chris@16 61 {
Chris@16 62 if (is_dst) {
Chris@16 63 return utc_offset_ + this->dst_offset();
Chris@16 64 }
Chris@16 65 else {
Chris@16 66 return utc_offset_;
Chris@16 67 }
Chris@16 68
Chris@16 69 }
Chris@16 70 private:
Chris@16 71 time_duration_type utc_offset_;
Chris@16 72
Chris@16 73 };
Chris@16 74
Chris@16 75
Chris@16 76
Chris@16 77 //! Embed the rules for local time adjustments at compile time
Chris@16 78 template<class time_type, class dst_rules, class utc_offset_rules>
Chris@16 79 class static_local_time_adjustor: public dst_rules, public utc_offset_rules
Chris@16 80 {
Chris@16 81 public:
Chris@16 82 typedef typename time_type::time_duration_type time_duration_type;
Chris@16 83 typedef typename time_type::date_type date_type;
Chris@16 84
Chris@16 85 //! Calculates the offset from a utc time to local based on dst and utc offset
Chris@16 86 /*! @param t UTC time to calculate offset to local time
Chris@16 87 * This adjustment depends on the following observations about the
Chris@16 88 * workings of the DST boundary offset. Since UTC time labels are
Chris@16 89 * monotonically increasing we can determine if a given local time
Chris@16 90 * is in DST or not and therefore adjust the offset appropriately.
Chris@16 91 *
Chris@16 92 * The logic is as follows. Starting with UTC time use the offset to
Chris@16 93 * create a label for an non-dst adjusted local time. Then call
Chris@16 94 * dst_rules::local_is_dst with the non adjust local time. The
Chris@16 95 * results of this function will either unabiguously decide that
Chris@16 96 * the initial local time is in dst or return an illegal or
Chris@16 97 * ambiguous result. An illegal result only occurs at the end
Chris@16 98 * of dst (where labels are skipped) and indicates that dst has
Chris@16 99 * ended. An ambiguous result means that we need to recheck by
Chris@16 100 * making a dst adjustment and then rechecking. If the dst offset
Chris@16 101 * is added to the utc time and the recheck proves non-ambiguous
Chris@16 102 * then we are past the boundary. If it is still ambiguous then
Chris@16 103 * we are ahead of the boundary and dst is still in effect.
Chris@16 104 *
Chris@16 105 * TODO -- check if all dst offsets are positive. If not then
Chris@16 106 * the algorithm needs to check for this and reverse the
Chris@16 107 * illegal/ambiguous logic.
Chris@16 108 */
Chris@16 109 static time_duration_type utc_to_local_offset(const time_type& t)
Chris@16 110 {
Chris@16 111 //get initial local time guess by applying utc offset
Chris@16 112 time_type initial = t + utc_offset_rules::utc_to_local_base_offset();
Chris@16 113 time_is_dst_result dst_flag =
Chris@16 114 dst_rules::local_is_dst(initial.date(), initial.time_of_day());
Chris@16 115 switch(dst_flag) {
Chris@16 116 case is_in_dst: return utc_offset_rules::utc_to_local_base_offset() + dst_rules::dst_offset();
Chris@16 117 case is_not_in_dst: return utc_offset_rules::utc_to_local_base_offset();
Chris@16 118 case invalid_time_label:return utc_offset_rules::utc_to_local_base_offset() + dst_rules::dst_offset();
Chris@16 119 case ambiguous: {
Chris@16 120 time_type retry = initial + dst_rules::dst_offset();
Chris@16 121 dst_flag = dst_rules::local_is_dst(retry.date(), retry.time_of_day());
Chris@16 122 //if still ambibuous then the utc time still translates to a dst time
Chris@16 123 if (dst_flag == ambiguous) {
Chris@16 124 return utc_offset_rules::utc_to_local_base_offset() + dst_rules::dst_offset();
Chris@16 125 }
Chris@16 126 // we are past the dst boundary
Chris@16 127 else {
Chris@16 128 return utc_offset_rules::utc_to_local_base_offset();
Chris@16 129 }
Chris@16 130 }
Chris@16 131 }//case
Chris@16 132 //TODO better exception type
Chris@16 133 boost::throw_exception(std::out_of_range("Unreachable case"));
Chris@16 134 BOOST_DATE_TIME_UNREACHABLE_EXPRESSION(return time_duration_type(not_a_date_time)); // should never reach
Chris@16 135 }
Chris@16 136
Chris@16 137 //! Get the offset to UTC given a local time
Chris@16 138 static time_duration_type local_to_utc_offset(const time_type& t,
Chris@16 139 date_time::dst_flags dst=date_time::calculate)
Chris@16 140 {
Chris@16 141 switch (dst) {
Chris@16 142 case is_dst:
Chris@16 143 return utc_offset_rules::local_to_utc_base_offset() - dst_rules::dst_offset();
Chris@16 144 case not_dst:
Chris@16 145 return utc_offset_rules::local_to_utc_base_offset();
Chris@16 146 case calculate:
Chris@16 147 time_is_dst_result res =
Chris@16 148 dst_rules::local_is_dst(t.date(), t.time_of_day());
Chris@16 149 switch(res) {
Chris@16 150 case is_in_dst: return utc_offset_rules::local_to_utc_base_offset() - dst_rules::dst_offset();
Chris@16 151 case is_not_in_dst: return utc_offset_rules::local_to_utc_base_offset();
Chris@16 152 case ambiguous: return utc_offset_rules::local_to_utc_base_offset();
Chris@16 153 case invalid_time_label: break;
Chris@16 154 }
Chris@16 155 }
Chris@16 156 boost::throw_exception(std::out_of_range("Time label invalid"));
Chris@16 157 BOOST_DATE_TIME_UNREACHABLE_EXPRESSION(return time_duration_type(not_a_date_time)); // should never reach
Chris@16 158 }
Chris@16 159
Chris@16 160
Chris@16 161 private:
Chris@16 162
Chris@16 163 };
Chris@16 164
Chris@16 165 void dummy_to_prevent_msvc6_ice(); //why ask why?
Chris@16 166
Chris@16 167 //! Template that simplifies the creation of local time calculator
Chris@16 168 /*! Use this template to create the timezone to utc convertors as required.
Chris@16 169 *
Chris@16 170 * This class will also work for other regions that don't use dst and
Chris@16 171 * have a utc offset which is an integral number of hours.
Chris@16 172 *
Chris@16 173 * <b>Template Parameters</b>
Chris@16 174 * -time_type -- Time class to use
Chris@16 175 * -utc_offset -- Number hours local time is adjust from utc
Chris@16 176 * -use_dst -- true (default) if region uses dst, false otherwise
Chris@16 177 * For example:
Chris@16 178 * @code
Chris@16 179 * //eastern timezone is utc-5
Chris@16 180 typedef date_time::local_adjustor<ptime, -5, us_dst> us_eastern;
Chris@16 181 typedef date_time::local_adjustor<ptime, -6, us_dst> us_central;
Chris@16 182 typedef date_time::local_adjustor<ptime, -7, us_dst> us_mountain;
Chris@16 183 typedef date_time::local_adjustor<ptime, -8, us_dst> us_pacific;
Chris@16 184 typedef date_time::local_adjustor<ptime, -7, no_dst> us_arizona;
Chris@16 185 @endcode
Chris@16 186
Chris@16 187 */
Chris@16 188 template<class time_type, short utc_offset, class dst_rule>
Chris@16 189 class local_adjustor
Chris@16 190 {
Chris@16 191 public:
Chris@16 192 typedef typename time_type::time_duration_type time_duration_type;
Chris@16 193 typedef typename time_type::date_type date_type;
Chris@16 194 typedef static_local_time_adjustor<time_type,
Chris@16 195 dst_rule,
Chris@16 196 utc_adjustment<time_duration_type,
Chris@16 197 utc_offset> > dst_adjustor;
Chris@16 198 //! Convert a utc time to local time
Chris@16 199 static time_type utc_to_local(const time_type& t)
Chris@16 200 {
Chris@16 201 time_duration_type td = dst_adjustor::utc_to_local_offset(t);
Chris@16 202 return t + td;
Chris@16 203 }
Chris@16 204 //! Convert a local time to utc
Chris@16 205 static time_type local_to_utc(const time_type& t,
Chris@16 206 date_time::dst_flags dst=date_time::calculate)
Chris@16 207 {
Chris@16 208 time_duration_type td = dst_adjustor::local_to_utc_offset(t, dst);
Chris@16 209 return t + td;
Chris@16 210 }
Chris@16 211 };
Chris@16 212
Chris@16 213
Chris@16 214 } } //namespace date_time
Chris@16 215
Chris@16 216
Chris@16 217
Chris@16 218 #endif