1 | #include "boost/date_time/posix_time/posix_time.hpp"
|
---|
2 | #include "boost/date_time/local_time_adjustor.hpp"
|
---|
3 | #include "boost/date_time/c_local_time_adjustor.hpp"
|
---|
4 | #include <iostream>
|
---|
5 |
|
---|
6 | void convertUtcTime(const boost::posix_time::ptime& tUtc);
|
---|
7 | boost::posix_time::ptime utc_to_local_workaround(const boost::posix_time::ptime& t);
|
---|
8 |
|
---|
9 | int main()
|
---|
10 | {
|
---|
11 | using namespace boost::posix_time;
|
---|
12 | using namespace boost::gregorian;
|
---|
13 | typedef boost::date_time::c_local_adjustor<ptime> local_adj;
|
---|
14 |
|
---|
15 | const ptime tUtcGood(date(2038,Jan,19), hours(3));
|
---|
16 | const ptime tUtcBad (date(2038,Jan,19), hours(4));
|
---|
17 |
|
---|
18 | convertUtcTime(tUtcGood);
|
---|
19 | convertUtcTime(tUtcBad);
|
---|
20 |
|
---|
21 | return 0;
|
---|
22 | }
|
---|
23 |
|
---|
24 |
|
---|
25 | void convertUtcTime(const boost::posix_time::ptime& tUtc)
|
---|
26 | {
|
---|
27 | using namespace boost::posix_time;
|
---|
28 | using namespace boost::gregorian;
|
---|
29 | typedef boost::date_time::c_local_adjustor<ptime> local_adj;
|
---|
30 |
|
---|
31 | std::cout << "Converting UTC time " << to_simple_string(tUtc) << ". ";
|
---|
32 | boost::posix_time::ptime tLoc;
|
---|
33 | try
|
---|
34 | {
|
---|
35 | tLoc = local_adj::utc_to_local(tUtc);
|
---|
36 | }
|
---|
37 | catch (std::exception& e)
|
---|
38 | {
|
---|
39 | std::cout << "Ouch, year 2038 problem: " << e.what() << ". " << std::endl << "Applying bug fix... ";
|
---|
40 | tLoc = utc_to_local_workaround(tUtc);
|
---|
41 | }
|
---|
42 | std::cout << "Local time is " << to_simple_string(tLoc) << std::endl;
|
---|
43 | }
|
---|
44 |
|
---|
45 |
|
---|
46 | boost::posix_time::ptime utc_to_local_workaround(const boost::posix_time::ptime& t)
|
---|
47 | {
|
---|
48 | // This code is a modified, non-templated version of boost::date_time::c_local_adjustor<ptime>
|
---|
49 |
|
---|
50 | typedef boost::posix_time::ptime time_type;
|
---|
51 | typedef time_type::time_duration_type time_duration_type;
|
---|
52 | typedef time_type::date_type date_type;
|
---|
53 | typedef date_type::duration_type date_duration_type;
|
---|
54 |
|
---|
55 | date_type time_t_start_day(1970,1,1);
|
---|
56 | time_type time_t_start_time(time_t_start_day,time_duration_type(0,0,0));
|
---|
57 | if (t < time_t_start_time) {
|
---|
58 | boost::throw_exception(std::out_of_range("Cannot convert dates prior to Jan 1, 1970"));
|
---|
59 | BOOST_DATE_TIME_UNREACHABLE_EXPRESSION(return time_t_start_time); // should never reach
|
---|
60 | }
|
---|
61 | date_duration_type dd = t.date() - time_t_start_day;
|
---|
62 | time_duration_type td = t.time_of_day();
|
---|
63 |
|
---|
64 | // The bugfix, needing generalization:
|
---|
65 | std::time_t t2 = static_cast<__int64>(dd.days())*__int64(86400) + static_cast<__int64>(td.hours()*3600 + td.minutes()*60 + td.seconds());
|
---|
66 |
|
---|
67 | std::tm tms, *tms_ptr;
|
---|
68 | tms_ptr = boost::date_time::c_time::localtime(&t2, &tms);
|
---|
69 | date_type d(static_cast<unsigned short>(tms_ptr->tm_year + 1900),
|
---|
70 | static_cast<unsigned short>(tms_ptr->tm_mon + 1),
|
---|
71 | static_cast<unsigned short>(tms_ptr->tm_mday));
|
---|
72 | time_duration_type td2(tms_ptr->tm_hour,
|
---|
73 | tms_ptr->tm_min,
|
---|
74 | tms_ptr->tm_sec,
|
---|
75 | t.time_of_day().fractional_seconds());
|
---|
76 |
|
---|
77 | return time_type(d,td2);
|
---|
78 | }
|
---|
79 |
|
---|
80 |
|
---|
81 | /* Printout:
|
---|
82 |
|
---|
83 | Converting UTC time 2038-Jan-19 03:00:00. Local time is 2038-Jan-19 04:00:00
|
---|
84 | Converting UTC time 2038-Jan-19 04:00:00. Ouch, year 2038 problem: could not convert calendar time to local time.
|
---|
85 | Applying bug fix... Local time is 2038-Jan-19 05:00:00
|
---|
86 | */
|
---|