22,25c22,23
< private import std.conv;
< private import std.stdio;
< private import std.dateparse;
< private import std.string;
---
> private import std.stdio;
> private import std.dateparse;
46,277d43
<  * Time of day broken down into its components.
<  */
< struct Time
< {
<     int hour;		   /// 0..23
<     int minute;		/// 0..59
<     int second;		/// 0..59
<     int ms;		      /// 0..999
< 
<     void fromTimeParts(int h, int m, int s, int msec = 0)
<     {
<        if (h < 0 || h > 23)
<           throw new Exception("Hour value out of range.");
<        if (m < 0 || m > 59)
<           throw new Exception("Minute value out of range.");
<        if (s < 0 || s > 59)
<           throw new Exception("Second value out of range.");
<        if (ms < 0 || ms > 999)
<           throw new Exception("Millisecond value out of range.");
<        hour = h;
<        minute = m;
<        second = s;
<        ms = msec;
<     }
< 
<     void fromTicks(d_time t)
<     {   
<         hour = HourFromTime(t);
<         minute = MinFromTime(t);
<         second = SecFromTime(t);
<         ms = msFromTime(t);
<     }
<     void parse(string s)
<     {
<         // Will parse time strings in the following forms:
<         //   22:02
<         //   22:02:02
<         //   22:02:02:000
<         //   22:02:02.000
<         //   10:02pm
<         //   10:02:02pm
<         //   10:02:02:000pm
<         //   10:02:02.000pm
<         //   09:02
<         //   09:02am
<         //   09:02:02
<         //   9:02:02
<         //   09:02:02am
<         //   9:12
<         //   9:12am
<         //   9:12:12am
<         //   ...
< 
<         int sp;
<         int lms;
< 
<         void adjusthour(bool pm)
<         {
<            if (pm)
<            {
<               if (hour < 12)
<                  hour += 12;
<               else if (hour > 12)
<                  throw new Exception("Inconsistent hour with pm.");
<            }
<            else
<            {
<               if (hour > 12)
<                  throw new Exception("Inconsistent hour with am.");
<               if (hour == 12)
<                  hour = 0;
<            }
<         }
< 
<         int splitmsp(string msp, out int msv)
<         {
<            if (msp.length == 0)
<               return 0;
<            msv = std.conv.parse!(int)(msp);
<            if (msp.length == 0)
<               return 0;
<            if (msp == "am")
<               return 1;
<            else if (msp == "pm")
<               return 2;
<            else
<               throw new Exception("Expected am, pm or nothing.");
<         }
< 
<         bool splithop(string hop, out int hv)
<         {
<             hv = std.conv.parse!(int)(hop);
<             if (hop == "am")
<                 return false;
<             else if (hop == "pm")
<                 return true;
<             else
<                 throw new Exception("Expected am or pm.");
<         }
< 
<         bool splitmsop(string sop, out int sv)
<         {
<            sv = std.conv.parse!(int)(sop);
<            if (sop == "am")
<               return false;
<            else if (sop == "pm")
<               return true;
<            else
<               throw new Exception("Expected am or pm.");
<         }
< 
<         void splitsp(string last, out int sv, out int msv)
<         {
<            int dot = find(last, '.');
<            if (dot == -1)
<            {
<               msv = 0;
<               if (last.length == 4)
<               {
<                  bool pm = splitmsop(last, sv);
<                  adjusthour(pm);
<               }
<               else
<                  throw new Exception("Expected NNam or NNpm.");
<            }
<            else
<            {
<               if (dot != 2)
<                  throw new Exception("Seconds not 2 digits in time string.");
<               sv = std.conv.parse!(int)(last);
<               munch(last, ".");
<               if (last.length > 5)
<                  throw new Exception("Malformed miliseconds-am/pm string.");
<               if (last.length == 0)
<                  msv = 0;
<               else
<               {
<                  int dp = splitmsp(last, msv);
<                  if (dp == 1)
<                     adjusthour(false);
<                  else if (dp == 2)
<                     adjusthour(true);
<               }
<            }
<         }
< 
<         bool tmc = false;
<         s = tolower(cast(string) s);
<         s = replace(cast(string) s, " ", "");
< 	     string[] parts = split(cast(string) s, ":");
<         if (parts.length == 1)
<         {
<            if (parts[0].length > 2)
<            {
<               bool pm = splithop(parts[0], hour);
<               adjusthour(pm);
<            }
<            else
<               hour = to!(int)(parts[0]);
<            minute = 0;
<            second = 0;
<            ms = 0;
<         }
<         else if (parts.length == 2)
<         {
<            // Hour and minute
<            hour = to!(int)(parts[0]);
<            if (parts[1].length > 2)
<            {
<               bool pm = splitmsop(parts[1], minute);
<               adjusthour(pm);
<            }
<            else
<               minute = to!(int)(parts[1]);
<            second = 0;
<            ms = 0;
<         }
<         else if (parts.length == 3)
<         {
<            hour = to!(int)(parts[0]);
<            minute = to!(int)(parts[1]);
<            if (parts[2].length > 2)
<            {
<               splitsp(parts[2], second, ms);
<            }
<            else
<            {
<               second = to!(int)(parts[2]);
<               ms = 0;
<            }
<         }
<         else if (parts.length == 4)
<         {
<            hour = to!(int)(parts[0]);
<            minute = to!(int)(parts[1]);
<            second = to!(int)(parts[2]);
<            if (parts[3].length > 3)
<            {
<               int dp = splitmsp(parts[3], ms);
<               if (dp == 1)
<                  adjusthour(false);
<               else if (dp == 2)
<                  adjusthour(true);
<            }
<            else
<               ms = (parts[3].length > 0)? to!(int)(parts[3]): 0;
<         }
<         else
<            tmc = true;
<         if (tmc)
<            throw new Exception("Too many colons in time string.");
<         if (hour < 0 || hour > 23)
<            throw new Exception("Hour value out of range.");
<         if (minute < 0 || minute > 59)
<            throw new Exception("Minute value out of range.");
<         if (second < 0 || second > 59)
<            throw new Exception("Second value out of range.");
<         if (ms < 0 || ms > 999)
<            throw new Exception("Millisecond value out of range.");
<     }
< 
<     string T24String(bool secs = false, bool msecs = false)
<     {
<        if (msecs)
<           return format("%02d:%02d:%02d.%03d", hour, minute, second, ms);
<        else if (secs)
<           return format("%02d:%02d:%02d", hour, minute, second);
<        else
<           return format("%02d:%02d", hour, minute);
<     }
< }
< /**
283,406c49,56
<     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 yday;        /// 1..365(366)
<     int tzcorrection = int.min;	/// -1200..1200 correction in hours
< 
<     void fromDateParts(int y, int m, int d, int h, int mn, int s, int msi = 0)
<     {
<        year = y;
<        month = m;
<        day = d;
<        hour = h;
<        minute = mn;
<        second = s;
<        ms = msi;
<        weekday = DOWFromDate(year, month, day);
<        yday = YDayFromDate(year, month, day);
<     }
< 
< 
<     void fromTicks(d_time t)
<     {   
<         int y;
<         int d;
<         int m;
< 
<         if (t == d_time_nan)
<             throw new Exception("Bad d_time value");
< 
<         // Hazard a guess
<         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);
<         }
<         year = y;
< 
<         int leap = LeapYear(y);
<         d = Day(t) - DayFromYear(year);
< 
<         if (d < 59)
<         {
<             if (d < 31)
<             {
<                 assert(d >= 0);
<                 m = 0;
<             }
<             else
<             {
<                 m = 1;
<             }
<         }
<         else
<         {
<             d -= leap;
<             if (d < 212)
<             {
<                 if (d < 59)
<                     m = 1;
<                 else if (d < 90)
<                     m = 2;
<                 else if (d < 120)
<                     m = 3;
<                 else if (d < 151)
<                     m = 4;
<                 else if (d < 181)
<                     m = 5;
<                 else
<                     m = 6;
<             }
<             else
<             {
<                 if (d < 243)
<                     m = 7;
<                 else if (d < 273)
<                     m = 8;
<                 else if (d < 304)
<                     m = 9;
<                 else if (d < 334)
<                     m = 10;
<                 else if (d < 365)
<                     m = 11;
<                 else
<                     assert(0);
<             }
<         }
<         month = m+1;
<         switch (m)
<         {
<             case 0:  day = d +   1;      break;
<             case 1:  day = d -  30;      break;
<             case 2:  day = d -  58 - leap;   break;
<             case 3:  day = d -  89 - leap;   break;
<             case 4:  day = d - 119 - leap;   break;
<             case 5:  day = d - 150 - leap;   break;
<             case 6:  day = d - 180 - leap;   break;
<             case 7:  day = d - 211 - leap;   break;
<             case 8:  day = d - 242 - leap;   break;
<             case 9:  day = d - 272 - leap;   break;
<             case 10: day = d - 303 - leap;   break;
<             case 11: day = d - 333 - leap;   break;
<             default:
<                 assert(0);
<         }
<         hour = HourFromTime(t);
<         minute = MinFromTime(t);
<         second = SecFromTime(t);
<         ms = msFromTime(t);
<         weekday = WeekDay(t)+1;
<         yday = YDayFromDate(year, month, day);
<     }
---
>     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
411,419c61,63
< 	     DateParse dp;
< 	     dp.parse(s, *this);
<     }
< 
<     string toISODateString()
<     {
<        return (ms == 0)?
<          std.string.format("%d-%02d-%02d %02d:%02d:%02d", year, month, day, hour, minute, second):
<          std.string.format("%d-%02d-%02d %02d:%02d:%02d.%03d", year, month, day, hour, minute, second, ms);
---
> 	DateParse dp;
> 
> 	dp.parse(s, *this);
552,577d195
< int DOWFromDate(int year, int month, int day)
< {
<    static int[13] mdd = [ -1, 3, 28, 0, 4, 9, 6, 11, 8, 5, 10, 7, 12 ];
< 
<    int century = year/100+1;
<    int a = century*5;
<    int b = (century-1)/4;
<    int anchor = (a+b+4)%7;
< 
<    int e = (year%100)/12;
<    int f = (year%100)%12;
<    int g = f/4;
<    int dday = (e+f+g+anchor)%7;
< 
<    int mday = (month <= 2 && LeapYear(year))? mdd[month]+1: mdd[month];
<    int delta = (day - mday);
<    return 1+(dday+delta)%7;
< }
< 
< int YDayFromDate(int year, int month, int day)
< {
<    static int[13] mcum = [ -1, 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334 ];
<    int n = (month > 2 && LeapYear(year))? mcum[month]+1: mcum[month];
<    return n + day;
< }
< 
617,624c235,241
< {   
<     int y;
< 
<     if (t == d_time_nan)
<         return 0;
< 
<     // Hazard a guess
<     // y = 1970 + cast(int) (t / (365.2425 * msPerDay));
---
> {   int y;
> 
>     if (t == d_time_nan)
> 	return 0;
> 
>     // Hazard a guess
>     //y = 1970 + cast(int) (t / (365.2425 * msPerDay));
630,631c247,248
< 	     while (TimeFromYear(y + 1) <= t)
< 	         y++;
---
> 	while (TimeFromYear(y + 1) <= t)
> 	    y++;
635,638c252,256
< 	     do
< 	     {
< 	         y--;
< 	     } while (TimeFromYear(y) > t);
---
> 	do
> 	{
> 	    y--;
> 	}
> 	while (TimeFromYear(y) > t);
908d525
< 
1373,1599d989
< 
< unittest
< {
<     LocalTZA = getLocalTZA();
<     Date date;
< 
<     SYSTEMTIME st;
<     GetLocalTime(&st);
< 
<     d_time t = getUTCtime();
<     d_time loc = UTCtoLocalTime(t);
<     writefln("%d %d", t, loc);
<     date.fromTicks(loc);
< 
<     writefln(date.year);
<     writefln(date.month);
<     writefln(date.day);
<     writefln(date.hour);
<     writefln(date.minute);
<     writefln(date.second);
<     writefln(date.ms);
<     writefln(date.weekday);
<     writefln(date.yday);
<     writefln("");
< 
<     writefln(st.wYear);
<     assert(st.wYear == date.year);
<     writefln(st.wMonth);
<     assert(st.wMonth == date.month);
<     writefln(st.wDay);
<     assert(st.wDay == date.day);
<     writefln(st.wHour);
<     assert(st.wHour == date.hour);
<     writefln(st.wMinute);
<     assert(st.wMinute == date.minute);
<     writefln(st.wSecond);
<     assert(st.wSecond == date.second);
<     writefln(st.wMilliseconds);
<     writefln(st.wDayOfWeek);
<     assert(st.wDayOfWeek+1 == date.weekday);
<     writefln("");
< 
<     date.fromDateParts(2007,10,31,12,12,12,123);
< 
<     writefln(date.year);
<     assert(date.year == 2007);
<     writefln(date.month);
<     assert(date.month == 10);
<     writefln(date.day);
<     assert(date.day == 31);
<     writefln(date.hour);
<     assert(date.hour == 12);
<     writefln(date.minute);
<     assert(date.minute == 12);
<     writefln(date.second);
<     assert(date.second == 12);
<     writefln(date.ms);
<     assert(date.ms == 123);
<     writefln(date.weekday);
<     assert(date.weekday == 4);
<     writefln(date.yday);
<     assert(date.yday == 304);
< 
<     writefln("");    date.fromDateParts(2004,10,31,12,12,12,123);    // leap year
<     writefln(date.weekday);
<     assert(date.weekday == 1);
<     writefln(date.yday);
<     assert(date.yday == 305);
< 
< 
<     // Time stuff
< 
<     //   22:02
<     //   22:02:02
<     //   22:02:02:000
<     //   22:02:02.000
<     //   10:02pm
<     //   10:02:02pm
<     //   10:02:02:000pm
<     //   10:02:02.000pm
<     //   09:02
<     //   09:02am
<     //   09:02:02
<     //   9:02:02
<     //   09:02:02am
<     //   9:12
<     //   9:12am
<     //   9:12:12am
< 
<     Time ts;
<     ts.parse("22:02");
<     writefln(ts.T24String(true, true));
<     assert(ts.hour == 22 && ts.minute == 2 && ts.second == 0 && ts.ms == 0);
<     ts.parse("22:02:02");
<     writefln(ts.T24String(true, true));
<     assert(ts.hour == 22 && ts.minute == 2 && ts.second == 2 && ts.ms == 0);
<     ts.parse("22:02:02:123");
<     writefln(ts.T24String(true, true));
<     assert(ts.hour == 22 && ts.minute == 2 && ts.second == 2 && ts.ms == 123);
<     ts.parse("22:02:02:1");
<     writefln(ts.T24String(true, true));
<     assert(ts.hour == 22 && ts.minute == 2 && ts.second == 2 && ts.ms == 1);
<     ts.parse("22:02:02:12");
<     writefln(ts.T24String(true, true));
<     assert(ts.hour == 22 && ts.minute == 2 && ts.second == 2 && ts.ms == 12);
<     ts.parse("22:02:02:");
<     writefln(ts.T24String(true, true));
<     assert(ts.hour == 22 && ts.minute == 2 && ts.second == 2 && ts.ms == 0);
<     ts.parse("22:02:02.123");
<     writefln(ts.T24String(true, true));
<     assert(ts.hour == 22 && ts.minute == 2 && ts.second == 2 && ts.ms == 123);
<     ts.parse("22:02:02.1");
<     writefln(ts.T24String(true, true));
<     assert(ts.hour == 22 && ts.minute == 2 && ts.second == 2 && ts.ms == 1);
<     ts.parse("22:02:02.12");
<     writefln(ts.T24String(true, true));
<     assert(ts.hour == 22 && ts.minute == 2 && ts.second == 2 && ts.ms == 12);
<     ts.parse("22:02:02.");
<     writefln(ts.T24String(true, true));
<     assert(ts.hour == 22 && ts.minute == 2 && ts.second == 2 && ts.ms == 0);
< 
<     Time ts2;
<     ts2.fromTimeParts(ts.hour, ts.minute, ts.second, ts.ms);
<     writefln(ts2.T24String(true, true));
<     assert(ts.hour == ts2.hour && ts.minute == ts2.minute && ts.second == ts2.second && ts.ms == ts2.ms);
< 
<     ts.parse("10:02pm");
<     writefln(ts.T24String(true, true));
<     assert(ts.hour == 22 && ts.minute == 2 && ts.second == 0 && ts.ms == 0);
<     ts.parse("10:02:02pm");
<     writefln(ts.T24String(true, true));
<     assert(ts.hour == 22 && ts.minute == 2 && ts.second == 2 && ts.ms == 0);
<     ts.parse("10:02:02:123pm");
<     writefln(ts.T24String(true, true));
<     assert(ts.hour == 22 && ts.minute == 2 && ts.second == 2 && ts.ms == 123);
<     ts.parse("10:02:02.123pm");
<     writefln(ts.T24String(true, true));
<     assert(ts.hour == 22 && ts.minute == 2 && ts.second == 2 && ts.ms == 123);
<     ts.parse("10:02:02.12pm");
<     writefln(ts.T24String(true, true));
<     assert(ts.hour == 22 && ts.minute == 2 && ts.second == 2 && ts.ms == 12);
<     ts.parse("10:02:02.1pm");
<     writefln(ts.T24String(true, true));
<     assert(ts.hour == 22 && ts.minute == 2 && ts.second == 2 && ts.ms == 1);
< 
<     ts.parse("9:02am");
<     writefln(ts.T24String(true, true));
<     assert(ts.hour == 9 && ts.minute == 2 && ts.second == 0 && ts.ms == 0);
<     ts.parse("9:02:02am");
<     writefln(ts.T24String(true, true));
<     assert(ts.hour == 9 && ts.minute == 2 && ts.second == 2 && ts.ms == 0);
<     ts.parse("9:02:02:123am");
<     writefln(ts.T24String(true, true));
<     assert(ts.hour == 9 && ts.minute == 2 && ts.second == 2 && ts.ms == 123);
<     ts.parse("9:02:02.123am");
<     writefln(ts.T24String(true, true));
<     assert(ts.hour == 9 && ts.minute == 2 && ts.second == 2 && ts.ms == 123);
< 
<     ts.parse("9:02pm");
<     writefln(ts.T24String(true, true));
<     assert(ts.hour == 21 && ts.minute == 2 && ts.second == 0 && ts.ms == 0);
<     ts.parse("9:02:02pm");
<     writefln(ts.T24String(true, true));
<     assert(ts.hour == 21 && ts.minute == 2 && ts.second == 2 && ts.ms == 0);
<     ts.parse("9:02:02:123pm");
<     writefln(ts.T24String(true, true));
<     assert(ts.hour == 21 && ts.minute == 2 && ts.second == 2 && ts.ms == 123);
<     ts.parse("9:02:02.123pm");
<     writefln(ts.T24String(true, true));
<     assert(ts.hour == 21 && ts.minute == 2 && ts.second == 2 && ts.ms == 123);
< 
<     ts.parse("9am");
<     writefln(ts.T24String(true, true));
<     assert(ts.hour == 9 && ts.minute == 0 && ts.second == 0 && ts.ms == 0);
<     ts.parse("9pm");
<     writefln(ts.T24String(true, true));
<     assert(ts.hour == 21 && ts.minute == 0 && ts.second == 0 && ts.ms == 0);
<     ts.parse("10am");
<     writefln(ts.T24String(true, true));
<     assert(ts.hour == 10 && ts.minute == 0 && ts.second == 0 && ts.ms == 0);
<     ts.parse("10pm");
<     writefln(ts.T24String(true, true));
<     assert(ts.hour == 22 && ts.minute == 0 && ts.second == 0 && ts.ms == 0);
< 
<     try
<     {
<         ts.parse("123:12:12");
<     }
<     catch (Exception ex)
<     {
<         writefln(ex.toString());
<         assert(ex.toString() == "Hour value out of range.");
<     }
< 
<     try
<     {
<         ts.parse("22:12:12.12am");
<     }
<     catch (Exception ex)
<     {
<         writefln(ex.toString());
<         assert(ex.toString() == "Inconsistent hour with am.");
<     }
< 
<     try
<     {
<         ts.parse("12:12:12:12:12");
<     }
<     catch (Exception ex)
<     {
<         writefln(ex.toString());
<         assert(ex.toString() == "Too many colons in time string.");
<     }
< 
<     try
<     {
<         ts.parse("12:12:12.pm");
<     }
<     catch (Exception ex)
<     {
<         writefln(ex.toString());
<         assert(ex.toString() == "conversion pm");
<     }
< }
< 
< 
< 
