// some trivial ones
static const int MONTHS_IN_YEAR = 12;
-static const int SECONDS_IN_MINUTE = 60;
+static const int SEC_PER_MIN = 60;
+
+static const int MIN_PER_HOUR = 60;
+
+static const int HOURS_PER_DAY = 24;
static const long SECONDS_PER_DAY = 86400l;
+static const int DAYS_PER_WEEK = 7;
+
static const long MILLISECONDS_PER_DAY = 86400000l;
// this is the integral part of JDN of the midnight of Jan 1, 1970
// in the fine tradition of ANSI C we use our equivalent of (time_t)-1 to
// indicate an invalid wxDateTime object
+#ifdef __WIN16__
+static const wxDateTime gs_dtDefault;
+#else
static const wxDateTime gs_dtDefault = wxLongLong((long)ULONG_MAX, ULONG_MAX);
+#endif
const wxDateTime& wxDefaultDateTime = gs_dtDefault;
{
// just call localtime() instead of figuring out whether this system
// supports tzset(), _tzset() or something else
- time_t t;
- (void)localtime(&t);
+ time_t t = 0;
+ (void)localtime(&t);
s_timezoneSet = TRUE;
}
else
{
time += (time_t)tz.GetOffset();
-#ifdef __VMS__ // time is unsigned so avoid warning
+#if defined(__VMS__) || defined(__WATCOMC__) // time is unsigned so avoid warning
int time2 = (int) time;
if ( time2 >= 0 )
#else
{
time += (int)tz.GetOffset();
-#ifdef __VMS__ // time is unsigned so avoid the warning
+#if defined(__VMS__) || defined(__WATCOMC__) // time is unsigned so avoid warning
int time2 = (int) time;
if ( time2 >= 0 )
#else
: 31;
// can it be day?
- if ( (val == 0) || (val > maxDays) )
+ if ( (val == 0) || (val > (unsigned long)maxDays) ) // cast to shut up compiler warning in BCC
{
isYear = TRUE;
}
// it's a month
if ( haveMon )
{
- break;
+ // but we already have a month - maybe we guessed wrong?
+ if ( !haveDay )
+ {
+ // no need to check in month range as always < 12, but
+ // the days are counted from 1 unlike the months
+ day = (wxDateTime_t)mon + 1;
+ haveDay = TRUE;
+ }
+ else
+ {
+ // could possible be the year (doesn't the year come
+ // before the month in the japanese format?) (FIXME)
+ break;
+ }
}
mon = mon2;
haveMon = TRUE;
}
- else
+ else // not a valid month name
{
wday = GetWeekDayFromName(token, Name_Full | Name_Abbr);
if ( wday != Inv_WeekDay )
haveWDay = TRUE;
}
- else
+ else // not a valid weekday name
{
// try the ordinals
static const wxChar *ordinals[] =
wxTRANSLATE("nineteenth"),
wxTRANSLATE("twentieth"),
// that's enough - otherwise we'd have problems with
- // composite (or not) ordinals otherwise
+ // composite (or not) ordinals
};
size_t n;
haveDay = TRUE;
- day = n + 1;
+ day = (wxDateTime_t)(n + 1);
}
}
}
mon = (wxDateTime::Month)(day - 1);
// we're in the current year then
- if ( year <= GetNumOfDaysInMonth(Inv_Year, mon) )
+ if ( (year > 0) &&
+ (unsigned)year <= GetNumOfDaysInMonth(Inv_Year, mon) )
{
day = year;
wxString str;
str.Alloc(wxStrlen(format));
+ // Suppose we have wxTimeSpan ts(1 /* hour */, 2 /* min */, 3 /* sec */)
+ //
+ // Then, of course, ts.Format("%H:%M:%S") must return "01:02:03", but the
+ // question is what should ts.Format("%S") do? The code here returns "3273"
+ // in this case (i.e. the total number of seconds, not just seconds % 60)
+ // because, for me, this call means "give me entire time interval in
+ // seconds" and not "give me the seconds part of the time interval"
+ //
+ // If we agree that it should behave like this, it is clear that the
+ // interpretation of each format specifier depends on the presence of the
+ // other format specs in the string: if there was "%H" before "%M", we
+ // should use GetMinutes() % 60, otherwise just GetMinutes() &c
+
+ // we remember the most important unit found so far
+ enum TimeSpanPart
+ {
+ Part_Week,
+ Part_Day,
+ Part_Hour,
+ Part_Min,
+ Part_Sec,
+ Part_MSec
+ } partBiggest = Part_MSec;
+
for ( const wxChar *pch = format; *pch; pch++ )
{
wxChar ch = *pch;
if ( ch == _T('%') )
{
- wxString tmp;
+ // the start of the format specification of the printf() below
+ wxString fmtPrefix = _T('%');
+
+ // the number
+ long n;
ch = *++pch; // get the format spec char
switch ( ch )
// fall through
case _T('%'):
- // will get to str << ch below
- break;
+ str += ch;
+
+ // skip the part below switch
+ continue;
case _T('D'):
- tmp.Printf(_T("%d"), GetDays());
+ n = GetDays();
+ if ( partBiggest < Part_Day )
+ {
+ n %= DAYS_PER_WEEK;
+ }
+ else
+ {
+ partBiggest = Part_Day;
+ }
break;
case _T('E'):
- tmp.Printf(_T("%d"), GetWeeks());
+ partBiggest = Part_Week;
+ n = GetWeeks();
break;
case _T('H'):
- tmp.Printf(_T("%02d"), GetHours());
+ n = GetHours();
+ if ( partBiggest < Part_Hour )
+ {
+ n %= HOURS_PER_DAY;
+ }
+ else
+ {
+ partBiggest = Part_Hour;
+ }
+
+ fmtPrefix += _T("02");
break;
case _T('l'):
- tmp.Printf(_T("%03ld"), GetMilliseconds().ToLong());
+ n = GetMilliseconds().ToLong();
+ if ( partBiggest < Part_MSec )
+ {
+ n %= 1000;
+ }
+ //else: no need to reset partBiggest to Part_MSec, it is
+ // the least significant one anyhow
+
+ fmtPrefix += _T("03");
break;
case _T('M'):
- tmp.Printf(_T("%02d"), GetMinutes());
+ n = GetMinutes();
+ if ( partBiggest < Part_Min )
+ {
+ n %= MIN_PER_HOUR;
+ }
+ else
+ {
+ partBiggest = Part_Min;
+ }
+
+ fmtPrefix += _T("02");
break;
case _T('S'):
- tmp.Printf(_T("%02ld"), GetSeconds().ToLong());
+ n = GetSeconds().ToLong();
+ if ( partBiggest < Part_Sec )
+ {
+ n %= SEC_PER_MIN;
+ }
+ else
+ {
+ partBiggest = Part_Sec;
+ }
+
+ fmtPrefix += _T("02");
break;
}
- if ( !!tmp )
- {
- str += tmp;
-
- // skip str += ch below
- continue;
- }
+ str += wxString::Format(fmtPrefix + _T("ld"), n);
+ }
+ else
+ {
+ // normal character, just copy
+ str += ch;
}
-
- str += ch;
}
return str;