1 #ifndef DATE_TIME_TIME_RESOLUTION_TRAITS_HPP
2 #define DATE_TIME_TIME_RESOLUTION_TRAITS_HPP
3 
4 /* Copyright (c) 2002,2003 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$
10  */
11 
12 #include <ctime>
13 #include <boost/cstdint.hpp>
14 #include <boost/date_time/time_defs.hpp>
15 #include <boost/date_time/int_adapter.hpp>
16 #include <boost/date_time/compiler_config.hpp>
17 
18 namespace boost {
19 namespace date_time {
20 
21   //! Simple function to calculate absolute value of a numeric type
22   template <typename T>
23   // JDG [7/6/02 made a template],
24   // moved here from time_duration.hpp 2003-Sept-4.
absolute_value(T x)25   inline BOOST_CXX14_CONSTEXPR T absolute_value(T x)
26   {
27     return x < 0 ? -x : x;
28   }
29 
30   //! traits struct for time_resolution_traits implementation type
31   struct time_resolution_traits_bi32_impl {
32     typedef boost::int32_t int_type;
33     typedef boost::int32_t impl_type;
as_numberboost::date_time::time_resolution_traits_bi32_impl34     static BOOST_CXX14_CONSTEXPR int_type as_number(impl_type i){ return i;}
35     //! Used to determine if implemented type is int_adapter or int
is_adaptedboost::date_time::time_resolution_traits_bi32_impl36     static BOOST_CXX14_CONSTEXPR bool is_adapted() { return false;}
37   };
38   //! traits struct for time_resolution_traits implementation type
39   struct time_resolution_traits_adapted32_impl {
40     typedef boost::int32_t int_type;
41     typedef boost::date_time::int_adapter<boost::int32_t> impl_type;
as_numberboost::date_time::time_resolution_traits_adapted32_impl42     static BOOST_CXX14_CONSTEXPR int_type as_number(impl_type i){ return i.as_number();}
43     //! Used to determine if implemented type is int_adapter or int
is_adaptedboost::date_time::time_resolution_traits_adapted32_impl44     static BOOST_CXX14_CONSTEXPR bool is_adapted() { return true;}
45   };
46   //! traits struct for time_resolution_traits implementation type
47   struct time_resolution_traits_bi64_impl {
48     typedef boost::int64_t int_type;
49     typedef boost::int64_t impl_type;
as_numberboost::date_time::time_resolution_traits_bi64_impl50     static BOOST_CXX14_CONSTEXPR int_type as_number(impl_type i){ return i;}
51     //! Used to determine if implemented type is int_adapter or int
is_adaptedboost::date_time::time_resolution_traits_bi64_impl52     static BOOST_CXX14_CONSTEXPR bool is_adapted() { return false;}
53   };
54   //! traits struct for time_resolution_traits implementation type
55   struct time_resolution_traits_adapted64_impl {
56     typedef boost::int64_t int_type;
57     typedef boost::date_time::int_adapter<boost::int64_t> impl_type;
as_numberboost::date_time::time_resolution_traits_adapted64_impl58     static BOOST_CXX14_CONSTEXPR int_type as_number(impl_type i){ return i.as_number();}
59     //! Used to determine if implemented type is int_adapter or int
is_adaptedboost::date_time::time_resolution_traits_adapted64_impl60     static BOOST_CXX14_CONSTEXPR bool is_adapted() { return true;}
61   };
62 
63   //
64   // Note about var_type, which is used to define the variable that
65   // stores hours, minutes, and seconds values:
66   //
67   // In Boost 1.65.1 and earlier var_type was boost::int32_t which suffers
68   // the year 2038 problem.  Binary serialization of posix_time uses
69   // 32-bit values, and uses serialization version 0.
70   //
71   // In Boost 1.66.0 the var_type changed to std::time_t, however
72   // binary serialization was not properly versioned, so on platforms
73   // where std::time_t is 32-bits, it remains compatible, however on
74   // platforms where std::time_t is 64-bits, binary serialization ingest
75   // will be incompatible with previous versions.  Furthermore, binary
76   // serialized output from 1.66.0 will not be compatible with future
77   // versions.  Yes, it's a mess.  Static assertions were not present
78   // in the serialization code to protect against this possibility.
79   //
80   // In Boost 1.67.0 the var_type was changed to boost::int64_t,
81   // ensuring the output size is 64 bits, and the serialization version
82   // was bumped.  Static assertions were added as well, protecting
83   // future changes in this area.
84   //
85 
86   template<typename frac_sec_type,
87            time_resolutions res,
88 #if (defined(BOOST_MSVC) && (_MSC_VER < 1300))
89            boost::int64_t resolution_adjust,
90 #else
91            typename frac_sec_type::int_type resolution_adjust,
92 #endif
93            unsigned short frac_digits,
94            typename var_type = boost::int64_t >     // see note above
95   class time_resolution_traits {
96   public:
97     typedef typename frac_sec_type::int_type fractional_seconds_type;
98     typedef typename frac_sec_type::int_type tick_type;
99     typedef typename frac_sec_type::impl_type impl_type;
100     typedef var_type  day_type;
101     typedef var_type  hour_type;
102     typedef var_type  min_type;
103     typedef var_type  sec_type;
104 
105     // bring in function from frac_sec_type traits structs
as_number(impl_type i)106     static BOOST_CXX14_CONSTEXPR fractional_seconds_type as_number(impl_type i)
107     {
108       return frac_sec_type::as_number(i);
109     }
is_adapted()110     static BOOST_CXX14_CONSTEXPR bool is_adapted()
111     {
112       return frac_sec_type::is_adapted();
113     }
114 
115     //Would like this to be frac_sec_type, but some compilers complain
116 #if (defined(BOOST_MSVC) && (_MSC_VER < 1300))
117     BOOST_STATIC_CONSTANT(boost::int64_t, ticks_per_second = resolution_adjust);
118 #else
119     BOOST_STATIC_CONSTANT(fractional_seconds_type, ticks_per_second = resolution_adjust);
120 #endif
121 
resolution()122     static BOOST_CXX14_CONSTEXPR time_resolutions resolution()
123     {
124       return res;
125     }
num_fractional_digits()126     static BOOST_CXX14_CONSTEXPR unsigned short num_fractional_digits()
127     {
128       return frac_digits;
129     }
res_adjust()130     static BOOST_CXX14_CONSTEXPR fractional_seconds_type res_adjust()
131     {
132       return resolution_adjust;
133     }
134     //! Any negative argument results in a negative tick_count
to_tick_count(hour_type hours,min_type minutes,sec_type seconds,fractional_seconds_type fs)135     static BOOST_CXX14_CONSTEXPR tick_type to_tick_count(hour_type hours,
136                                                          min_type  minutes,
137                                                          sec_type  seconds,
138                                                          fractional_seconds_type  fs)
139     {
140       if(hours < 0 || minutes < 0 || seconds < 0 || fs < 0)
141       {
142         hours = absolute_value(hours);
143         minutes = absolute_value(minutes);
144         seconds = absolute_value(seconds);
145         fs = absolute_value(fs);
146         return static_cast<tick_type>(((((fractional_seconds_type(hours)*3600)
147                                        + (fractional_seconds_type(minutes)*60)
148                                        + seconds)*res_adjust()) + fs) * -1);
149       }
150 
151       return static_cast<tick_type>((((fractional_seconds_type(hours)*3600)
152                                     + (fractional_seconds_type(minutes)*60)
153                                     + seconds)*res_adjust()) + fs);
154     }
155 
156   };
157 
158   typedef time_resolution_traits<time_resolution_traits_adapted32_impl, milli, 1000, 3 > milli_res;
159   typedef time_resolution_traits<time_resolution_traits_adapted64_impl, micro, 1000000, 6 > micro_res;
160   typedef time_resolution_traits<time_resolution_traits_adapted64_impl, nano,  1000000000, 9 > nano_res;
161 
162 
163 } } //namespace date_time
164 
165 
166 
167 #endif
168