diff lphobos/std/date.d @ 473:373489eeaf90

Applied downs' lphobos update
author Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
date Mon, 04 Aug 2008 19:28:49 +0200
parents
children
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lphobos/std/date.d	Mon Aug 04 19:28:49 2008 +0200
@@ -0,0 +1,1074 @@
+
+// Written in the D programming language.
+
+/**
+ * Dates are represented in several formats. The date implementation revolves
+ * around a central type, d_time, from which other formats are converted to and
+ * from.
+ * Dates are calculated using the Gregorian calendar.
+ * References:
+ *	$(LINK2 http://en.wikipedia.org/wiki/Gregorian_calendar, Gregorian calendar (Wikipedia))
+ * Macros:
+ *	WIKI = Phobos/StdDate
+ */
+
+// Copyright (c) 1999-2007 by Digital Mars
+// All Rights Reserved
+// written by Walter Bright
+// www.digitalmars.com
+
+/* NOTE: This file has been patched from the original DMD distribution to
+   work with the GDC compiler.
+
+   Modified by David Friedman, May 2005
+*/
+
+module std.date;
+
+private import std.stdio;
+private import std.dateparse;
+
+/**
+ * d_time is a signed arithmetic type giving the time elapsed since January 1,
+ * 1970.
+ * Negative values are for dates preceding 1970. The time unit used is Ticks.
+ * Ticks are milliseconds or smaller intervals.
+ *
+ * The usual arithmetic operations can be performed on d_time, such as adding,
+ * subtracting, etc. Elapsed time in Ticks can be computed by subtracting a
+ * starting d_time from an ending d_time. 
+ */
+alias long d_time;
+
+/**
+ * A value for d_time that does not represent a valid time.
+ */
+const d_time d_time_nan = long.min;
+
+/**
+ * Time broken down into its components.
+ */
+struct Date
+{
+    int year = int.min;	/// use int.min as "nan" year value
+    int month;		/// 1..12
+    int day;		/// 1..31
+    int hour;		/// 0..23
+    int minute;		/// 0..59
+    int second;		/// 0..59
+    int ms;		/// 0..999
+    int weekday;	/// 0: not specified, 1..7: Sunday..Saturday
+    int tzcorrection = int.min;	/// -1200..1200 correction in hours
+
+    /// Parse date out of string s[] and store it in this Date instance.
+    void parse(string s)
+    {
+	DateParse dp;
+
+	dp.parse(s, *this);
+    }
+}
+
+enum
+{
+	HoursPerDay    = 24,
+	MinutesPerHour = 60,
+	msPerMinute    = 60 * 1000,
+	msPerHour      = 60 * msPerMinute,
+	msPerDay       = 86400000,
+	TicksPerMs     = 1,
+	TicksPerSecond = 1000,			/// Will be at least 1000
+	TicksPerMinute = TicksPerSecond * 60,
+	TicksPerHour   = TicksPerMinute * 60,
+	TicksPerDay    = TicksPerHour   * 24,
+}
+
+d_time LocalTZA = 0;
+
+
+const char[] daystr = "SunMonTueWedThuFriSat";
+const char[] monstr = "JanFebMarAprMayJunJulAugSepOctNovDec";
+
+const int[12] mdays = [ 0,31,59,90,120,151,181,212,243,273,304,334 ];
+
+/********************************
+ * Compute year and week [1..53] from t. The ISO 8601 week 1 is the first week
+ * of the year that includes January 4. Monday is the first day of the week.
+ * References:
+ *	$(LINK2 http://en.wikipedia.org/wiki/ISO_8601, ISO 8601 (Wikipedia))
+ */
+
+void toISO8601YearWeek(d_time t, out int year, out int week)
+{
+    year = YearFromTime(t);
+
+    int yday = Day(t) - DayFromYear(year);
+    int d;
+    int w;
+    int ydaybeg;
+
+    /* Determine day of week Jan 4 falls on.
+     * Weeks begin on a Monday.
+     */
+
+    d = DayFromYear(year);
+    w = (d + 3/*Jan4*/ + 3) % 7;
+    if (w < 0)
+        w += 7;
+
+    /* Find yday of beginning of ISO 8601 year
+     */
+    ydaybeg = 3/*Jan4*/ - w;
+
+    /* Check if yday is actually the last week of the previous year
+     */
+    if (yday < ydaybeg)
+    {
+	year -= 1;
+	week = 53;
+        return;
+    }
+
+    /* Check if yday is actually the first week of the next year
+     */
+    if (yday >= 362)                            // possible
+    {   int d2;
+        int ydaybeg2;
+
+        d2 = DayFromYear(year + 1);
+        w = (d2 + 3/*Jan4*/ + 3) % 7;
+        if (w < 0)
+            w += 7;
+        //printf("w = %d\n", w);
+        ydaybeg2 = 3/*Jan4*/ - w;
+        if (d + yday >= d2 + ydaybeg2)
+        {
+	    year += 1;
+	    week = 1;
+            return;
+        }
+    }
+
+    week = (yday - ydaybeg) / 7 + 1;
+}
+
+/* ***********************************
+ * Divide time by divisor. Always round down, even if d is negative.
+ */
+
+d_time floor(d_time d, int divisor)
+{
+    if (d < 0)
+	d -= divisor - 1;
+    return d / divisor;
+}
+
+int dmod(d_time n, d_time d)
+{   d_time r;
+
+    r = n % d;
+    if (r < 0)
+	r += d;
+    assert(cast(int)r == r);
+    return cast(int)r;
+}
+
+int HourFromTime(d_time t)
+{
+    return dmod(floor(t, msPerHour), HoursPerDay);
+}
+
+int MinFromTime(d_time t)
+{
+    return dmod(floor(t, msPerMinute), MinutesPerHour);
+}
+
+int SecFromTime(d_time t)
+{
+    return dmod(floor(t, TicksPerSecond), 60);
+}
+
+int msFromTime(d_time t)
+{
+    return dmod(t / (TicksPerSecond / 1000), 1000);
+}
+
+int TimeWithinDay(d_time t)
+{
+    return dmod(t, msPerDay);
+}
+
+d_time toInteger(d_time n)
+{
+    return n;
+}
+
+int Day(d_time t)
+{
+    return cast(int)floor(t, msPerDay);
+}
+
+int LeapYear(int y)
+{
+    return ((y & 3) == 0 &&
+	    (y % 100 || (y % 400) == 0));
+}
+
+int DaysInYear(int y)
+{
+    return 365 + LeapYear(y);
+}
+
+int DayFromYear(int y)
+{
+    return cast(int) (365 * (y - 1970) +
+		floor((y - 1969), 4) -
+		floor((y - 1901), 100) +
+		floor((y - 1601), 400));
+}
+
+d_time TimeFromYear(int y)
+{
+    return cast(d_time)msPerDay * DayFromYear(y);
+}
+
+/*****************************
+ * Calculates the year from the d_time t.
+ */
+
+int YearFromTime(d_time t)
+{   int y;
+
+    if (t == d_time_nan)
+	return 0;
+
+    // Hazard a guess
+    //y = 1970 + cast(int) (t / (365.2425 * msPerDay));
+    // Use integer only math
+    y = 1970 + cast(int) (t / (3652425 * (msPerDay / 10000)));
+
+    if (TimeFromYear(y) <= t)
+    {
+	while (TimeFromYear(y + 1) <= t)
+	    y++;
+    }
+    else
+    {
+	do
+	{
+	    y--;
+	}
+	while (TimeFromYear(y) > t);
+    }
+    return y;
+}
+
+/*******************************
+ * Determines if d_time t is a leap year.
+ *
+ * A leap year is every 4 years except years ending in 00 that are not
+ * divsible by 400.
+ *
+ * Returns: !=0 if it is a leap year.
+ *
+ * References:
+ *	$(LINK2 http://en.wikipedia.org/wiki/Leap_year, Wikipedia)
+ */
+
+int inLeapYear(d_time t)
+{
+    return LeapYear(YearFromTime(t));
+}
+
+/*****************************
+ * Calculates the month from the d_time t.
+ *
+ * Returns: Integer in the range 0..11, where
+ *	0 represents January and 11 represents December.
+ */
+
+int MonthFromTime(d_time t)
+{
+    int day;
+    int month;
+    int year;
+
+    year = YearFromTime(t);
+    day = Day(t) - DayFromYear(year);
+
+    if (day < 59)
+    {
+	if (day < 31)
+	{   assert(day >= 0);
+	    month = 0;
+	}
+	else
+	    month = 1;
+    }
+    else
+    {
+	day -= LeapYear(year);
+	if (day < 212)
+	{
+	    if (day < 59)
+		month = 1;
+	    else if (day < 90)
+		month = 2;
+	    else if (day < 120)
+		month = 3;
+	    else if (day < 151)
+		month = 4;
+	    else if (day < 181)
+		month = 5;
+	    else
+		month = 6;
+	}
+	else
+	{
+	    if (day < 243)
+		month = 7;
+	    else if (day < 273)
+		month = 8;
+	    else if (day < 304)
+		month = 9;
+	    else if (day < 334)
+		month = 10;
+	    else if (day < 365)
+		month = 11;
+	    else
+		assert(0);
+	}
+    }
+    return month;
+}
+
+/*******************************
+ * Compute which day in a month a d_time t is.
+ * Returns:
+ *	Integer in the range 1..31
+ */
+int DateFromTime(d_time t)
+{
+    int day;
+    int leap;
+    int month;
+    int year;
+    int date;
+
+    year = YearFromTime(t);
+    day = Day(t) - DayFromYear(year);
+    leap = LeapYear(year);
+    month = MonthFromTime(t);
+    switch (month)
+    {
+	case 0:	 date = day +   1;		break;
+	case 1:	 date = day -  30;		break;
+	case 2:	 date = day -  58 - leap;	break;
+	case 3:	 date = day -  89 - leap;	break;
+	case 4:	 date = day - 119 - leap;	break;
+	case 5:	 date = day - 150 - leap;	break;
+	case 6:	 date = day - 180 - leap;	break;
+	case 7:	 date = day - 211 - leap;	break;
+	case 8:	 date = day - 242 - leap;	break;
+	case 9:	 date = day - 272 - leap;	break;
+	case 10: date = day - 303 - leap;	break;
+	case 11: date = day - 333 - leap;	break;
+	default:
+	    assert(0);
+    }
+    return date;
+}
+
+/*******************************
+ * Compute which day of the week a d_time t is.
+ * Returns:
+ *	Integer in the range 0..6, where 0 represents Sunday
+ *	and 6 represents Saturday.
+ */
+int WeekDay(d_time t)
+{   int w;
+
+    w = (cast(int)Day(t) + 4) % 7;
+    if (w < 0)
+	w += 7;
+    return w;
+}
+
+/***********************************
+ * Convert from UTC to local time.
+ */
+
+d_time UTCtoLocalTime(d_time t)
+{
+    return (t == d_time_nan)
+	? d_time_nan
+	: t + LocalTZA + DaylightSavingTA(t);
+}
+
+/***********************************
+ * Convert from local time to UTC.
+ */
+
+d_time LocalTimetoUTC(d_time t)
+{
+    return (t == d_time_nan)
+	? d_time_nan
+	: t - LocalTZA - DaylightSavingTA(t - LocalTZA);
+}
+
+
+d_time MakeTime(d_time hour, d_time min, d_time sec, d_time ms)
+{
+    return hour * TicksPerHour +
+	   min * TicksPerMinute +
+	   sec * TicksPerSecond +
+	   ms * TicksPerMs;
+}
+
+
+d_time MakeDay(d_time year, d_time month, d_time date)
+{   d_time t;
+    int y;
+    int m;
+    int leap;
+
+    y = cast(int)(year + floor(month, 12));
+    m = dmod(month, 12);
+
+    leap = LeapYear(y);
+    t = TimeFromYear(y) + cast(d_time)mdays[m] * msPerDay;
+    if (leap && month >= 2)
+	t += msPerDay;
+
+    if (YearFromTime(t) != y ||
+	MonthFromTime(t) != m ||
+	DateFromTime(t) != 1)
+    {
+	return  d_time_nan;
+    }
+
+    return Day(t) + date - 1;
+}
+
+d_time MakeDate(d_time day, d_time time)
+{
+    if (day == d_time_nan || time == d_time_nan)
+	return d_time_nan;
+
+    return day * TicksPerDay + time;
+}
+
+d_time TimeClip(d_time time)
+{
+    //printf("TimeClip(%g) = %g\n", time, toInteger(time));
+
+    return toInteger(time);
+}
+
+/*************************************
+ * Converts UTC time into a text string of the form:
+ * "Www Mmm dd hh:mm:ss GMT+-TZ yyyy".
+ * For example, "Tue Apr 02 02:04:57 GMT-0800 1996".
+ * If time is invalid, i.e. is d_time_nan,
+ * the string "Invalid date" is returned.
+ *
+ * Example:
+ * ------------------------------------
+  d_time lNow;
+  char[] lNowString;
+
+  // Grab the date and time relative to UTC
+  lNow = std.date.getUTCtime();
+  // Convert this into the local date and time for display.
+  lNowString = std.date.toString(lNow);
+ * ------------------------------------
+ */
+
+string toString(d_time time)
+{
+    d_time t;
+    char sign;
+    int hr;
+    int mn;
+    int len;
+    d_time offset;
+    d_time dst;
+
+    // Years are supposed to be -285616 .. 285616, or 7 digits
+    // "Tue Apr 02 02:04:57 GMT-0800 1996"
+    char[] buffer = new char[29 + 7 + 1];
+
+    if (time == d_time_nan)
+	return "Invalid Date";
+
+    dst = DaylightSavingTA(time);
+    offset = LocalTZA + dst;
+    t = time + offset;
+    sign = '+';
+    if (offset < 0)
+    {	sign = '-';
+//	offset = -offset;
+	offset = -(LocalTZA + dst);
+    }
+
+    mn = cast(int)(offset / msPerMinute);
+    hr = mn / 60;
+    mn %= 60;
+
+    //printf("hr = %d, offset = %g, LocalTZA = %g, dst = %g, + = %g\n", hr, offset, LocalTZA, dst, LocalTZA + dst);
+
+    len = sprintf(buffer.ptr, "%.3s %.3s %02d %02d:%02d:%02d GMT%c%02d%02d %d",
+	&daystr[WeekDay(t) * 3],
+	&monstr[MonthFromTime(t) * 3],
+	DateFromTime(t),
+	HourFromTime(t), MinFromTime(t), SecFromTime(t),
+	sign, hr, mn,
+	/*cast(long)*/YearFromTime(t));
+
+    // Ensure no buggy buffer overflows
+    //printf("len = %d, buffer.length = %d\n", len, buffer.length);
+    assert(len < buffer.length);
+
+    return buffer[0 .. len];
+}
+
+/***********************************
+ * Converts t into a text string of the form: "Www, dd Mmm yyyy hh:mm:ss UTC".
+ * If t is invalid, "Invalid date" is returned.
+ */
+
+string toUTCString(d_time t)
+{
+    // Years are supposed to be -285616 .. 285616, or 7 digits
+    // "Tue, 02 Apr 1996 02:04:57 GMT"
+    char[] buffer = new char[25 + 7 + 1];
+    int len;
+
+    if (t == d_time_nan)
+	return "Invalid Date";
+
+    len = sprintf(buffer.ptr, "%.3s, %02d %.3s %d %02d:%02d:%02d UTC",
+	&daystr[WeekDay(t) * 3], DateFromTime(t),
+	&monstr[MonthFromTime(t) * 3],
+	YearFromTime(t),
+	HourFromTime(t), MinFromTime(t), SecFromTime(t));
+
+    // Ensure no buggy buffer overflows
+    assert(len < buffer.length);
+
+    return buffer[0 .. len];
+}
+
+/************************************
+ * Converts the date portion of time into a text string of the form: "Www Mmm dd
+ * yyyy", for example, "Tue Apr 02 1996".
+ * If time is invalid, "Invalid date" is returned.
+ */
+
+string toDateString(d_time time)
+{
+    d_time t;
+    d_time offset;
+    d_time dst;
+    int len;
+
+    // Years are supposed to be -285616 .. 285616, or 7 digits
+    // "Tue Apr 02 1996"
+    char[] buffer = new char[29 + 7 + 1];
+
+    if (time == d_time_nan)
+	return "Invalid Date";
+
+    dst = DaylightSavingTA(time);
+    offset = LocalTZA + dst;
+    t = time + offset;
+
+    len = sprintf(buffer.ptr, "%.3s %.3s %02d %d",
+	&daystr[WeekDay(t) * 3],
+	&monstr[MonthFromTime(t) * 3],
+	DateFromTime(t),
+	/*cast(long)*/YearFromTime(t));
+
+    // Ensure no buggy buffer overflows
+    assert(len < buffer.length);
+
+    return buffer[0 .. len];
+}
+
+/******************************************
+ * Converts the time portion of t into a text string of the form: "hh:mm:ss
+ * GMT+-TZ", for example, "02:04:57 GMT-0800".
+ * If t is invalid, "Invalid date" is returned.
+ * The input must be in UTC, and the output is in local time.
+ */
+
+string toTimeString(d_time time)
+{
+    d_time t;
+    char sign;
+    int hr;
+    int mn;
+    int len;
+    d_time offset;
+    d_time dst;
+
+    // "02:04:57 GMT-0800"
+    char[] buffer = new char[17 + 1];
+
+    if (time == d_time_nan)
+	return "Invalid Date";
+
+    dst = DaylightSavingTA(time);
+    offset = LocalTZA + dst;
+    t = time + offset;
+    sign = '+';
+    if (offset < 0)
+    {	sign = '-';
+//	offset = -offset;
+	offset = -(LocalTZA + dst);
+    }
+
+    mn = cast(int)(offset / msPerMinute);
+    hr = mn / 60;
+    mn %= 60;
+
+    //printf("hr = %d, offset = %g, LocalTZA = %g, dst = %g, + = %g\n", hr, offset, LocalTZA, dst, LocalTZA + dst);
+
+    len = sprintf(buffer.ptr, "%02d:%02d:%02d GMT%c%02d%02d",
+	HourFromTime(t), MinFromTime(t), SecFromTime(t),
+	sign, hr, mn);
+
+    // Ensure no buggy buffer overflows
+    assert(len < buffer.length);
+
+    // Lop off terminating 0
+    return buffer[0 .. len];
+}
+
+
+/******************************************
+ * Parses s as a textual date string, and returns it as a d_time.
+ * If the string is not a valid date, d_time_nan is returned.
+ */
+
+d_time parse(string s)
+{
+    Date dp;
+    d_time n;
+    d_time day;
+    d_time time;
+
+    try
+    {
+	dp.parse(s);
+
+	//writefln("year = %d, month = %d, day = %d", dp.year, dp.month, dp.day);
+	//writefln("%02d:%02d:%02d.%03d", dp.hour, dp.minute, dp.second, dp.ms);
+	//writefln("weekday = %d, ampm = %d, tzcorrection = %d", dp.weekday, 1, dp.tzcorrection);
+
+	time = MakeTime(dp.hour, dp.minute, dp.second, dp.ms);
+	if (dp.tzcorrection == int.min)
+	    time -= LocalTZA;
+	else
+	{
+	    time += cast(d_time)(dp.tzcorrection / 100) * msPerHour +
+		    cast(d_time)(dp.tzcorrection % 100) * msPerMinute;
+	}
+	day = MakeDay(dp.year, dp.month - 1, dp.day);
+	n = MakeDate(day,time);
+	n = TimeClip(n);
+    }
+    catch
+    {
+	n =  d_time_nan;		// erroneous date string
+    }
+    return n;
+}
+
+static this()
+{
+    LocalTZA = getLocalTZA();
+    //printf("LocalTZA = %g, %g\n", LocalTZA, LocalTZA / msPerHour);
+}
+
+version (Win32)
+{
+
+    private import std.c.windows.windows;
+    //import c.time;
+
+    /******
+     * Get current UTC time.
+     */
+    d_time getUTCtime()
+    {
+	SYSTEMTIME st;
+	d_time n;
+
+	GetSystemTime(&st);		// get time in UTC
+	n = SYSTEMTIME2d_time(&st, 0);
+	return n;
+	//return c.time.time(null) * TicksPerSecond;
+    }
+
+    static d_time FILETIME2d_time(FILETIME *ft)
+    {   SYSTEMTIME st;
+
+	if (!FileTimeToSystemTime(ft, &st))
+	    return d_time_nan;
+	return SYSTEMTIME2d_time(&st, 0);
+    }
+
+    static d_time SYSTEMTIME2d_time(SYSTEMTIME *st, d_time t)
+    {
+	d_time n;
+	d_time day;
+	d_time time;
+
+	if (st.wYear)
+	{
+	    time = MakeTime(st.wHour, st.wMinute, st.wSecond, st.wMilliseconds);
+	    day = MakeDay(st.wYear, st.wMonth - 1, st.wDay);
+	}
+	else
+	{   // wDayOfWeek is weekday, wDay is which week in the month
+	    int year;
+	    int wd;
+	    int mday;
+	    int month;
+	    d_time x;
+
+	    year = YearFromTime(t);
+	    month = st.wMonth - 1;
+	    x = MakeDay(year, month, 1);
+	    wd = WeekDay(MakeDate(x, 0));
+
+	    mday = (7 - wd + st.wDayOfWeek);
+	    if (mday >= 7)
+		mday -= 7;
+	    mday += (st.wDay - 1) * 7 + 1;
+	    //printf("month = %d, wDayOfWeek = %d, wDay = %d, mday = %d\n", st.wMonth, st.wDayOfWeek, st.wDay, mday);
+
+	    day = MakeDay(year, month, mday);
+	    time = 0;
+	}
+	n = MakeDate(day,time);
+	n = TimeClip(n);
+	return n;
+    }
+
+    d_time getLocalTZA()
+    {
+	d_time t;
+	DWORD r;
+	TIME_ZONE_INFORMATION tzi;
+
+	/* http://msdn.microsoft.com/library/en-us/sysinfo/base/gettimezoneinformation.asp
+	 * http://msdn2.microsoft.com/en-us/library/ms725481.aspx
+	 */
+	r = GetTimeZoneInformation(&tzi);
+	//printf("bias = %d\n", tzi.Bias);
+	//printf("standardbias = %d\n", tzi.StandardBias);
+	//printf("daylightbias = %d\n", tzi.DaylightBias);
+	switch (r)
+	{
+	    case TIME_ZONE_ID_STANDARD:
+		t = -(tzi.Bias + tzi.StandardBias) * cast(d_time)(60 * TicksPerSecond);
+		break;
+	    case TIME_ZONE_ID_DAYLIGHT:
+		//t = -(tzi.Bias + tzi.DaylightBias) * cast(d_time)(60 * TicksPerSecond);
+		//break;
+	    case TIME_ZONE_ID_UNKNOWN:
+		t = -(tzi.Bias) * cast(d_time)(60 * TicksPerSecond);
+		break;
+
+	    default:
+		t = 0;
+		break;
+	}
+
+	return t;
+    }
+
+    /*
+     * Get daylight savings time adjust for time dt.
+     */
+
+    int DaylightSavingTA(d_time dt)
+    {
+	int t;
+	DWORD r;
+	TIME_ZONE_INFORMATION tzi;
+	d_time ts;
+	d_time td;
+
+	/* http://msdn.microsoft.com/library/en-us/sysinfo/base/gettimezoneinformation.asp
+	 */
+	r = GetTimeZoneInformation(&tzi);
+	t = 0;
+	switch (r)
+	{
+	    case TIME_ZONE_ID_STANDARD:
+	    case TIME_ZONE_ID_DAYLIGHT:
+		if (tzi.StandardDate.wMonth == 0 ||
+		    tzi.DaylightDate.wMonth == 0)
+		    break;
+
+		ts = SYSTEMTIME2d_time(&tzi.StandardDate, dt);
+		td = SYSTEMTIME2d_time(&tzi.DaylightDate, dt);
+
+		if (td <= dt && dt <= ts)
+		{
+		    t = -tzi.DaylightBias * (60 * TicksPerSecond);
+		    //printf("DST is in effect, %d\n", t);
+		}
+		else
+		{
+		    //printf("no DST\n");
+		}
+		break;
+
+	    case TIME_ZONE_ID_UNKNOWN:
+		// Daylight savings time not used in this time zone
+		break;
+
+	    default:
+		assert(0);
+	}
+	return t;
+    }
+}
+else version (linux)
+{
+
+    private import std.c.linux.linux;
+
+    d_time getUTCtime()
+    {   timeval tv;
+
+	//printf("getUTCtime()\n");
+	if (gettimeofday(&tv, null))
+	{   // Some error happened - try time() instead
+	    return time(null) * TicksPerSecond;
+	}
+
+	return tv.tv_sec * cast(d_time)TicksPerSecond +
+		(tv.tv_usec / (1000000 / cast(d_time)TicksPerSecond));
+    }
+
+    d_time getLocalTZA()
+    {
+	__time_t t;
+
+	time(&t);
+	localtime(&t);	// this will set timezone
+	return -(timezone * TicksPerSecond);
+    }
+
+    /*
+     * Get daylight savings time adjust for time dt.
+     */
+
+    int DaylightSavingTA(d_time dt)
+    {
+	tm *tmp;
+	int dst = 0;
+
+	if (dt != d_time_nan)
+	{
+	    d_time seconds = dt / TicksPerSecond;
+	    int t;
+	    t = cast(int) seconds;
+	    if (t == seconds)	// if in range
+	    {
+		tmp = localtime(cast(__time_t*)&t);
+		if (tmp.tm_isdst > 0)
+		    dst = TicksPerHour;	// BUG: Assume daylight savings time is plus one hour.
+	    }
+	    else	// out of range for system time, use our own calculation
+	    {	// Daylight savings time goes from 2 AM the first Sunday
+		// in April through 2 AM the last Sunday in October
+
+		dt -= LocalTZA;
+
+		int year = YearFromTime(dt);
+		int leap = LeapYear(dt);
+		//writefln("year = %s, leap = %s, month = %s", year, leap, MonthFromTime(dt));
+
+		d_time start = TimeFromYear(year);		// Jan 1
+		d_time end = start;
+		// Move fwd to Apr 1
+		start += cast(d_time)(mdays[3] + leap) * TicksPerDay;
+		// Advance a day at a time until we find Sunday (0)
+		while (WeekDay(start) != 0)
+		    start += TicksPerDay;
+
+		// Move fwd to Oct 30
+		end += cast(d_time)(mdays[9] + leap + 30) * TicksPerDay;
+		// Back up a day at a time until we find Sunday (0)
+		while (WeekDay(end) != 0)		// 0 is Sunday
+		    end -= TicksPerDay;
+
+		dt -= 2 * TicksPerHour;			// 2 AM
+		if (dt >= start && dt <= end)
+		    dst = TicksPerHour;
+		//writefln("start = %s, dt = %s, end = %s, dst = %s", start, dt, end, dst);
+	    }
+	}
+	return dst;
+    }
+
+}
+else version (Unix)
+{
+    // for now, just copy linux
+    private import std.c.unix.unix;
+
+    d_time getUTCtime()
+    {   timeval tv;
+
+	if (gettimeofday(&tv, null))
+	{   // Some error happened - try time() instead
+	    return time(null) * TicksPerSecond;
+	}
+
+	return tv.tv_sec * cast(d_time)TicksPerSecond +
+		(tv.tv_usec / (1000000 / cast(d_time)TicksPerSecond));
+    }
+
+    private extern (C) time_t _d_gnu_cbridge_tza();
+    
+    d_time getLocalTZA()
+    {
+	return _d_gnu_cbridge_tza() * TicksPerSecond;
+    }
+
+    /*
+     * Get daylight savings time adjust for time dt.
+     */
+
+    int DaylightSavingTA(d_time dt)
+    {
+	tm *tmp;
+	time_t t;
+	int dst = 0;
+
+	if (dt != d_time_nan)
+	{
+	    d_time seconds = dt / TicksPerSecond;
+	    t = cast(time_t) seconds;
+	    if (t == seconds)	// if in range
+	    {
+		tmp = localtime(&t);
+		if (tmp.tm_isdst > 0)
+		    dst = TicksPerHour;	// BUG: Assume daylight savings time is plus one hour.
+	    }
+	    else	// out of range for system time, use our own calculation
+	    {	// Daylight savings time goes from 2 AM the first Sunday
+		// in April through 2 AM the last Sunday in October
+
+		dt -= LocalTZA;
+
+		int year = YearFromTime(dt);
+		int leap = LeapYear(cast(int)dt);
+		//writefln("year = %s, leap = %s, month = %s", year, leap, MonthFromTime(dt));
+
+		d_time start = TimeFromYear(year);		// Jan 1
+		d_time end = start;
+		// Move fwd to Apr 1
+		start += cast(d_time)(mdays[3] + leap) * TicksPerDay;
+		// Advance a day at a time until we find Sunday (0)
+		while (WeekDay(start) != 0)
+		    start += TicksPerDay;
+
+		// Move fwd to Oct 30
+		end += cast(d_time)(mdays[9] + leap + 30) * TicksPerDay;
+		// Back up a day at a time until we find Sunday (0)
+		while (WeekDay(end) != 0)		// 0 is Sunday
+		    end -= TicksPerDay;
+
+		dt -= 2 * TicksPerHour;			// 2 AM
+		if (dt >= start && dt <= end)
+		    dst = TicksPerHour;
+		//writefln("start = %s, dt = %s, end = %s, dst = %s", start, dt, end, dst);
+	    }
+	}
+	return dst;
+    }
+}
+else version (NoSystem)
+{
+    d_time getLocalTZA() { return 0; }    
+    int DaylightSavingTA(d_time dt) { return 0; }
+}
+
+/+ ====================== DOS File Time =============================== +/
+
+/***
+ * Type representing the DOS file date/time format.
+ */
+typedef uint DosFileTime;
+
+/************************************
+ * Convert from DOS file date/time to d_time.
+ */
+
+d_time toDtime(DosFileTime time)
+{
+    uint dt = cast(uint)time;
+
+    if (dt == 0)
+	return d_time_nan;
+
+    int year = ((dt >> 25) & 0x7F) + 1980;
+    int month = ((dt >> 21) & 0x0F) - 1;	// 0..12
+    int dayofmonth = ((dt >> 16) & 0x1F);	// 0..31
+    int hour = (dt >> 11) & 0x1F;		// 0..23
+    int minute = (dt >> 5) & 0x3F;		// 0..59
+    int second = (dt << 1) & 0x3E;		// 0..58 (in 2 second increments)
+
+    d_time t;
+
+    t = std.date.MakeDate(std.date.MakeDay(year, month, dayofmonth),
+	    std.date.MakeTime(hour, minute, second, 0));
+
+    assert(YearFromTime(t) == year);
+    assert(MonthFromTime(t) == month);
+    assert(DateFromTime(t) == dayofmonth);
+    assert(HourFromTime(t) == hour);
+    assert(MinFromTime(t) == minute);
+    assert(SecFromTime(t) == second);
+
+    t -= LocalTZA + DaylightSavingTA(t);
+
+    return t;
+}
+
+/****************************************
+ * Convert from d_time to DOS file date/time.
+ */
+
+DosFileTime toDosFileTime(d_time t)
+{   uint dt;
+
+    if (t == d_time_nan)
+	return cast(DosFileTime)0;
+
+    t += LocalTZA + DaylightSavingTA(t);
+
+    uint year = YearFromTime(t);
+    uint month = MonthFromTime(t);
+    uint dayofmonth = DateFromTime(t);
+    uint hour = HourFromTime(t);
+    uint minute = MinFromTime(t);
+    uint second = SecFromTime(t);
+
+    dt = (year - 1980) << 25;
+    dt |= ((month + 1) & 0x0F) << 21;
+    dt |= (dayofmonth & 0x1F) << 16;
+    dt |= (hour & 0x1F) << 11;
+    dt |= (minute & 0x3F) << 5;
+    dt |= (second >> 1) & 0x1F;
+
+    return cast(DosFileTime)dt;
+}