digitalmars.D.bugs - [Issue 1639] New: Date/Time deficiences
- d-bugmail puremagic.com (17/17) Nov 04 2007 http://d.puremagic.com/issues/show_bug.cgi?id=1639
- d-bugmail puremagic.com (6/6) Nov 04 2007 http://d.puremagic.com/issues/show_bug.cgi?id=1639
- d-bugmail puremagic.com (6/6) Nov 04 2007 http://d.puremagic.com/issues/show_bug.cgi?id=1639
- d-bugmail puremagic.com (4/684) Apr 30 2009 http://d.puremagic.com/issues/show_bug.cgi?id=1639
- d-bugmail puremagic.com (13/13) Apr 30 2009 http://d.puremagic.com/issues/show_bug.cgi?id=1639
- d-bugmail puremagic.com (19/41) Apr 30 2009 http://d.puremagic.com/issues/show_bug.cgi?id=1639
- d-bugmail puremagic.com (8/9) Apr 30 2009 http://d.puremagic.com/issues/show_bug.cgi?id=1639
- d-bugmail puremagic.com (11/11) Apr 30 2009 http://d.puremagic.com/issues/show_bug.cgi?id=1639
- d-bugmail puremagic.com (10/10) Oct 11 2009 http://d.puremagic.com/issues/show_bug.cgi?id=1639
http://d.puremagic.com/issues/show_bug.cgi?id=1639 Summary: Date/Time deficiences Product: D Version: unspecified Platform: PC OS/Version: Windows Status: NEW Severity: normal Priority: P2 Component: Phobos AssignedTo: braddr puremagic.com ReportedBy: steve.teale britseyeview.com The Date struct is lacking a day-of-year (Julian day) field. Date instances can only be instantiated by parsing a string. Should be possible to instantiate from clock ticks and explicit date part values. There needs to be a corresponding Time struct for example for use with ODBC. --
Nov 04 2007
http://d.puremagic.com/issues/show_bug.cgi?id=1639 Created an attachment (id=200) --> (http://d.puremagic.com/issues/attachment.cgi?id=200&action=view) Proposed modifications --
Nov 04 2007
http://d.puremagic.com/issues/show_bug.cgi?id=1639 matti.niemenmaa+dbugzilla iki.fi changed: What |Removed |Added ---------------------------------------------------------------------------- Severity|normal |enhancement --
Nov 04 2007
http://d.puremagic.com/issues/show_bug.cgi?id=1639 (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 hours411,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"); < } < } < < <
Apr 30 2009
http://d.puremagic.com/issues/show_bug.cgi?id=1639 In struct Time method fromTicks, function calls HourFromTime MinFromTime SecFromTime need to changed to hourFromTime minFromTime secFromTime respectively. --
Apr 30 2009
http://d.puremagic.com/issues/show_bug.cgi?id=1639 smjg iname.com changed: What |Removed |Added ---------------------------------------------------------------------------- CC| |smjg iname.comThe Date struct is lacking a day-of-year (Julian day) field. Date instances can only be instantiated by parsing a string. Should be possible to instantiate from clock ticks and explicit date part values.The latter is possible. http://www.digitalmars.com/d/1.0/struct.html#StructLiteral Whether it checks the struct for validity or auto-fills weekday/yday is another matter....< if (s < 0 || s > 59) < throw new Exception("Second value out of range.");This'll prevent storing a leap second time....There needs to be a corresponding Time struct for example for use with ODBC.<snip 665 more lines> What was the purpose of copying this long block of code here? But std.date could certainly do with improvements. BTW check out this alternative: http://pr.stewartsplace.org.uk/d/sutil/ --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
Apr 30 2009
http://d.puremagic.com/issues/show_bug.cgi?id=1639What was the purpose of copying this long block of code here?Sorry about that. I'm new to bugzilla. That long block of code resulted from my using the "Edit as Comment" feature on the proposed code attachment to this issue. If I had known that would be the result I would not have done it. --
Apr 30 2009
http://d.puremagic.com/issues/show_bug.cgi?id=1639 braddr puremagic.com changed: What |Removed |Added ---------------------------------------------------------------------------- AssignedTo|braddr puremagic.com |bugzilla digitalmars.com Not sure why this is assigned to me. Re-assigning it back to the default owner. One brief comment, unit tests shouldn't ever have that much output to them. No output other than assertion failures. --
Apr 30 2009
http://d.puremagic.com/issues/show_bug.cgi?id=1639 Andrei Alexandrescu <andrei metalanguage.com> changed: What |Removed |Added ---------------------------------------------------------------------------- Status|NEW |ASSIGNED CC| |andrei metalanguage.com AssignedTo|nobody puremagic.com |andrei metalanguage.com -- Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email ------- You are receiving this mail because: -------
Oct 11 2009