Thread overview
d_time2FILETIME
Apr 10, 2009
Denis Koroskin
April 10, 2009
Hello,

I want to port the function setFileTimes available in Phobos/Posix to Windows. Does anyone know of a simple way to convert a d_time value to a FILETIME value? d_time is Ticks since 1-1-1970 and FILETIME contains quanta of 100-nanoseconds since 1-1-1601. So there's only some shifting and scaling involved, but the shifting constant is tricky :o).

Andrei
April 10, 2009
On Fri, 10 Apr 2009 18:07:20 +0400, Andrei Alexandrescu <SeeWebsiteForEmail@erdani.org> wrote:

> Hello,
>
> I want to port the function setFileTimes available in Phobos/Posix to Windows. Does anyone know of a simple way to convert a d_time value to a FILETIME value? d_time is Ticks since 1-1-1970 and FILETIME contains quanta of 100-nanoseconds since 1-1-1601. So there's only some shifting and scaling involved, but the shifting constant is tricky :o).
>
> Andrei

You may take a look at Boost Posix Time System: http://www.boost.org/doc/libs/1_38_0/doc/html/date_time/posix_time.html

It has a plenty of functions that convert time to and from various formats, including Posix time and Windows FILETIME.
April 10, 2009
On Fri, 10 Apr 2009 10:07:20 -0400, Andrei Alexandrescu <SeeWebsiteForEmail@erdani.org> wrote:

> Hello,
>
> I want to port the function setFileTimes available in Phobos/Posix to Windows. Does anyone know of a simple way to convert a d_time value to a FILETIME value? d_time is Ticks since 1-1-1970 and FILETIME contains quanta of 100-nanoseconds since 1-1-1601. So there's only some shifting and scaling involved, but the shifting constant is tricky :o).

What you need is the constant that is the number of Ticks (either 100ns ticks or whatever) from 1601 to 1970.

I redid most of the tango time stuff, but those constants were already there before my time (no pun intended).  The number of seconds between 1/1/1601 and 1/1/1970 is 11644473600.  Scale that to whatever you wish.

Note that we do not take into account leap-seconds, not sure if that matters to you.

-Steve
April 10, 2009
Steven Schveighoffer wrote:
> On Fri, 10 Apr 2009 10:07:20 -0400, Andrei Alexandrescu <SeeWebsiteForEmail@erdani.org> wrote:
> 
>> Hello,
>>
>> I want to port the function setFileTimes available in Phobos/Posix to Windows. Does anyone know of a simple way to convert a d_time value to a FILETIME value? d_time is Ticks since 1-1-1970 and FILETIME contains quanta of 100-nanoseconds since 1-1-1601. So there's only some shifting and scaling involved, but the shifting constant is tricky :o).
> 
> What you need is the constant that is the number of Ticks (either 100ns ticks or whatever) from 1601 to 1970.
> 
> I redid most of the tango time stuff, but those constants were already there before my time (no pun intended).  The number of seconds between 1/1/1601 and 1/1/1970 is 11644473600.  Scale that to whatever you wish.
> 
> Note that we do not take into account leap-seconds, not sure if that matters to you.
> 
> -Steve

Thanks a lot! However, something's amiss a bit. I have this code:

    static d_time FILETIME2d_time(const FILETIME *ft)
    {
        SYSTEMTIME st = void;
        if (!FileTimeToSystemTime(ft, &st))
            return d_time_nan;
        return SYSTEMTIME2d_time(&st, 0);
    }

    FILETIME d_time2FILETIME(d_time dt)
    {
        enum ulong ticksFrom1601To1970 = 11_644_473_600UL * TicksPerSecond;
        static assert(10_000_000 % TicksPerSecond == 0);
        ulong t = (dt - ticksFrom1601To1970) * (10_000_000 / TicksPerSecond);
        FILETIME result = void;
        result.dwLowDateTime = cast(uint) (t & uint.max);
        result.dwHighDateTime = cast(uint) (t >> 32);
        return result;
    }

    unittest
    {
        auto dt = getUTCtime;
        auto ft = d_time2FILETIME(dt);
        auto dt1 = FILETIME2d_time(&ft);
        assert(dt == dt1, text(dt, " != ", dt1));
    }

which fails with 1239379868629 != 156195960030165. Let me clarify that a little:

1_239_379_868_629 != 156_195_960_030_165

So it looks like I made a mistake somewhere because the difference is very large. A FILETIME has 100-ns increments, and there are 10_000_000 of those in a second. So I get the ticks from 1601 to dt, then I divide by TicksPerSecond to get the seconds, and finally I multiply by 10M to get the 100-ns count. Where am I wrong?


Thanks,

Andrei
April 10, 2009
Andrei Alexandrescu wrote:
>         ulong t = (dt - ticksFrom1601To1970) * (10_000_000 / TicksPerSecond);

That must be addition, otherwise I go back in time to 1200 or so. Now everything works, thanks to all who answered. The upside of all this is that now setFileTimes works on both Windows and Posix. :o)

Andrei