diff tango/tango/time/Clock.d @ 132:1700239cab2e trunk

[svn r136] MAJOR UNSTABLE UPDATE!!! Initial commit after moving to Tango instead of Phobos. Lots of bugfixes... This build is not suitable for most things.
author lindquist
date Fri, 11 Jan 2008 17:57:40 +0100
parents
children
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tango/tango/time/Clock.d	Fri Jan 11 17:57:40 2008 +0100
@@ -0,0 +1,302 @@
+/*******************************************************************************
+
+        copyright:      Copyright (c) 2007 Kris Bell. All rights reserved
+
+        license:        BSD style: $(LICENSE)
+
+        version:        Feb 2007: Initial release
+
+        author:         Kris
+
+*******************************************************************************/
+
+module tango.time.Clock;
+
+public  import  tango.time.Time;
+
+private import  tango.sys.Common;
+
+private import  tango.core.Exception;
+
+/******************************************************************************
+
+        Exposes UTC time relative to Jan 1st, 1 AD. These values are
+        based upon a clock-tick of 100ns, giving them a span of greater
+        than 10,000 years. These units of time are the foundation of most
+        time and date functionality in Tango.
+
+        Interval is another type of time period, used for measuring a
+        much shorter duration; typically used for timeout periods and
+        for high-resolution timers. These intervals are measured in
+        units of 1 second, and support fractional units (0.001 = 1ms).
+
+*******************************************************************************/
+
+struct Clock
+{
+        version (Win32)
+        {
+                /***************************************************************
+
+                        Return the current time as UTC since the epoch
+
+                ***************************************************************/
+
+                static Time now ()
+                {
+                        FILETIME fTime = void;
+                        GetSystemTimeAsFileTime (&fTime);
+                        return convert (fTime);
+                }
+
+                /***************************************************************
+
+                        Set Date fields to represent the current time. 
+
+                ***************************************************************/
+
+                static DateTime toDate ()
+                {
+                        return toDate (now);
+                }
+
+                /***************************************************************
+
+                        Set fields to represent the provided UTC time. Note 
+                        that the conversion is limited by the underlying OS,
+                        and will fail to operate correctly with Time
+                        values beyond the domain. On Win32 the earliest
+                        representable date is 1601. On linux it is 1970. Both
+                        systems have limitations upon future dates also. Date
+                        is limited to millisecond accuracy at best.
+
+                ***************************************************************/
+
+                static DateTime toDate (Time time)
+                {
+                        DateTime dt = void;
+                        SYSTEMTIME sTime = void;
+
+                        auto fTime = convert (time);
+                        FileTimeToSystemTime (&fTime, &sTime);
+
+                        dt.date.year    = sTime.wYear;
+                        dt.date.month   = sTime.wMonth;
+                        dt.date.day     = sTime.wDay;
+                        dt.date.dow     = sTime.wDayOfWeek;
+                        dt.date.doy     = 0;
+                        dt.date.era     = 0;
+                        dt.time.hours   = sTime.wHour;
+                        dt.time.minutes = sTime.wMinute;
+                        dt.time.seconds = sTime.wSecond;
+                        dt.time.millis  = sTime.wMilliseconds;
+                        return dt;
+                }
+
+                /***************************************************************
+
+                        Convert Date fields to Time
+
+                        Note that the conversion is limited by the underlying 
+                        OS, and will not operate correctly with Time
+                        values beyond the domain. On Win32 the earliest
+                        representable date is 1601. On linux it is 1970. Both
+                        systems have limitations upon future dates also. Date
+                        is limited to millisecond accuracy at best.
+
+                ***************************************************************/
+
+                static Time fromDate (inout DateTime dt)
+                {
+                        SYSTEMTIME sTime = void;
+                        FILETIME   fTime = void;
+
+                        sTime.wYear         = cast(ushort) dt.date.year;
+                        sTime.wMonth        = cast(ushort) dt.date.month;
+                        sTime.wDayOfWeek    = 0;
+                        sTime.wDay          = cast(ushort) dt.date.day;
+                        sTime.wHour         = cast(ushort) dt.time.hours;
+                        sTime.wMinute       = cast(ushort) dt.time.minutes;
+                        sTime.wSecond       = cast(ushort) dt.time.seconds;
+                        sTime.wMilliseconds = cast(ushort) dt.time.millis;
+
+                        SystemTimeToFileTime (&sTime, &fTime);
+                        return convert (fTime);
+                }
+
+                /***************************************************************
+
+                        Convert FILETIME to a Time
+
+                ***************************************************************/
+
+                package static Time convert (FILETIME time)
+                {
+                        auto t = *cast(long*) &time;
+                        t *= 100 / TimeSpan.NanosecondsPerTick;
+                        return Time.epoch1601 + TimeSpan(t);
+                }
+
+                /***************************************************************
+
+                        Convert Time to a FILETIME
+
+                ***************************************************************/
+
+                package static FILETIME convert (Time dt)
+                {
+                        FILETIME time = void;
+
+                        TimeSpan span = dt - Time.epoch1601;
+                        assert (span >= TimeSpan.zero);
+                        *cast(long*) &time.dwLowDateTime = span.ticks;
+                        return time;
+                }
+        }
+
+        version (Posix)
+        {
+                /***************************************************************
+
+                        Return the current time as UTC since the epoch
+
+                ***************************************************************/
+
+                static Time now ()
+                {
+                        timeval tv = void;
+                        if (gettimeofday (&tv, null))
+                            throw new PlatformException ("Clock.now :: Posix timer is not available");
+
+                        return convert (tv);
+                }
+
+                /***************************************************************
+
+                        Set Date fields to represent the current time. 
+
+                ***************************************************************/
+
+                static DateTime toDate ()
+                {
+                        return toDate (now);
+                }
+
+                /***************************************************************
+
+                        Set fields to represent the provided UTC time. Note 
+                        that the conversion is limited by the underlying OS,
+                        and will fail to operate correctly with Time
+                        values beyond the domain. On Win32 the earliest
+                        representable date is 1601. On linux it is 1970. Both
+                        systems have limitations upon future dates also. Date
+                        is limited to millisecond accuracy at best.
+
+                **************************************************************/
+
+                static DateTime toDate (Time time)
+                {
+                        DateTime dt = void;
+                        auto timeval = convert (time);
+                        dt.time.millis = timeval.tv_usec / 1000;
+
+                        tm t = void;
+                        gmtime_r (&timeval.tv_sec, &t);
+        
+                        dt.date.year    = t.tm_year + 1900;
+                        dt.date.month   = t.tm_mon + 1;
+                        dt.date.day     = t.tm_mday;
+                        dt.date.dow     = t.tm_wday;
+                        dt.date.doy     = 0;
+                        dt.date.era     = 0;
+                        dt.time.hours   = t.tm_hour;
+                        dt.time.minutes = t.tm_min;
+                        dt.time.seconds = t.tm_sec;
+                        return dt;
+                }
+
+                /***************************************************************
+
+                        Convert Date fields to Time
+
+                        Note that the conversion is limited by the underlying 
+                        OS, and will not operate correctly with Time
+                        values beyond the domain. On Win32 the earliest
+                        representable date is 1601. On linux it is 1970. Both
+                        systems have limitations upon future dates also. Date
+                        is limited to millisecond accuracy at best.
+
+                ***************************************************************/
+
+                static Time fromDate (inout DateTime dt)
+                {
+                        tm t = void;
+
+                        t.tm_year = dt.date.year - 1900;
+                        t.tm_mon  = dt.date.month - 1;
+                        t.tm_mday = dt.date.day;
+                        t.tm_hour = dt.time.hours;
+                        t.tm_min  = dt.time.minutes;
+                        t.tm_sec  = dt.time.seconds;
+
+                        auto seconds = timegm (&t);
+                        return Time.epoch1970 + 
+                               TimeSpan.seconds(seconds) + 
+                               TimeSpan.millis(dt.time.millis);
+                }
+
+                /***************************************************************
+
+                        Convert timeval to a Time
+
+                ***************************************************************/
+
+                package static Time convert (inout timeval tv)
+                {
+                        return Time.epoch1970 + 
+                               TimeSpan.seconds(tv.tv_sec) + 
+                               TimeSpan.micros(tv.tv_usec);
+                }
+
+                /***************************************************************
+
+                        Convert Time to a timeval
+
+                ***************************************************************/
+
+                package static timeval convert (Time time)
+                {
+                        timeval tv = void;
+
+                        TimeSpan span = time - time.epoch1970;
+                        assert (span >= TimeSpan.zero);
+                        tv.tv_sec  = span.seconds;
+                        tv.tv_usec = span.micros % 1_000_000L;
+                        return tv;
+                }
+        }
+}
+
+
+
+debug (UnitTest)
+{
+        unittest 
+        {
+                auto time = Clock.now;
+                assert (Clock.convert(Clock.convert(time)) is time);
+
+                time -= TimeSpan(time.ticks % TimeSpan.TicksPerSecond);
+                auto date = Clock.toDate(time);
+
+                assert (time is Clock.fromDate(date));
+        }
+}
+
+debug (Clock)
+{
+        void main() 
+        {
+                auto time = Clock.now;
+        }
+}
\ No newline at end of file