time_serialize.hpp 8.9 KB

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