X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/f6bcfd974ef26faf6f91a62cac09827e09463fd1..77d4384e31b10791b3b074b9874c73f5df004556:/src/common/datetime.cpp diff --git a/src/common/datetime.cpp b/src/common/datetime.cpp index c0afcdaab2..6dab762700 100644 --- a/src/common/datetime.cpp +++ b/src/common/datetime.cpp @@ -106,6 +106,19 @@ #endif #endif // !WX_TIMEZONE +// ---------------------------------------------------------------------------- +// macros +// ---------------------------------------------------------------------------- + +// debugging helper: just a convenient replacement of wxCHECK() +#define wxDATETIME_CHECK(expr, msg) \ + if ( !(expr) ) \ + { \ + wxFAIL_MSG(msg); \ + *this = wxInvalidDateTime; \ + return *this; \ + } + // ---------------------------------------------------------------------------- // private classes // ---------------------------------------------------------------------------- @@ -173,9 +186,11 @@ static const wxDateTime::wxDateTime_t gs_cumulatedDays[2][MONTHS_IN_YEAR] = // global data // ---------------------------------------------------------------------------- -static wxDateTime gs_dtDefault; +// in the fine tradition of ANSI C we use our equivalent of (time_t)-1 to +// indicate an invalid wxDateTime object +static const wxDateTime gs_dtDefault = wxLongLong((long)ULONG_MAX, ULONG_MAX); -wxDateTime& wxDefaultDateTime = gs_dtDefault; +const wxDateTime& wxDefaultDateTime = gs_dtDefault; wxDateTime::Country wxDateTime::ms_country = wxDateTime::Country_Unknown; @@ -232,9 +247,9 @@ static int GetTimeZone() { // 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; } @@ -1071,7 +1086,9 @@ wxDateTime& wxDateTime::Set(const struct tm& tm) wxFAIL_MSG( _T("mktime() failed") ); - return wxInvalidDateTime; + *this = wxInvalidDateTime; + + return *this; } else { @@ -1088,14 +1105,16 @@ wxDateTime& wxDateTime::Set(wxDateTime_t hour, // we allow seconds to be 61 to account for the leap seconds, even if we // don't use them really - wxCHECK_MSG( hour < 24 && second < 62 && minute < 60 && millisec < 1000, - wxInvalidDateTime, - _T("Invalid time in wxDateTime::Set()") ); + wxDATETIME_CHECK( hour < 24 && + second < 62 && + minute < 60 && + millisec < 1000, + _T("Invalid time in wxDateTime::Set()") ); // get the current date from system struct tm *tm = GetTmNow(); - wxCHECK_MSG( tm, wxInvalidDateTime, _T("localtime() failed") ); + wxDATETIME_CHECK( tm, _T("localtime() failed") ); // adjust the time tm->tm_hour = hour; @@ -1118,15 +1137,16 @@ wxDateTime& wxDateTime::Set(wxDateTime_t day, { wxASSERT_MSG( IsValid(), _T("invalid wxDateTime") ); - wxCHECK_MSG( hour < 24 && second < 62 && minute < 60 && millisec < 1000, - wxInvalidDateTime, - _T("Invalid time in wxDateTime::Set()") ); + wxDATETIME_CHECK( hour < 24 && + second < 62 && + minute < 60 && + millisec < 1000, + _T("Invalid time in wxDateTime::Set()") ); ReplaceDefaultYearMonthWithCurrent(&year, &month); - wxCHECK_MSG( (0 < day) && (day <= GetNumberOfDays(month, year)), - wxInvalidDateTime, - _T("Invalid date in wxDateTime::Set()") ); + wxDATETIME_CHECK( (0 < day) && (day <= GetNumberOfDays(month, year)), + _T("Invalid date in wxDateTime::Set()") ); // the range of time_t type (inclusive) static const int yearMinInRange = 1970; @@ -1479,7 +1499,7 @@ wxDateTime& wxDateTime::SetToLastMonthDay(Month month, wxDateTime& wxDateTime::SetToWeekDayInSameWeek(WeekDay weekday) { - wxCHECK_MSG( weekday != Inv_WeekDay, wxInvalidDateTime, _T("invalid weekday") ); + wxDATETIME_CHECK( weekday != Inv_WeekDay, _T("invalid weekday") ); WeekDay wdayThis = GetWeekDay(); if ( weekday == wdayThis ) @@ -1499,7 +1519,7 @@ wxDateTime& wxDateTime::SetToWeekDayInSameWeek(WeekDay weekday) wxDateTime& wxDateTime::SetToNextWeekDay(WeekDay weekday) { - wxCHECK_MSG( weekday != Inv_WeekDay, wxInvalidDateTime, _T("invalid weekday") ); + wxDATETIME_CHECK( weekday != Inv_WeekDay, _T("invalid weekday") ); int diff; WeekDay wdayThis = GetWeekDay(); @@ -1523,7 +1543,7 @@ wxDateTime& wxDateTime::SetToNextWeekDay(WeekDay weekday) wxDateTime& wxDateTime::SetToPrevWeekDay(WeekDay weekday) { - wxCHECK_MSG( weekday != Inv_WeekDay, wxInvalidDateTime, _T("invalid weekday") ); + wxDATETIME_CHECK( weekday != Inv_WeekDay, _T("invalid weekday") ); int diff; WeekDay wdayThis = GetWeekDay(); @@ -1671,8 +1691,8 @@ wxDateTime::wxDateTime_t wxDateTime::GetWeekOfMonth(wxDateTime::WeekFlags flags, wxDateTime& wxDateTime::SetToYearDay(wxDateTime::wxDateTime_t yday) { int year = GetYear(); - wxCHECK_MSG( (0 < yday) && (yday <= GetNumberOfDays(year)), - wxInvalidDateTime, _T("invalid year day") ); + wxDATETIME_CHECK( (0 < yday) && (yday <= GetNumberOfDays(year)), + _T("invalid year day") ); bool isLeap = IsLeapYear(year); for ( Month mon = Jan; mon < Inv_Month; wxNextMonth(mon) ) @@ -3044,6 +3064,11 @@ const wxChar *wxDateTime::ParseDate(const wxChar *date) } } + // We try to guess what we have here: for each new (numeric) token, we + // determine if it can be a month, day or a year. Of course, there is an + // ambiguity as some numbers may be days as well as months, so we also + // have the ability to back track. + // what do we have? bool haveDay = FALSE, // the months day? haveWDay = FALSE, // the day of week? @@ -3063,6 +3088,8 @@ const wxChar *wxDateTime::ParseDate(const wxChar *date) while ( tok.HasMoreTokens() ) { wxString token = tok.GetNextToken(); + if ( !token ) + continue; // is it a number? unsigned long val; @@ -3072,110 +3099,53 @@ const wxChar *wxDateTime::ParseDate(const wxChar *date) bool isDay = FALSE, isMonth = FALSE, - // only years are counted from 0 - isYear = (val == 0) || (val > 31); - if ( !isYear ) + isYear = FALSE; + + if ( !haveMon && val > 0 && val <= 12 ) { - // may be the month or month day or the year, assume the - // month day by default and fallback to month if the range - // allow it or to the year if our assumption doesn't work - if ( haveDay ) + // assume it is month + isMonth = TRUE; + } + else // not the month + { + wxDateTime_t maxDays = haveMon + ? GetNumOfDaysInMonth(haveYear ? year : Inv_Year, mon) + : 31; + + // can it be day? + if ( (val == 0) || (val > maxDays) ) { - // we already have the day, so may only be a month or year - if ( val > 12 ) - { - isYear = TRUE; - } - else - { - isMonth = TRUE; - } + isYear = TRUE; } - else // it may be day + else { isDay = TRUE; - - // check the range - if ( haveMon ) - { - if ( val > GetNumOfDaysInMonth(haveYear ? year - : Inv_Year, - mon) ) - { - // oops, it can't be a day finally - isDay = FALSE; - - if ( val > 12 ) - { - isYear = TRUE; - } - else - { - isMonth = TRUE; - } - } - } } } - // remember that we have this and stop the scan if it's the second - // time we find this, except for the day logic (see there) if ( isYear ) { if ( haveYear ) - { break; - } haveYear = TRUE; - // no roll over - 99 means 99, not 1999 for us year = (wxDateTime_t)val; } - else if ( isMonth ) + else if ( isDay ) { - if ( haveMon ) - { + if ( haveDay ) break; - } - haveMon = TRUE; + haveDay = TRUE; - // month 1 is Jan - mon = (wxDateTime::Month)(val - 1); + day = (wxDateTime_t)val; } - else + else if ( isMonth ) { - wxASSERT_MSG( isDay, _T("logic error") ); - - if ( haveDay ) - { - // may be were mistaken when we found it for the first - // time? may be it was a month or year instead? - // - // this ability to "backtrack" allows us to correctly parse - // both things like 01/13 and 13/01 - but, of course, we - // still can't resolve the ambiguity in 01/02 (it will be - // Feb 1 for us, not Jan 2 as americans might expect!) - if ( (day <= 12) && !haveMon ) - { - // exchange day and month - mon = (wxDateTime::Month)(day - 1); - - haveMon = TRUE; - } - else if ( !haveYear ) - { - // exchange day and year - year = day; - - haveYear = TRUE; - } - } - - haveDay = TRUE; + haveMon = TRUE; - day = (wxDateTime_t)val; + mon = (Month)(val - 1); } } else // not a number @@ -3187,14 +3157,27 @@ const wxChar *wxDateTime::ParseDate(const wxChar *date) // 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 ) @@ -3207,7 +3190,7 @@ const wxChar *wxDateTime::ParseDate(const wxChar *date) haveWDay = TRUE; } - else + else // not a valid weekday name { // try the ordinals static const wxChar *ordinals[] = @@ -3233,7 +3216,7 @@ const wxChar *wxDateTime::ParseDate(const wxChar *date) 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;