Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

datetime string given 100 nanosecond units from year 1?

163 views
Skip to first unread message

Christopher Pisz

unread,
Oct 15, 2014, 12:07:32 PM10/15/14
to
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.


Scott Neugroschl

unread,
Oct 15, 2014, 12:32:35 PM10/15/14
to
Yes, it should fit into a 64 bit long.

One year = approximately 32M seconds or 2^25 seconds.
2000 years ~= 2^11 * 2^25 seconds = 2^36 seconds.
1 ns = 10^9 ns ~= 2^30 ns.
2000 years ~= 2^30 * 2^36 ns = 2^66 ns.
At this point, we have overflowed... BUT...
You only need 100ns intervals.
100ns ~= 2^7 ns.
So, 2000 years in 100ns intervals ~= 2^66/2^7 = 2^59 ticks.

Victor Bazarov

unread,
Oct 15, 2014, 12:38:08 PM10/15/14
to
Windows has FileTimeToSystemTime (or something like that) function and
similar ones. Why do you think you need to do it "manually"?

V
--
I do not respond to top-posted replies, please don't ask

Bo Persson

unread,
Oct 15, 2014, 1:01:43 PM10/15/14
to
Not to mention changing the calendar in various countries in different
years. :-)

Some dates just never happened!


Bo Persson

Jorgen Grahn

unread,
Oct 15, 2014, 1:23:57 PM10/15/14
to
As I understand it, to do calculation on times before 1750 something,
you need a programmer and a historian ... see e.g. the Unix cal(1) man
page.

/Jorgen

--
// Jorgen Grahn <grahn@ Oo o. . .
\X/ snipabacken.se> O o .

Christopher Pisz

unread,
Oct 15, 2014, 2:11:44 PM10/15/14
to
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.

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;

// 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.


Victor Bazarov

unread,
Oct 15, 2014, 3:56:52 PM10/15/14
to
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?
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)...

Christopher Pisz

unread,
Oct 15, 2014, 4:26:51 PM10/15/14
to
On 10/15/2014 2:56 PM, Victor Bazarov wrote:
> 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:
SNIP
>> 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?
>

Because those same Microsoft designers decided to force me to do so.
They are giving me a WS_DATETIME structure, which has data as an
unsigned long long that represents 100 nanosecond units since Jan 01
0001 at midnight.

In other words, it wasn't my decision. I'd love to be dealing with unix
timestamps or datetime strings.

I only care about precision to the second myself.

>>
>> 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?

From the .NET code listed at the bottom.
I am not sure what you mean when you say write it as an expression. You
mean just use the literal directly in an expression instead of creating
a variable? That wouldn't have any functional difference. Maybe you mean
something else that I am not understanding.


SNIP

>>
>> 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());
>> }
>> }
>>

SNIP
>
> 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)...

SNIP


Paul N

unread,
Oct 15, 2014, 4:52:31 PM10/15/14
to
I don't think your unit even makes sense.

The modern definition of a second doesn't tie up exactly with the rotation of the Earth. This means that every few years you need to introduce a "leap second" to bring them back into line. I don't think anyone has worked out or decided when leap seconds occurred between 1 and about 1972 and so the "time" now (by your measurement) is undefined by a range of about 1000 seconds.

I think you will need to decide how many leap seconds are deemed to have occured between 1 and a date of 1972 or later, and work things out from that. Presumably normal time functions can then be used for dates after your "start date".

Robert Wessel

unread,
Oct 15, 2014, 4:56:41 PM10/15/14
to
On Wed, 15 Oct 2014 15:26:38 -0500, Christopher Pisz
<nos...@notanaddress.com> wrote:

>On 10/15/2014 2:56 PM, Victor Bazarov wrote:
>> 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:
>SNIP
>>> 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?
>>
>
>Because those same Microsoft designers decided to force me to do so.
>They are giving me a WS_DATETIME structure, which has data as an
>unsigned long long that represents 100 nanosecond units since Jan 01
>0001 at midnight.


So use WsDateTimeToFileTime() first.

Or if you can use .NET stuff, just use DateTime.ToString(), or one of
the other couple dozens of conversion functions. Take a look at
http://msdn.microsoft.com/en-us/library/system.datetime.aspx
for more.

Christopher Pisz

unread,
Oct 15, 2014, 5:00:10 PM10/15/14
to
On 10/15/2014 2:56 PM, Victor Bazarov wrote:
> 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...
SNIP

I found the answer. They actually did provide a way. Evidently, they
give a function to convert to a FILETIME (they give an error for pre
1601) and then a function to convert that to a SYSTEMTIME and then I can
convert that to a boost::posix_time and convert that to a string.

Fun stuff!
I thought I was going to have to do it manually.

Your answer did give the clues I needed though. Thanks Victor.




Christopher Pisz

unread,
Oct 15, 2014, 5:02:09 PM10/15/14
to
Yep. Just found that. convert and then convert and then convert again.
Can't use any .NET. Its a native C++ app. Yes, those guys do have it easier.


Scott Neugroschl

unread,
Oct 15, 2014, 5:42:22 PM10/15/14
to
On 10/15/2014 10:01 AM, Bo Persson wrote:
>>
> Some dates just never happened!
>
In my personal experience, 1 Aug 2012 never happened...
But that's a baseball thing.


0 new messages