OLE Automation date to local_date_time conversion

Hello fellow boosters, Under MSVC boost::date_time supports conversion from FILETIME, so it makes sense to also support conversion from the OLE automation date format, helpfully defined at: http://msdn.microsoft.com/en-us/library/system.datetime.fromoadate.aspx
The d parameter is a double-precision floating-point number that represents a date as the number of days before or after the base date, midnight, 30 December 1899. The sign and integral part of d encode the date as a positive or negative day displacement from 30 December 1899, and the absolute value of the fractional part of d encodes the time of day as a fraction of a day displacement from midnight. d must be a value between negative 657435.0 through positive 2958466.0.
In fact, I don't see a good reason this function can't be included in a non-MSVC build too since it doesn't depend on the Win32 API in any way. The code to handle this conversion is quite ugly. Here is my code to do it: namespace boost { namespace date_time { //! Create a time object from an OLE automation date value. /*! Create a time object from an OLE automation date value. * The oa_date parameter is a double-precision floating-point number that * represents a date as the number of days before or after the base date, midnight, * 30 December 1899. The sign and integral part of oa_date encode the date as a * positive or negative day displacement from 30 December 1899, and the absolute * value of the fractional part of oa_date encodes the time of day as a fraction of a * day displacement from midnight. oa_date must be a value between * negative 657435.0 through positive 2958466.0. */ template<class time_type> inline time_type time_from_OADATE(double oa_date) { typedef typename time_type::date_type date_type; typedef typename time_type::date_duration_type date_duration_type; typedef typename time_type::time_duration_type time_duration_type; using boost::math::modf; static const date_type base_date(1899, Dec, 30); static const time_type base_time(base_date, time_duration_type(0,0,0)); int dayOffset, hourOffset, minuteOffset, secondOffset; double fraction = fabs(modf(oa_date, &dayOffset)) * 24; // fraction = hours fraction = modf(fraction, &hourOffset) * 60; // fraction = minutes fraction = modf(fraction, &minuteOffset) * 60; // fraction = seconds modf(fraction, &secondOffset); time_type t(base_time); t += time_duration_type(hourOffset, minuteOffset, secondOffset); t += date_duration_type(dayOffset); return t; } } } Here are some basic unit tests: template<typename time_type> void test_time_from_OADATE(std::ostream* os_ = NULL) { typedef typename time_type::date_type date_type; typedef typename time_type::date_duration_type date_duration_type; typedef typename time_type::time_duration_type time_duration_type; using namespace boost::date_time; if (os_) *os_ << "OADATE: 0.0 -> " << time_from_OADATE<time_type>(0.0) << endl; unit_assert(time_from_OADATE<time_type>(0.0) == time_type(date_type(1899, Dec, 30), time_duration_type(0,0,0))); if (os_) *os_ << "OADATE: 1.0 -> " << time_from_OADATE<time_type>(1.0) << endl; unit_assert(time_from_OADATE<time_type>(1.0) == time_type(date_type(1899, Dec, 31), time_duration_type(0,0,0))); if (os_) *os_ << "OADATE: -1.0 -> " << time_from_OADATE<time_type>(-1.0) << endl; unit_assert(time_from_OADATE<time_type>(-1.0) == time_type(date_type(1899, Dec, 29), time_duration_type(0,0,0))); if (os_) *os_ << "OADATE: 2.0 -> " << time_from_OADATE<time_type>(2.0) << endl; unit_assert(time_from_OADATE<time_type>(2.0) == time_type(date_type(1900, Jan, 1), time_duration_type(0,0,0))); if (os_) *os_ << "OADATE: 2.25 -> " << time_from_OADATE<time_type>(2.25) << endl; unit_assert(time_from_OADATE<time_type>(2.25) == time_type(date_type(1900, Jan, 1), time_duration_type(6,0,0))); if (os_) *os_ << "OADATE: -1.25 -> " << time_from_OADATE<time_type>(-1.25) << endl; unit_assert(time_from_OADATE<time_type>(-1.25) == time_type(date_type(1899, Dec, 29), time_duration_type(6,0,0))); } I made it templated because its sibling function in boost\date_time\filetime_functions.hpp is templated, but it seems that ptime is the only stock type that will work. Local_time doesn't have the right constructors, at least. Thoughts? What's the procedure to add this officially to date_time? Thanks, -Matt Chambers

Matthew Chambers wrote:
Hello fellow boosters,
Under MSVC boost::date_time supports conversion from FILETIME, so it makes sense to also support conversion from the OLE automation date format, helpfully defined at: http://msdn.microsoft.com/en-us/library/system.datetime.fromoadate.aspx
In fact, I don't see a good reason this function can't be included in a non-MSVC build too since it doesn't depend on the Win32 API in any way.
[snip]
Thoughts? What's the procedure to add this officially to date_time?
The best way to do it is to create a feature request ticket on the Trac. I think it would be a nice addition.
participants (2)
-
Andrey Semashev
-
Matthew Chambers