Mercurial > projects > ldc
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