1#ifndef GREGORIAN_SERIALIZE_HPP___
2#define GREGORIAN_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/gregorian/gregorian_types.hpp"
13#include "boost/date_time/gregorian/parsers.hpp"
14#include "boost/serialization/split_free.hpp"
15#include "boost/serialization/nvp.hpp"
16
17
18// macros to split serialize functions into save & load functions
19// An expanded version is below for gregorian::date
20// NOTE: these macros define template functions in the boost::serialization namespace.
21// They must be expanded *outside* of any namespace
22BOOST_SERIALIZATION_SPLIT_FREE(::boost::gregorian::date_duration)
23BOOST_SERIALIZATION_SPLIT_FREE(::boost::gregorian::date_duration::duration_rep)
24BOOST_SERIALIZATION_SPLIT_FREE(::boost::gregorian::date_period)
25BOOST_SERIALIZATION_SPLIT_FREE(::boost::gregorian::greg_year)
26BOOST_SERIALIZATION_SPLIT_FREE(::boost::gregorian::greg_month)
27BOOST_SERIALIZATION_SPLIT_FREE(::boost::gregorian::greg_day)
28BOOST_SERIALIZATION_SPLIT_FREE(::boost::gregorian::greg_weekday)
29BOOST_SERIALIZATION_SPLIT_FREE(::boost::gregorian::partial_date)
30BOOST_SERIALIZATION_SPLIT_FREE(::boost::gregorian::nth_kday_of_month)
31BOOST_SERIALIZATION_SPLIT_FREE(::boost::gregorian::first_kday_of_month)
32BOOST_SERIALIZATION_SPLIT_FREE(::boost::gregorian::last_kday_of_month)
33BOOST_SERIALIZATION_SPLIT_FREE(::boost::gregorian::first_kday_before)
34BOOST_SERIALIZATION_SPLIT_FREE(::boost::gregorian::first_kday_after)
35
36namespace boost {
37namespace serialization {
38
39/*! Method that does serialization for gregorian::date -- splits to load/save
40 */
41template<class Archive>
42inline void serialize(Archive & ar,
43 ::boost::gregorian::date & d,
44 const unsigned int file_version)
45{
46 split_free(ar, d, file_version);
47}
48
49//! Function to save gregorian::date objects using serialization lib
50/*! Dates are serialized into a string for transport and storage.
51 * While it would be more efficient to store the internal
52 * integer used to manipulate the dates, it is an unstable solution.
53 */
54template<class Archive>
55void save(Archive & ar,
56 const ::boost::gregorian::date & d,
57 unsigned int /* version */)
58{
59 std::string ds = to_iso_string(d);
60 ar & make_nvp(name: "date", t&: ds);
61}
62
63//! Function to load gregorian::date objects using serialization lib
64/*! Dates are serialized into a string for transport and storage.
65 * While it would be more efficient to store the internal
66 * integer used to manipulate the dates, it is an unstable solution.
67 */
68template<class Archive>
69void load(Archive & ar,
70 ::boost::gregorian::date & d,
71 unsigned int /*version*/)
72{
73 std::string ds;
74 ar & make_nvp(name: "date", t&: ds);
75 try{
76 d = ::boost::gregorian::from_undelimited_string(s: ds);
77 }catch(bad_lexical_cast&) {
78 gregorian::special_values sv = gregorian::special_value_from_string(s: ds);
79 if(sv == gregorian::not_special) {
80 throw; // no match found, rethrow original exception
81 }
82 else {
83 d = gregorian::date(sv);
84 }
85 }
86}
87
88
89//!override needed b/c no default constructor
90template<class Archive>
91inline void load_construct_data(Archive & /*ar*/,
92 ::boost::gregorian::date* dp,
93 const unsigned int /*file_version*/)
94{
95 // retrieve data from archive required to construct new
96 // invoke inplace constructor to initialize instance of date
97 ::new(dp) ::boost::gregorian::date(::boost::gregorian::not_a_date_time);
98}
99
100/**** date_duration ****/
101
102//! Function to save gregorian::date_duration objects using serialization lib
103template<class Archive>
104void save(Archive & ar, const gregorian::date_duration & dd,
105 unsigned int /*version*/)
106{
107 typename gregorian::date_duration::duration_rep dr = dd.get_rep();
108 ar & make_nvp(name: "date_duration", t&: dr);
109}
110//! Function to load gregorian::date_duration objects using serialization lib
111template<class Archive>
112void load(Archive & ar, gregorian::date_duration & dd, unsigned int /*version*/)
113{
114 typename gregorian::date_duration::duration_rep dr(0);
115 ar & make_nvp(name: "date_duration", t&: dr);
116 dd = gregorian::date_duration(dr);
117}
118//!override needed b/c no default constructor
119template<class Archive>
120inline void load_construct_data(Archive & /*ar*/, gregorian::date_duration* dd,
121 const unsigned int /*file_version*/)
122{
123 ::new(dd) gregorian::date_duration(gregorian::not_a_date_time);
124}
125
126/**** date_duration::duration_rep (most likely int_adapter) ****/
127
128//! helper unction to save date_duration objects using serialization lib
129template<class Archive>
130void save(Archive & ar, const gregorian::date_duration::duration_rep & dr,
131 unsigned int /*version*/)
132{
133 typename gregorian::date_duration::duration_rep::int_type it = dr.as_number();
134 ar & make_nvp(name: "date_duration_duration_rep", t&: it);
135}
136//! helper function to load date_duration objects using serialization lib
137template<class Archive>
138void load(Archive & ar, gregorian::date_duration::duration_rep & dr, unsigned int /*version*/)
139{
140 typename gregorian::date_duration::duration_rep::int_type it(0);
141 ar & make_nvp(name: "date_duration_duration_rep", t&: it);
142 dr = gregorian::date_duration::duration_rep::int_type(it);
143}
144//!override needed b/c no default constructor
145template<class Archive>
146inline void load_construct_data(Archive & /*ar*/, gregorian::date_duration::duration_rep* dr,
147 const unsigned int /*file_version*/)
148{
149 ::new(dr) gregorian::date_duration::duration_rep(0);
150}
151
152/**** date_period ****/
153
154//! Function to save gregorian::date_period objects using serialization lib
155/*! date_period objects are broken down into 2 parts for serialization:
156 * the begining date object and the end date object
157 */
158template<class Archive>
159void save(Archive & ar, const gregorian::date_period& dp,
160 unsigned int /*version*/)
161{
162 gregorian::date d1 = dp.begin();
163 gregorian::date d2 = dp.end();
164 ar & make_nvp(name: "date_period_begin_date", t&: d1);
165 ar & make_nvp(name: "date_period_end_date", t&: d2);
166}
167//! Function to load gregorian::date_period objects using serialization lib
168/*! date_period objects are broken down into 2 parts for serialization:
169 * the begining date object and the end date object
170 */
171template<class Archive>
172void load(Archive & ar, gregorian::date_period& dp, unsigned int /*version*/)
173{
174 gregorian::date d1(gregorian::not_a_date_time);
175 gregorian::date d2(gregorian::not_a_date_time);
176 ar & make_nvp(name: "date_period_begin_date", t&: d1);
177 ar & make_nvp(name: "date_period_end_date", t&: d2);
178 dp = gregorian::date_period(d1,d2);
179}
180//!override needed b/c no default constructor
181template<class Archive>
182inline void load_construct_data(Archive & /*ar*/, gregorian::date_period* dp,
183 const unsigned int /*file_version*/)
184{
185 gregorian::date d(gregorian::not_a_date_time);
186 gregorian::date_duration dd(1);
187 ::new(dp) gregorian::date_period(d,dd);
188}
189
190/**** greg_year ****/
191
192//! Function to save gregorian::greg_year objects using serialization lib
193template<class Archive>
194void save(Archive & ar, const gregorian::greg_year& gy,
195 unsigned int /*version*/)
196{
197 unsigned short us = gy;
198 ar & make_nvp(name: "greg_year", t&: us);
199}
200//! Function to load gregorian::greg_year objects using serialization lib
201template<class Archive>
202void load(Archive & ar, gregorian::greg_year& gy, unsigned int /*version*/)
203{
204 unsigned short us;
205 ar & make_nvp(name: "greg_year", t&: us);
206 gy = gregorian::greg_year(us);
207}
208//!override needed b/c no default constructor
209template<class Archive>
210inline void load_construct_data(Archive & /*ar*/, gregorian::greg_year* gy,
211 const unsigned int /*file_version*/)
212{
213 ::new(gy) gregorian::greg_year(1900);
214}
215
216/**** greg_month ****/
217
218//! Function to save gregorian::greg_month objects using serialization lib
219template<class Archive>
220void save(Archive & ar, const gregorian::greg_month& gm,
221 unsigned int /*version*/)
222{
223 unsigned short us = gm.as_number();
224 ar & make_nvp(name: "greg_month", t&: us);
225}
226//! Function to load gregorian::greg_month objects using serialization lib
227template<class Archive>
228void load(Archive & ar, gregorian::greg_month& gm, unsigned int /*version*/)
229{
230 unsigned short us;
231 ar & make_nvp(name: "greg_month", t&: us);
232 gm = gregorian::greg_month(us);
233}
234//!override needed b/c no default constructor
235template<class Archive>
236inline void load_construct_data(Archive & /*ar*/, gregorian::greg_month* gm,
237 const unsigned int /*file_version*/)
238{
239 ::new(gm) gregorian::greg_month(1);
240}
241
242/**** greg_day ****/
243
244//! Function to save gregorian::greg_day objects using serialization lib
245template<class Archive>
246void save(Archive & ar, const gregorian::greg_day& gd,
247 unsigned int /*version*/)
248{
249 unsigned short us = gd.as_number();
250 ar & make_nvp(name: "greg_day", t&: us);
251}
252//! Function to load gregorian::greg_day objects using serialization lib
253template<class Archive>
254void load(Archive & ar, gregorian::greg_day& gd, unsigned int /*version*/)
255{
256 unsigned short us;
257 ar & make_nvp(name: "greg_day", t&: us);
258 gd = gregorian::greg_day(us);
259}
260//!override needed b/c no default constructor
261template<class Archive>
262inline void load_construct_data(Archive & /*ar*/, gregorian::greg_day* gd,
263 const unsigned int /*file_version*/)
264{
265 ::new(gd) gregorian::greg_day(1);
266}
267
268/**** greg_weekday ****/
269
270//! Function to save gregorian::greg_weekday objects using serialization lib
271template<class Archive>
272void save(Archive & ar, const gregorian::greg_weekday& gd,
273 unsigned int /*version*/)
274{
275 unsigned short us = gd.as_number();
276 ar & make_nvp(name: "greg_weekday", t&: us);
277}
278//! Function to load gregorian::greg_weekday objects using serialization lib
279template<class Archive>
280void load(Archive & ar, gregorian::greg_weekday& gd, unsigned int /*version*/)
281{
282 unsigned short us;
283 ar & make_nvp(name: "greg_weekday", t&: us);
284 gd = gregorian::greg_weekday(us);
285}
286//!override needed b/c no default constructor
287template<class Archive>
288inline void load_construct_data(Archive & /*ar*/, gregorian::greg_weekday* gd,
289 const unsigned int /*file_version*/)
290{
291 ::new(gd) gregorian::greg_weekday(1);
292}
293
294/**** date_generators ****/
295
296/**** partial_date ****/
297
298//! Function to save gregorian::partial_date objects using serialization lib
299/*! partial_date objects are broken down into 2 parts for serialization:
300 * the day (typically greg_day) and month (typically greg_month) objects
301 */
302template<class Archive>
303void save(Archive & ar, const gregorian::partial_date& pd,
304 unsigned int /*version*/)
305{
306 gregorian::greg_day gd(pd.day());
307 gregorian::greg_month gm(pd.month().as_number());
308 ar & make_nvp(name: "partial_date_day", t&: gd);
309 ar & make_nvp(name: "partial_date_month", t&: gm);
310}
311//! Function to load gregorian::partial_date objects using serialization lib
312/*! partial_date objects are broken down into 2 parts for serialization:
313 * the day (greg_day) and month (greg_month) objects
314 */
315template<class Archive>
316void load(Archive & ar, gregorian::partial_date& pd, unsigned int /*version*/)
317{
318 gregorian::greg_day gd(1);
319 gregorian::greg_month gm(1);
320 ar & make_nvp(name: "partial_date_day", t&: gd);
321 ar & make_nvp(name: "partial_date_month", t&: gm);
322 pd = gregorian::partial_date(gd,gm);
323}
324//!override needed b/c no default constructor
325template<class Archive>
326inline void load_construct_data(Archive & /*ar*/, gregorian::partial_date* pd,
327 const unsigned int /*file_version*/)
328{
329 gregorian::greg_month gm(1);
330 gregorian::greg_day gd(1);
331 ::new(pd) gregorian::partial_date(gd,gm);
332}
333
334/**** nth_kday_of_month ****/
335
336//! Function to save nth_day_of_the_week_in_month objects using serialization lib
337/*! nth_day_of_the_week_in_month objects are broken down into 3 parts for
338 * serialization: the week number, the day of the week, and the month
339 */
340template<class Archive>
341void save(Archive & ar, const gregorian::nth_kday_of_month& nkd,
342 unsigned int /*version*/)
343{
344 typename gregorian::nth_kday_of_month::week_num wn(nkd.nth_week());
345 typename gregorian::nth_kday_of_month::day_of_week_type d(nkd.day_of_week().as_number());
346 typename gregorian::nth_kday_of_month::month_type m(nkd.month().as_number());
347 ar & make_nvp(name: "nth_kday_of_month_week_num", t&: wn);
348 ar & make_nvp(name: "nth_kday_of_month_day_of_week", t&: d);
349 ar & make_nvp(name: "nth_kday_of_month_month", t&: m);
350}
351//! Function to load nth_day_of_the_week_in_month objects using serialization lib
352/*! nth_day_of_the_week_in_month objects are broken down into 3 parts for
353 * serialization: the week number, the day of the week, and the month
354 */
355template<class Archive>
356void load(Archive & ar, gregorian::nth_kday_of_month& nkd, unsigned int /*version*/)
357{
358 typename gregorian::nth_kday_of_month::week_num wn(gregorian::nth_kday_of_month::first);
359 typename gregorian::nth_kday_of_month::day_of_week_type d(gregorian::Monday);
360 typename gregorian::nth_kday_of_month::month_type m(gregorian::Jan);
361 ar & make_nvp(name: "nth_kday_of_month_week_num", t&: wn);
362 ar & make_nvp(name: "nth_kday_of_month_day_of_week", t&: d);
363 ar & make_nvp(name: "nth_kday_of_month_month", t&: m);
364
365 nkd = gregorian::nth_kday_of_month(wn,d,m);
366}
367//!override needed b/c no default constructor
368template<class Archive>
369inline void load_construct_data(Archive & /*ar*/,
370 gregorian::nth_kday_of_month* nkd,
371 const unsigned int /*file_version*/)
372{
373 // values used are not significant
374 ::new(nkd) gregorian::nth_kday_of_month(gregorian::nth_kday_of_month::first,
375 gregorian::Monday,gregorian::Jan);
376}
377
378/**** first_kday_of_month ****/
379
380//! Function to save first_day_of_the_week_in_month objects using serialization lib
381/*! first_day_of_the_week_in_month objects are broken down into 2 parts for
382 * serialization: the day of the week, and the month
383 */
384template<class Archive>
385void save(Archive & ar, const gregorian::first_kday_of_month& fkd,
386 unsigned int /*version*/)
387{
388 typename gregorian::first_kday_of_month::day_of_week_type d(fkd.day_of_week().as_number());
389 typename gregorian::first_kday_of_month::month_type m(fkd.month().as_number());
390 ar & make_nvp(name: "first_kday_of_month_day_of_week", t&: d);
391 ar & make_nvp(name: "first_kday_of_month_month", t&: m);
392}
393//! Function to load first_day_of_the_week_in_month objects using serialization lib
394/*! first_day_of_the_week_in_month objects are broken down into 2 parts for
395 * serialization: the day of the week, and the month
396 */
397template<class Archive>
398void load(Archive & ar, gregorian::first_kday_of_month& fkd, unsigned int /*version*/)
399{
400 typename gregorian::first_kday_of_month::day_of_week_type d(gregorian::Monday);
401 typename gregorian::first_kday_of_month::month_type m(gregorian::Jan);
402 ar & make_nvp(name: "first_kday_of_month_day_of_week", t&: d);
403 ar & make_nvp(name: "first_kday_of_month_month", t&: m);
404
405 fkd = gregorian::first_kday_of_month(d,m);
406}
407//!override needed b/c no default constructor
408template<class Archive>
409inline void load_construct_data(Archive & /*ar*/,
410 gregorian::first_kday_of_month* fkd,
411 const unsigned int /*file_version*/)
412{
413 // values used are not significant
414 ::new(fkd) gregorian::first_kday_of_month(gregorian::Monday,gregorian::Jan);
415}
416
417/**** last_kday_of_month ****/
418
419//! Function to save last_day_of_the_week_in_month objects using serialization lib
420/*! last_day_of_the_week_in_month objects are broken down into 2 parts for
421 * serialization: the day of the week, and the month
422 */
423template<class Archive>
424void save(Archive & ar, const gregorian::last_kday_of_month& lkd,
425 unsigned int /*version*/)
426{
427 typename gregorian::last_kday_of_month::day_of_week_type d(lkd.day_of_week().as_number());
428 typename gregorian::last_kday_of_month::month_type m(lkd.month().as_number());
429 ar & make_nvp(name: "last_kday_of_month_day_of_week", t&: d);
430 ar & make_nvp(name: "last_kday_of_month_month", t&: m);
431}
432//! Function to load last_day_of_the_week_in_month objects using serialization lib
433/*! last_day_of_the_week_in_month objects are broken down into 2 parts for
434 * serialization: the day of the week, and the month
435 */
436template<class Archive>
437void load(Archive & ar, gregorian::last_kday_of_month& lkd, unsigned int /*version*/)
438{
439 typename gregorian::last_kday_of_month::day_of_week_type d(gregorian::Monday);
440 typename gregorian::last_kday_of_month::month_type m(gregorian::Jan);
441 ar & make_nvp(name: "last_kday_of_month_day_of_week", t&: d);
442 ar & make_nvp(name: "last_kday_of_month_month", t&: m);
443
444 lkd = gregorian::last_kday_of_month(d,m);
445}
446//!override needed b/c no default constructor
447template<class Archive>
448inline void load_construct_data(Archive & /*ar*/,
449 gregorian::last_kday_of_month* lkd,
450 const unsigned int /*file_version*/)
451{
452 // values used are not significant
453 ::new(lkd) gregorian::last_kday_of_month(gregorian::Monday,gregorian::Jan);
454}
455
456/**** first_kday_before ****/
457
458//! Function to save first_day_of_the_week_before objects using serialization lib
459template<class Archive>
460void save(Archive & ar, const gregorian::first_kday_before& fkdb,
461 unsigned int /*version*/)
462{
463 typename gregorian::first_kday_before::day_of_week_type d(fkdb.day_of_week().as_number());
464 ar & make_nvp(name: "first_kday_before_day_of_week", t&: d);
465}
466//! Function to load first_day_of_the_week_before objects using serialization lib
467template<class Archive>
468void load(Archive & ar, gregorian::first_kday_before& fkdb, unsigned int /*version*/)
469{
470 typename gregorian::first_kday_before::day_of_week_type d(gregorian::Monday);
471 ar & make_nvp(name: "first_kday_before_day_of_week", t&: d);
472
473 fkdb = gregorian::first_kday_before(d);
474}
475//!override needed b/c no default constructor
476template<class Archive>
477inline void load_construct_data(Archive & /*ar*/,
478 gregorian::first_kday_before* fkdb,
479 const unsigned int /*file_version*/)
480{
481 // values used are not significant
482 ::new(fkdb) gregorian::first_kday_before(gregorian::Monday);
483}
484
485/**** first_kday_after ****/
486
487//! Function to save first_day_of_the_week_after objects using serialization lib
488template<class Archive>
489void save(Archive & ar, const gregorian::first_kday_after& fkda,
490 unsigned int /*version*/)
491{
492 typename gregorian::first_kday_after::day_of_week_type d(fkda.day_of_week().as_number());
493 ar & make_nvp(name: "first_kday_after_day_of_week", t&: d);
494}
495//! Function to load first_day_of_the_week_after objects using serialization lib
496template<class Archive>
497void load(Archive & ar, gregorian::first_kday_after& fkda, unsigned int /*version*/)
498{
499 typename gregorian::first_kday_after::day_of_week_type d(gregorian::Monday);
500 ar & make_nvp(name: "first_kday_after_day_of_week", t&: d);
501
502 fkda = gregorian::first_kday_after(d);
503}
504//!override needed b/c no default constructor
505template<class Archive>
506inline void load_construct_data(Archive & /*ar*/,
507 gregorian::first_kday_after* fkda,
508 const unsigned int /*file_version*/)
509{
510 // values used are not significant
511 ::new(fkda) gregorian::first_kday_after(gregorian::Monday);
512}
513
514} // namespace serialization
515} // namespace boost
516
517#endif
518

source code of boost/boost/date_time/gregorian/greg_serialize.hpp