Re: datetime string given 100 nanosecond units from year 1?
On 10/15/2014 2:11 PM, Christopher Pisz wrote:
On 10/15/2014 11:37 AM, Victor Bazarov wrote:
On 10/15/2014 12:07 PM, Christopher Pisz wrote:
Any suggestions on how to get a datetime string from a 64 bit unsigned
long long which represents 100 nanosecond ticks from midnight Jan 01
0001 ?
I cannot use chrono because I have to support XP using msvc10 :/
I can use the boost library but it seems I cannot initialize a ptime
with a year of 0001 to perform the math.
I could do manual division on how many nanoseconds are in a year myself,
but it isn't always the same, right? Leap years and DST come into play.
I'd also have to figure if it would even fit in a 64bit long.
Windows has FileTimeToSystemTime (or something like that) function and
similar ones. Why do you think you need to do it "manually"?
V
It seems those structures take a time since 1601. I don't see anything
under the Time Functions reference that can handle a date since 0001 for
me.
Ah... OK, so due to the difference (and absence in their assumptions of
any negative dates), their functions won't work...
I wonder, if Microsoft designers decided it wasn't worth it to go back
past year 1601 for measuring file times, is it worth for you to do that?
What's the need to calculate the time down to sub-microsecond level
for all the centuries in which the humanity didn't really know how to
measure one second precisely? And what is the significance (to you or
to your problem) of the year 0001?
I did come up with this, which might work as long as times are local and
American.
std::string DateTimeToString(const WS_DATETIME & value)
{
std::string timeAsText;
// Ticks is in units of 100 nanoseconds since Jan 01 0001 00:00:00
const long long ticksFromCommonEraEpochToUnixEpoch =
621355968000000000ULL;
How did you arrive at this number? Would it not be better to write it
as an expression?
// Zero seems to represent a NULL value
// We'll return an empty string to represent a NULL value
if( !value.ticks )
{
return timeAsText;
}
// Make sure we can use our calculation method
else if(value.ticks < ticksFromCommonEraEpochToUnixEpoch)
{
const std::string msg = "Times before unix epoch are not valid";
throw Shared::Exception(__FILE__, __LINE__, msg);
}
const unsigned long long ticksSinceUnixEpoch = value.ticks -
ticksFromCommonEraEpochToUnixEpoch;
const unsigned long long secondsSinceUnixEpoch =
ticksSinceUnixEpoch / 10000000ULL;
boost::posix_time::ptime theTime(boost::gregorian::date(1970, 1, 01),
boost::posix_time::time_duration(0,0,0));
theTime = theTime + boost::posix_time::seconds(secondsSinceUnixEpoch);
timeAsText = boost::posix_time::to_iso_extended_string(theTime);
return timeAsText;
}
I got my magic number ticksFromCommonEraEpochToUnixEpoch from making a
seperate .NET console project, since that is where the data is coming from.
class Program
{
static void Main(string[] args)
{
DateTime dt1 = new DateTime(0001, 1, 1, 0, 0, 0,
DateTimeKind.Local);
DateTime dt2 = new DateTime(1970, 1, 1, 0, 0, 0,
DateTimeKind.Local);
TimeSpan span = dt2 - dt1;
Console.WriteLine("Seconds = " +
span.TotalSeconds.ToString());
}
}
I'll have to compare against some test data to see if I did it right.
Seems like a big pain in the butt. If MS decided to use 0001 as an epoch
they should have a function to convert it using that epoch.
Or you could simply shift the values you get from their function by
means of some other magic number (like the one I criticized above) that
you calculate as a number of 100-nanosecond intervals between 01.01.01
and Microsoft epoch (instead of Unix epoch)...
V
--
I do not respond to top-posted replies, please don't ask