Reputation: 13902
I am receiving from a data provider timestamps that follow this specification:
number of 100 nanoseconds since 1601
I am using boost::posix_time::ptime
and I would like to convert the timestamps to posix time. Is there a simple way to do that ?
Upvotes: 0
Views: 2059
Reputation: 4282
number of 100 nanoseconds since 1601
It is Windows FILETIME value.
Boost.DateTime actually use Windows FILETIME for Windows platform.
Below is the relevant Boost source code that convert FILETIME to boost::posix_time::ptime:
(from boost/date_time/microsec_time_clock.hpp)
static time_type create_time(time_converter converter)
{
winapi::file_time ft;
winapi::get_system_time_as_file_time(ft);
uint64_t micros = winapi::file_time_to_microseconds(ft); // it will not wrap, since ft is the current time
// and cannot be before 1970-Jan-01
std::time_t t = static_cast<std::time_t>(micros / 1000000UL); // seconds since epoch
// microseconds -- static casts supress warnings
boost::uint32_t sub_sec = static_cast<boost::uint32_t>(micros % 1000000UL);
std::tm curr;
std::tm* curr_ptr = converter(&t, &curr);
date_type d(curr_ptr->tm_year + 1900,
curr_ptr->tm_mon + 1,
curr_ptr->tm_mday);
//The following line will adjust the fractional second tick in terms
//of the current time system. For example, if the time system
//doesn't support fractional seconds then res_adjust returns 0
//and all the fractional seconds return 0.
int adjust = static_cast< int >(resolution_traits_type::res_adjust() / 1000000);
time_duration_type td(curr_ptr->tm_hour,
curr_ptr->tm_min,
curr_ptr->tm_sec,
sub_sec * adjust);
return time_type(d,td);
}
You can browse your Boost installation for the detailed implementation.
Upvotes: 1
Reputation: 753890
When did the switch from the Julian to Gregorian calendar occur for this system? Some countries switched before 1st January 1601; others didn't switch until much later. This will critically affect your calculation - by 11 days or so.
Since there are 107 units of 100 ns each in one second, you divide the starting number by 107 to produce the number of seconds since the reference time (the remainder is the fraction of a second). You then divide that by 86400 to give the number of days (the remainder is the time of day). Then you can compute the date from the number of days.
Since POSIX time uses 1970-01-01 00:00:00 as the reference, you may simply need to compute the correct number of seconds between 1601-01-01 00:00:00 and the POSIX epoch (as it is known), and subtract that number from the number of seconds you calculated.
Upvotes: 3