• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 #ifndef POSIX_TIME_SERIALIZE_HPP___
2 #define POSIX_TIME_SERIALIZE_HPP___
3 
4 /* Copyright (c) 2004-2005 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 "boost/date_time/posix_time/posix_time.hpp"
13 #include "boost/date_time/gregorian/greg_serialize.hpp"
14 #include "boost/core/nvp.hpp"
15 #include "boost/numeric/conversion/cast.hpp"
16 #include "boost/type_traits/integral_constant.hpp"
17 
18 // Define versions for serialization compatibility
19 // alows the unit tests to make an older version to check compatibility
20 #ifndef BOOST_DATE_TIME_POSIX_TIME_DURATION_VERSION
21 #define BOOST_DATE_TIME_POSIX_TIME_DURATION_VERSION 1
22 #endif
23 
24 namespace boost {
25 namespace serialization {
26 
27 template<typename T>
28 struct version;
29 
30 template<>
31 struct version<boost::posix_time::time_duration>
32   : integral_constant<int, BOOST_DATE_TIME_POSIX_TIME_DURATION_VERSION>
33 {
34 };
35 
36 // A macro to split serialize functions into save & load functions.
37 // It is here to avoid dependency on Boost.Serialization just for the
38 // BOOST_SERIALIZATION_SPLIT_FREE macro
39 #define BOOST_DATE_TIME_SPLIT_FREE(T)                                         \
40 template<class Archive>                                                       \
41 inline void serialize(Archive & ar,                                           \
42                       T & t,                                                  \
43                       const unsigned int file_version)                        \
44 {                                                                             \
45   split_free(ar, t, file_version);                                            \
46 }
47 
48 BOOST_DATE_TIME_SPLIT_FREE(boost::posix_time::ptime)
BOOST_DATE_TIME_SPLIT_FREE(boost::posix_time::time_duration)49 BOOST_DATE_TIME_SPLIT_FREE(boost::posix_time::time_duration)
50 BOOST_DATE_TIME_SPLIT_FREE(boost::posix_time::time_period)
51 
52 #undef BOOST_DATE_TIME_SPLIT_FREE
53 
54 /*** time_duration ***/
55 
56 //! Function to save posix_time::time_duration objects using serialization lib
57 /*! time_duration objects are broken down into 4 parts for serialization:
58  * types are hour_type, min_type, sec_type, and fractional_seconds_type
59  * as defined in the time_duration class
60  */
61 template<class TimeResTraitsSize, class Archive>
62 void save_td(Archive& ar, const posix_time::time_duration& td)
63 {
64     TimeResTraitsSize h = boost::numeric_cast<TimeResTraitsSize>(td.hours());
65     TimeResTraitsSize m = boost::numeric_cast<TimeResTraitsSize>(td.minutes());
66     TimeResTraitsSize s = boost::numeric_cast<TimeResTraitsSize>(td.seconds());
67     posix_time::time_duration::fractional_seconds_type fs = td.fractional_seconds();
68     ar & make_nvp("time_duration_hours", h);
69     ar & make_nvp("time_duration_minutes", m);
70     ar & make_nvp("time_duration_seconds", s);
71     ar & make_nvp("time_duration_fractional_seconds", fs);
72 }
73 
74 template<class Archive>
save(Archive & ar,const posix_time::time_duration & td,unsigned int version)75 void save(Archive & ar,
76           const posix_time::time_duration& td,
77           unsigned int version)
78 {
79   // serialize a bool so we know how to read this back in later
80   bool is_special = td.is_special();
81   ar & make_nvp("is_special", is_special);
82   if(is_special) {
83     std::string s = to_simple_string(td);
84     ar & make_nvp("sv_time_duration", s);
85   }
86   else {
87     // Write support for earlier versions allows for upgrade compatibility testing
88     // See load comments for version information
89     if (version == 0) {
90         save_td<int32_t>(ar, td);
91     } else {
92         save_td<int64_t>(ar, td);
93     }
94   }
95 }
96 
97 //! Function to load posix_time::time_duration objects using serialization lib
98 /*! time_duration objects are broken down into 4 parts for serialization:
99  * types are hour_type, min_type, sec_type, and fractional_seconds_type
100  * as defined in the time_duration class
101  */
102 template<class TimeResTraitsSize, class Archive>
load_td(Archive & ar,posix_time::time_duration & td)103 void load_td(Archive& ar, posix_time::time_duration& td)
104 {
105     TimeResTraitsSize h(0);
106     TimeResTraitsSize m(0);
107     TimeResTraitsSize s(0);
108     posix_time::time_duration::fractional_seconds_type fs(0);
109     ar & make_nvp("time_duration_hours", h);
110     ar & make_nvp("time_duration_minutes", m);
111     ar & make_nvp("time_duration_seconds", s);
112     ar & make_nvp("time_duration_fractional_seconds", fs);
113     td = posix_time::time_duration(h, m, s, fs);
114 }
115 
116 template<class Archive>
load(Archive & ar,posix_time::time_duration & td,unsigned int version)117 void load(Archive & ar,
118           posix_time::time_duration & td,
119           unsigned int version)
120 {
121   bool is_special = false;
122   ar & make_nvp("is_special", is_special);
123   if(is_special) {
124     std::string s;
125     ar & make_nvp("sv_time_duration", s);
126     posix_time::special_values sv = gregorian::special_value_from_string(s);
127     td = posix_time::time_duration(sv);
128   }
129   else {
130     // Version "0"   (Boost 1.65.1 or earlier, which used int32_t for day/hour/minute/second and
131     //                therefore suffered from the year 2038 issue.)
132     // Version "0.5" (Boost 1.66.0 changed to std::time_t but did not increase the version;
133     //                it was missed in the original change, all code reviews, and there were no
134     //                static assertions to protect the code; further std::time_t can be 32-bit
135     //                or 64-bit so it reduced portability.  This makes 1.66.0 hard to handle...)
136     // Version "1"   (Boost 1.67.0 or later uses int64_t and is properly versioned)
137 
138     // If the size of any of these items changes, a new version is needed.
139     BOOST_STATIC_ASSERT(sizeof(posix_time::time_duration::hour_type) == sizeof(boost::int64_t));
140     BOOST_STATIC_ASSERT(sizeof(posix_time::time_duration::min_type) == sizeof(boost::int64_t));
141     BOOST_STATIC_ASSERT(sizeof(posix_time::time_duration::sec_type) == sizeof(boost::int64_t));
142     BOOST_STATIC_ASSERT(sizeof(posix_time::time_duration::fractional_seconds_type) == sizeof(boost::int64_t));
143 
144     if (version == 0) {
145         load_td<int32_t>(ar, td);
146     } else {
147         load_td<int64_t>(ar, td);
148     }
149   }
150 }
151 
152 // no load_construct_data function provided as time_duration provides a
153 // default constructor
154 
155 /*** ptime ***/
156 
157 //! Function to save posix_time::ptime objects using serialization lib
158 /*! ptime objects are broken down into 2 parts for serialization:
159  * a date object and a time_duration onject
160  */
161 template<class Archive>
save(Archive & ar,const posix_time::ptime & pt,unsigned int)162 void save(Archive & ar,
163           const posix_time::ptime& pt,
164           unsigned int /*version*/)
165 {
166   // from_iso_string does not include fractional seconds
167   // therefore date and time_duration are used
168   posix_time::ptime::date_type d = pt.date();
169   ar & make_nvp("ptime_date", d);
170   if(!pt.is_special()) {
171     posix_time::ptime::time_duration_type td = pt.time_of_day();
172     ar & make_nvp("ptime_time_duration", td);
173   }
174 }
175 
176 //! Function to load posix_time::ptime objects using serialization lib
177 /*! ptime objects are broken down into 2 parts for serialization:
178  * a date object and a time_duration onject
179  */
180 template<class Archive>
load(Archive & ar,posix_time::ptime & pt,unsigned int)181 void load(Archive & ar,
182           posix_time::ptime & pt,
183           unsigned int /*version*/)
184 {
185   // from_iso_string does not include fractional seconds
186   // therefore date and time_duration are used
187   posix_time::ptime::date_type d(posix_time::not_a_date_time);
188   posix_time::ptime::time_duration_type td;
189   ar & make_nvp("ptime_date", d);
190   if(!d.is_special()) {
191     ar & make_nvp("ptime_time_duration", td);
192     pt = boost::posix_time::ptime(d,td);
193   }
194   else {
195     pt = boost::posix_time::ptime(d.as_special());
196   }
197 
198 }
199 
200 //!override needed b/c no default constructor
201 template<class Archive>
load_construct_data(Archive &,posix_time::ptime * pt,const unsigned int)202 inline void load_construct_data(Archive & /*ar*/,
203                                 posix_time::ptime* pt,
204                                 const unsigned int /*file_version*/)
205 {
206   // retrieve data from archive required to construct new
207   // invoke inplace constructor to initialize instance of date
208   new(pt) boost::posix_time::ptime(boost::posix_time::not_a_date_time);
209 }
210 
211 /*** time_period ***/
212 
213 //! Function to save posix_time::time_period objects using serialization lib
214 /*! time_period objects are broken down into 2 parts for serialization:
215  * a begining ptime object and an ending ptime object
216  */
217 template<class Archive>
save(Archive & ar,const posix_time::time_period & tp,unsigned int)218 void save(Archive & ar,
219           const posix_time::time_period& tp,
220           unsigned int /*version*/)
221 {
222   posix_time::ptime beg(tp.begin().date(), tp.begin().time_of_day());
223   posix_time::ptime end(tp.end().date(), tp.end().time_of_day());
224   ar & make_nvp("time_period_begin", beg);
225   ar & make_nvp("time_period_end", end);
226 }
227 
228 //! Function to load posix_time::time_period objects using serialization lib
229 /*! time_period objects are broken down into 2 parts for serialization:
230  * a begining ptime object and an ending ptime object
231  */
232 template<class Archive>
load(Archive & ar,boost::posix_time::time_period & tp,unsigned int)233 void load(Archive & ar,
234           boost::posix_time::time_period & tp,
235           unsigned int /*version*/)
236 {
237   posix_time::time_duration td(1,0,0);
238   gregorian::date d(gregorian::not_a_date_time);
239   posix_time::ptime beg(d,td);
240   posix_time::ptime end(d,td);
241   ar & make_nvp("time_period_begin", beg);
242   ar & make_nvp("time_period_end", end);
243   tp = boost::posix_time::time_period(beg, end);
244 }
245 
246 //!override needed b/c no default constructor
247 template<class Archive>
load_construct_data(Archive &,boost::posix_time::time_period * tp,const unsigned int)248 inline void load_construct_data(Archive & /*ar*/,
249                                 boost::posix_time::time_period* tp,
250                                 const unsigned int /*file_version*/)
251 {
252   posix_time::time_duration td(1,0,0);
253   gregorian::date d(gregorian::not_a_date_time);
254   posix_time::ptime beg(d,td);
255   posix_time::ptime end(d,td);
256   new(tp) boost::posix_time::time_period(beg,end);
257 }
258 
259 } // namespace serialization
260 } // namespace boost
261 
262 #endif
263