[Issue 1639] Date/Time deficiences

d-bugmail at puremagic.com d-bugmail at puremagic.com
Thu Apr 30 08:42:33 PDT 2009


http://d.puremagic.com/issues/show_bug.cgi?id=1639





------- Comment #2 from ghaecker at idworld.net  2009-04-30 10:42 -------
(From update of attachment 200)
>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");
><     }
>< }
>< 
>< 
>< 


-- 



More information about the Digitalmars-d-bugs mailing list