X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/cb73e6001f891ae46b12a1e4ca39b93649cb6099..0281278534339322516fa6133ed4df925c2156be:/src/common/datetime.cpp diff --git a/src/common/datetime.cpp b/src/common/datetime.cpp index 7e0815799c..9a2476991c 100644 --- a/src/common/datetime.cpp +++ b/src/common/datetime.cpp @@ -94,7 +94,7 @@ template<> void wxStringWriteValue(wxString &s , const wxDateTime &data ) s = data.Format(wxT("%Y-%m-%d %H:%M:%S")) ; } -WX_CUSTOM_TYPE_INFO(wxDateTime) +wxCUSTOM_TYPE_INFO(wxDateTime, wxToStringConverter , wxFromStringConverter) #endif @@ -171,7 +171,7 @@ public: { wxDateTimeHolidayAuthority::AddAuthority(new wxDateTimeWorkDays); - return TRUE; + return true; } virtual void OnExit() @@ -233,6 +233,9 @@ static const wxDateTime::wxDateTime_t gs_cumulatedDays[2][MONTHS_IN_YEAR] = // global data // ---------------------------------------------------------------------------- +const wxChar * wxDefaultDateTimeFormat = wxT("%c"); +const wxChar * wxDefaultTimeSpanFormat = wxT("%H:%M:%S"); + // in the fine tradition of ANSI C we use our equivalent of (time_t)-1 to // indicate an invalid wxDateTime object const wxDateTime wxDefaultDateTime; @@ -275,8 +278,8 @@ wxDateTime::wxDateTime_t GetNumOfDaysInMonth(int year, wxDateTime::Month month) static int GetTimeZone() { #ifdef WX_GMTOFF_IN_TM - // set to TRUE when the timezone is set - static bool s_timezoneSet = FALSE; + // set to true when the timezone is set + static bool s_timezoneSet = false; static long gmtoffset = LONG_MAX; // invalid timezone // ensure that the timezone variable is set by calling localtime @@ -288,7 +291,7 @@ static int GetTimeZone() struct tm *tm; tm = localtime(&t); - s_timezoneSet = TRUE; + s_timezoneSet = true; // note that GMT offset is the opposite of time zone and so to return // consistent results in both WX_GMTOFF_IN_TM and !WX_GMTOFF_IN_TM @@ -500,7 +503,7 @@ static bool GetNumericToken(size_t len, const wxChar*& p, unsigned long *number) break; } - return !!s && s.ToULong(number); + return !s.empty() && s.ToULong(number); } // scans all alphabetic characters and returns the resulting string @@ -536,14 +539,14 @@ wxDateTime::Tm::Tm(const struct tm& tm, const TimeZone& tz) : m_tz(tz) { msec = 0; - sec = tm.tm_sec; - min = tm.tm_min; - hour = tm.tm_hour; - mday = tm.tm_mday; + sec = (wxDateTime::wxDateTime_t)tm.tm_sec; + min = (wxDateTime::wxDateTime_t)tm.tm_min; + hour = (wxDateTime::wxDateTime_t)tm.tm_hour; + mday = (wxDateTime::wxDateTime_t)tm.tm_mday; mon = (wxDateTime::Month)tm.tm_mon; year = 1900 + tm.tm_year; - wday = tm.tm_wday; - yday = tm.tm_yday; + wday = (wxDateTime::wxDateTime_t)tm.tm_wday; + yday = (wxDateTime::wxDateTime_t)tm.tm_yday; } bool wxDateTime::Tm::IsValid() const @@ -559,7 +562,7 @@ void wxDateTime::Tm::ComputeWeekDay() // compute the week day from day/month/year: we use the dumbest algorithm // possible: just compute our JDN and then use the (simple to derive) // formula: weekday = (JDN + 1.5) % 7 - wday = (wxDateTime::WeekDay)(GetTruncatedJDN(mday, mon, year) + 2) % 7; + wday = (wxDateTime::wxDateTime_t)((wxDateTime::WeekDay)(GetTruncatedJDN(mday, mon, year) + 2) % 7); } void wxDateTime::Tm::AddMonths(int monDiff) @@ -597,7 +600,7 @@ void wxDateTime::Tm::AddDays(int dayDiff) dayDiff += GetNumOfDaysInMonth(year, mon); } - mday += dayDiff; + mday = (wxDateTime::wxDateTime_t)( mday + dayDiff ); while ( mday > GetNumOfDaysInMonth(year, mon) ) { mday -= GetNumOfDaysInMonth(year, mon); @@ -691,7 +694,7 @@ bool wxDateTime::IsLeapYear(int year, wxDateTime::Calendar cal) { wxFAIL_MSG(_T("unknown calendar")); - return FALSE; + return false; } } @@ -817,10 +820,12 @@ wxString wxDateTime::GetWeekDayName(wxDateTime::WeekDay wday, { wxCHECK_MSG( wday != Inv_WeekDay, _T(""), _T("invalid weekday") ); - // take some arbitrary Sunday + // take some arbitrary Sunday (but notice that the day should be such that + // after adding wday to it below we still have a valid date, e.g. don't + // take 28 here!) tm tm; InitTm(tm); - tm.tm_mday = 28; + tm.tm_mday = 21; tm.tm_mon = Nov; tm.tm_year = 99; @@ -839,14 +844,29 @@ void wxDateTime::GetAmPmStrings(wxString *am, wxString *pm) { tm tm; InitTm(tm); + wxChar buffer[64]; + // @Note: Do not call 'CallStrftime' here! CallStrftime checks the return code + // and causes an assertion failed if the buffer is to small (which is good) - OR - + // if strftime does not return anything because the format string is invalid - OR - + // if there are no 'am' / 'pm' tokens defined for the current locale (which is not good). + // wxDateTime::ParseTime will try several different formats to parse the time. + // As a result, GetAmPmStrings might get called, even if the current locale + // does not define any 'am' / 'pm' tokens. In this case, wxStrftime would + // assert, even though it is a perfectly legal use. if ( am ) { - *am = CallStrftime(_T("%p"), &tm); + if (wxStrftime(buffer, sizeof buffer, _T("%p"), &tm) > 0) + *am = wxString(buffer); + else + *am = wxString(); } if ( pm ) { tm.tm_hour = 13; - *pm = CallStrftime(_T("%p"), &tm); + if (wxStrftime(buffer, sizeof buffer, _T("%p"), &tm) > 0) + *pm = wxString(buffer); + else + *pm = wxString(); } } @@ -985,7 +1005,7 @@ wxDateTime wxDateTime::GetBeginDST(int year, Country country) dt += wxTimeSpan::Hours(1); // disable DST tests because it could result in an infinite recursion! - dt.MakeGMT(TRUE); + dt.MakeGMT(true); } else switch ( country ) { @@ -1086,7 +1106,7 @@ wxDateTime wxDateTime::GetEndDST(int year, Country country) dt += wxTimeSpan::Hours(1); // disable DST tests because it could result in an infinite recursion! - dt.MakeGMT(TRUE); + dt.MakeGMT(true); } else switch ( country ) { @@ -1151,16 +1171,11 @@ wxDateTime& wxDateTime::Set(const struct tm& tm) // less than timezone - try to make it work for this case if ( tm2.tm_year == 70 && tm2.tm_mon == 0 && tm2.tm_mday == 1 ) { - // add timezone to make sure that date is in range - tm2.tm_sec -= GetTimeZone(); - - timet = mktime(&tm2); - if ( timet != (time_t)-1 ) - { - timet += GetTimeZone(); - - return Set(timet); - } + return Set((time_t)( + GetTimeZone() + + tm2.tm_hour * MIN_PER_HOUR * SEC_PER_MIN + + tm2.tm_min * SEC_PER_MIN + + tm2.tm_sec)); } wxFAIL_MSG( _T("mktime() failed") ); @@ -1245,7 +1260,10 @@ wxDateTime& wxDateTime::Set(wxDateTime_t day, (void)Set(tm); // and finally adjust milliseconds - return SetMillisecond(millisec); + if (IsValid()) + SetMillisecond(millisec); + + return *this; } else { @@ -1272,6 +1290,17 @@ wxDateTime& wxDateTime::Set(double jdn) jdn *= MILLISECONDS_PER_DAY; + // JDNs always suppose an UTC date, so bring it back to local time zone + // (also see GetJulianDayNumber() implementation) + long tzDiff = GetTimeZone(); + if ( IsDST() == 1 ) + { + // FIXME: again, we suppose that DST is always one hour + tzDiff -= 3600; + } + + jdn += tzDiff*1000; // tzDiff is in seconds + m_time.Assign(jdn); return *this; @@ -1311,6 +1340,7 @@ wxDateTime& wxDateTime::ResetTime() wxDateTime& wxDateTime::SetFromDOS(unsigned long ddt) { struct tm tm; + InitTm(tm); long year = ddt & 0xFE000000; year >>= 25; @@ -1617,26 +1647,63 @@ wxDateTime& wxDateTime::Add(const wxDateSpan& diff) // Weekday and monthday stuff // ---------------------------------------------------------------------------- -bool wxDateTime::SetToTheWeek(wxDateTime_t numWeek, - WeekDay weekday, - WeekFlags flags) +// convert Sun, Mon, ..., Sat into 6, 0, ..., 5 +static inline int ConvertWeekDayToMondayBase(int wd) +{ + return wd == wxDateTime::Sun ? 6 : wd - 1; +} + +/* static */ +wxDateTime +wxDateTime::SetToWeekOfYear(int year, wxDateTime_t numWeek, WeekDay wd) { wxASSERT_MSG( numWeek > 0, _T("invalid week number: weeks are counted from 1") ); - int year = GetYear(); + // Jan 4 always lies in the 1st week of the year + wxDateTime dt(4, Jan, year); + dt.SetToWeekDayInSameWeek(wd); + dt += wxDateSpan::Weeks(numWeek - 1); + + return dt; +} +// use a separate function to avoid warnings about using deprecated +// SetToTheWeek in GetWeek below +static wxDateTime +SetToTheWeek(int year, + wxDateTime::wxDateTime_t numWeek, + wxDateTime::WeekDay weekday, + wxDateTime::WeekFlags flags) +{ // Jan 4 always lies in the 1st week of the year - Set(4, Jan, year); - SetToWeekDayInSameWeek(weekday, flags) += wxDateSpan::Weeks(numWeek - 1); + wxDateTime dt(4, wxDateTime::Jan, year); + dt.SetToWeekDayInSameWeek(weekday, flags); + dt += wxDateSpan::Weeks(numWeek - 1); + return dt; +} + +bool wxDateTime::SetToTheWeek(wxDateTime_t numWeek, + WeekDay weekday, + WeekFlags flags) +{ + int year = GetYear(); + *this = ::SetToTheWeek(year, numWeek, weekday, flags); if ( GetYear() != year ) { // oops... numWeek was too big - return FALSE; + return false; } - return TRUE; + return true; +} + +wxDateTime wxDateTime::GetWeek(wxDateTime_t numWeek, + WeekDay weekday, + WeekFlags flags) const +{ + return ::SetToTheWeek(GetYear(), numWeek, weekday, flags); } wxDateTime& wxDateTime::SetToLastMonthDay(Month month, @@ -1741,9 +1808,9 @@ bool wxDateTime::SetToWeekDay(WeekDay weekday, Month month, int year) { - wxCHECK_MSG( weekday != Inv_WeekDay, FALSE, _T("invalid weekday") ); + wxCHECK_MSG( weekday != Inv_WeekDay, false, _T("invalid weekday") ); - // we don't check explicitly that -5 <= n <= 5 because we will return FALSE + // we don't check explicitly that -5 <= n <= 5 because we will return false // anyhow in such case - but may be should still give an assert for it? // take the current month/year if none specified @@ -1795,52 +1862,87 @@ bool wxDateTime::SetToWeekDay(WeekDay weekday, { *this = dt; - return TRUE; + return true; } else { // no such day in this month - return FALSE; + return false; } } -wxDateTime::wxDateTime_t wxDateTime::GetDayOfYear(const TimeZone& tz) const +static inline +wxDateTime::wxDateTime_t GetDayOfYearFromTm(const wxDateTime::Tm& tm) { - Tm tm(GetTm(tz)); + return (wxDateTime::wxDateTime_t)(gs_cumulatedDays[wxDateTime::IsLeapYear(tm.year)][tm.mon] + tm.mday); +} - return gs_cumulatedDays[IsLeapYear(tm.year)][tm.mon] + tm.mday; +wxDateTime::wxDateTime_t wxDateTime::GetDayOfYear(const TimeZone& tz) const +{ + return GetDayOfYearFromTm(GetTm(tz)); } -wxDateTime::wxDateTime_t wxDateTime::GetWeekOfYear(wxDateTime::WeekFlags flags, - const TimeZone& tz) const +wxDateTime::wxDateTime_t +wxDateTime::GetWeekOfYear(wxDateTime::WeekFlags flags, const TimeZone& tz) const { if ( flags == Default_First ) { flags = GetCountry() == USA ? Sunday_First : Monday_First; } - wxDateTime_t nDayInYear = GetDayOfYear(tz); - wxDateTime_t week; + Tm tm(GetTm(tz)); + wxDateTime_t nDayInYear = GetDayOfYearFromTm(tm); - WeekDay wd = GetWeekDay(tz); + int wdTarget = GetWeekDay(tz); + int wdYearStart = wxDateTime(1, Jan, GetYear()).GetWeekDay(); + int week; if ( flags == Sunday_First ) { - week = (nDayInYear - wd + 7) / 7; + // FIXME: First week is not calculated correctly. + week = (nDayInYear - wdTarget + 7) / 7; + if ( wdYearStart == Wed || wdYearStart == Thu ) + week++; } - else + else // week starts with monday { - // have to shift the week days values - week = (nDayInYear - (wd - 1 + 7) % 7 + 7) / 7; - } + // adjust the weekdays to non-US style. + wdYearStart = ConvertWeekDayToMondayBase(wdYearStart); + wdTarget = ConvertWeekDayToMondayBase(wdTarget); - // FIXME some more elegant way?? - WeekDay wdYearStart = wxDateTime(1, Jan, GetYear()).GetWeekDay(); - if ( wdYearStart == Wed || wdYearStart == Thu ) - { - week++; + // quoting from http://www.cl.cam.ac.uk/~mgk25/iso-time.html: + // + // Week 01 of a year is per definition the first week that has the + // Thursday in this year, which is equivalent to the week that + // contains the fourth day of January. In other words, the first + // week of a new year is the week that has the majority of its + // days in the new year. Week 01 might also contain days from the + // previous year and the week before week 01 of a year is the last + // week (52 or 53) of the previous year even if it contains days + // from the new year. A week starts with Monday (day 1) and ends + // with Sunday (day 7). + // + + // if Jan 1 is Thursday or less, it is in the first week of this year + if ( wdYearStart < 4 ) + { + // count the number of entire weeks between Jan 1 and this date + week = (nDayInYear + wdYearStart + 6 - wdTarget)/7; + + // be careful to check for overflow in the next year + if ( week == 53 && tm.mday - wdTarget > 28 ) + week = 1; + } + else // Jan 1 is in the last week of the previous year + { + // check if we happen to be at the last week of previous year: + if ( tm.mon == Jan && tm.mday < 8 - wdYearStart ) + week = wxDateTime(31, Dec, GetYear()-1).GetWeekOfYear(); + else + week = (nDayInYear + wdYearStart - 1 - wdTarget)/7; + } } - return week; + return (wxDateTime::wxDateTime_t)week; } wxDateTime::wxDateTime_t wxDateTime::GetWeekOfMonth(wxDateTime::WeekFlags flags, @@ -1871,9 +1973,9 @@ wxDateTime& wxDateTime::SetToYearDay(wxDateTime::wxDateTime_t yday) // for Dec, we can't compare with gs_cumulatedDays[mon + 1], but we // don't need it neither - because of the CHECK above we know that // yday lies in December then - if ( (mon == Dec) || (yday < gs_cumulatedDays[isLeap][mon + 1]) ) + if ( (mon == Dec) || (yday <= gs_cumulatedDays[isLeap][mon + 1]) ) { - Set(yday - gs_cumulatedDays[isLeap][mon], mon, year); + Set((wxDateTime::wxDateTime_t)(yday - gs_cumulatedDays[isLeap][mon]), mon, year); break; } @@ -1888,8 +1990,8 @@ wxDateTime& wxDateTime::SetToYearDay(wxDateTime::wxDateTime_t yday) double wxDateTime::GetJulianDayNumber() const { - // JDN are always expressed for the GMT dates - Tm tm(ToTimezone(GMT0).GetTm(GMT0)); + // JDN are always expressed for the UTC dates + Tm tm(ToTimezone(UTC).GetTm(UTC)); double result = GetTruncatedJDN(tm.mday, tm.mon, tm.year); @@ -2058,17 +2160,17 @@ wxString wxDateTime::Format(const wxChar *format, const TimeZone& tz) const fmt = _T("%02d"); } - bool restart = TRUE; + bool restart = true; while ( restart ) { - restart = FALSE; + restart = false; // start of the format specification switch ( *p ) { case _T('a'): // a weekday name case _T('A'): - // second parameter should be TRUE for abbreviated names + // second parameter should be true for abbreviated names res += GetWeekDayName(tm.GetWeekDay(), *p == _T('a') ? Name_Abbr : Name_Full); break; @@ -2293,13 +2395,13 @@ wxString wxDateTime::Format(const wxChar *format, const TimeZone& tz) const fmt += *p; } - if ( !fmt.IsEmpty() ) + if ( !fmt.empty() ) { // we've only got the flags and width so far in fmt fmt.Prepend(_T('%')); fmt.Append(_T('d')); - restart = TRUE; + restart = true; break; } @@ -2366,11 +2468,11 @@ const wxChar *wxDateTime::ParseRfc822Date(const wxChar* date) return (wxChar *)NULL; } - wxDateTime_t day = *p++ - _T('0'); + wxDateTime_t day = (wxDateTime_t)(*p++ - _T('0')); if ( wxIsdigit(*p) ) { day *= 10; - day += *p++ - _T('0'); + day = (wxDateTime_t)(day + (*p++ - _T('0'))); } if ( *p++ != _T(' ') ) @@ -2464,7 +2566,7 @@ const wxChar *wxDateTime::ParseRfc822Date(const wxChar* date) return (wxChar *)NULL; } - wxDateTime_t hour = *p++ - _T('0'); + wxDateTime_t hour = (wxDateTime_t)(*p++ - _T('0')); if ( !wxIsdigit(*p) ) { @@ -2472,7 +2574,7 @@ const wxChar *wxDateTime::ParseRfc822Date(const wxChar* date) } hour *= 10; - hour += *p++ - _T('0'); + hour = (wxDateTime_t)(hour + (*p++ - _T('0'))); if ( *p++ != _T(':') ) { @@ -2484,7 +2586,7 @@ const wxChar *wxDateTime::ParseRfc822Date(const wxChar* date) return (wxChar *)NULL; } - wxDateTime_t min = *p++ - _T('0'); + wxDateTime_t min = (wxDateTime_t)(*p++ - _T('0')); if ( !wxIsdigit(*p) ) { @@ -2492,7 +2594,7 @@ const wxChar *wxDateTime::ParseRfc822Date(const wxChar* date) } min *= 10; - min += *p++ - _T('0'); + min = (wxDateTime_t)(min + *p++ - _T('0')); wxDateTime_t sec = 0; if ( *p++ == _T(':') ) @@ -2502,7 +2604,7 @@ const wxChar *wxDateTime::ParseRfc822Date(const wxChar* date) return (wxChar *)NULL; } - sec = *p++ - _T('0'); + sec = (wxDateTime_t)(*p++ - _T('0')); if ( !wxIsdigit(*p) ) { @@ -2510,7 +2612,7 @@ const wxChar *wxDateTime::ParseRfc822Date(const wxChar* date) } sec *= 10; - sec += *p++ - _T('0'); + sec = (wxDateTime_t)(sec + *p++ - _T('0')); } if ( *p++ != _T(' ') ) @@ -2632,17 +2734,17 @@ const wxChar *wxDateTime::ParseFormat(const wxChar *date, unsigned long num; // what fields have we found? - bool haveWDay = FALSE, - haveYDay = FALSE, - haveDay = FALSE, - haveMon = FALSE, - haveYear = FALSE, - haveHour = FALSE, - haveMin = FALSE, - haveSec = FALSE; - - bool hourIsIn12hFormat = FALSE, // or in 24h one? - isPM = FALSE; // AM by default + bool haveWDay = false, + haveYDay = false, + haveDay = false, + haveMon = false, + haveYear = false, + haveHour = false, + haveMin = false, + haveSec = false; + + bool hourIsIn12hFormat = false, // or in 24h one? + isPM = false; // AM by default // and the value of the items we have (init them to get rid of warnings) wxDateTime_t sec = 0, @@ -2731,7 +2833,7 @@ const wxChar *wxDateTime::ParseFormat(const wxChar *date, return (wxChar *)NULL; } } - haveWDay = TRUE; + haveWDay = true; break; case _T('b'): // a month name @@ -2745,7 +2847,7 @@ const wxChar *wxDateTime::ParseFormat(const wxChar *date, return (wxChar *)NULL; } } - haveMon = TRUE; + haveMon = true; break; case _T('c'): // locale default date and time representation @@ -2776,7 +2878,7 @@ const wxChar *wxDateTime::ParseFormat(const wxChar *date, Tm tm = dt.GetTm(); haveDay = haveMon = haveYear = - haveHour = haveMin = haveSec = TRUE; + haveHour = haveMin = haveSec = true; hour = tm.hour; min = tm.min; @@ -2800,7 +2902,7 @@ const wxChar *wxDateTime::ParseFormat(const wxChar *date, // we can't check whether the day range is correct yet, will // do it later - assume ok for now - haveDay = TRUE; + haveDay = true; mday = (wxDateTime_t)num; break; @@ -2811,7 +2913,7 @@ const wxChar *wxDateTime::ParseFormat(const wxChar *date, return (wxChar *)NULL; } - haveHour = TRUE; + haveHour = true; hour = (wxDateTime_t)num; break; @@ -2822,8 +2924,8 @@ const wxChar *wxDateTime::ParseFormat(const wxChar *date, return (wxChar *)NULL; } - haveHour = TRUE; - hourIsIn12hFormat = TRUE; + haveHour = true; + hourIsIn12hFormat = true; hour = (wxDateTime_t)(num % 12); // 12 should be 0 break; @@ -2834,7 +2936,7 @@ const wxChar *wxDateTime::ParseFormat(const wxChar *date, return (wxChar *)NULL; } - haveYDay = TRUE; + haveYDay = true; yday = (wxDateTime_t)num; break; @@ -2845,7 +2947,7 @@ const wxChar *wxDateTime::ParseFormat(const wxChar *date, return (wxChar *)NULL; } - haveMon = TRUE; + haveMon = true; mon = (Month)(num - 1); break; @@ -2856,7 +2958,7 @@ const wxChar *wxDateTime::ParseFormat(const wxChar *date, return (wxChar *)NULL; } - haveMin = TRUE; + haveMin = true; min = (wxDateTime_t)num; break; @@ -2865,9 +2967,11 @@ const wxChar *wxDateTime::ParseFormat(const wxChar *date, wxString am, pm, token = GetAlphaToken(input); GetAmPmStrings(&am, &pm); + if (am.empty() && pm.empty()) + return (wxChar *)NULL; // no am/pm strings defined if ( token.CmpNoCase(pm) == 0 ) { - isPM = TRUE; + isPM = true; } else if ( token.CmpNoCase(am) != 0 ) { @@ -2887,7 +2991,7 @@ const wxChar *wxDateTime::ParseFormat(const wxChar *date, return (wxChar *)NULL; } - haveHour = haveMin = haveSec = TRUE; + haveHour = haveMin = haveSec = true; Tm tm = dt.GetTm(); hour = tm.hour; @@ -2906,7 +3010,7 @@ const wxChar *wxDateTime::ParseFormat(const wxChar *date, return (wxChar *)NULL; } - haveHour = haveMin = TRUE; + haveHour = haveMin = true; Tm tm = dt.GetTm(); hour = tm.hour; @@ -2920,7 +3024,7 @@ const wxChar *wxDateTime::ParseFormat(const wxChar *date, return (wxChar *)NULL; } - haveSec = TRUE; + haveSec = true; sec = (wxDateTime_t)num; break; @@ -2934,7 +3038,7 @@ const wxChar *wxDateTime::ParseFormat(const wxChar *date, return (wxChar *)NULL; } - haveHour = haveMin = haveSec = TRUE; + haveHour = haveMin = haveSec = true; Tm tm = dt.GetTm(); hour = tm.hour; @@ -2950,7 +3054,7 @@ const wxChar *wxDateTime::ParseFormat(const wxChar *date, return (wxChar *)NULL; } - haveWDay = TRUE; + haveWDay = true; wday = (WeekDay)num; break; @@ -2967,7 +3071,7 @@ const wxChar *wxDateTime::ParseFormat(const wxChar *date, { input = result; - haveDay = haveMon = haveYear = TRUE; + haveDay = haveMon = haveYear = true; year = 1900 + tm.tm_year; mon = (Month)tm.tm_mon; @@ -3011,7 +3115,7 @@ const wxChar *wxDateTime::ParseFormat(const wxChar *date, Tm tm = dt.GetTm(); - haveDay = haveMon = haveYear = TRUE; + haveDay = haveMon = haveYear = true; year = tm.year; mon = tm.mon; @@ -3033,7 +3137,7 @@ const wxChar *wxDateTime::ParseFormat(const wxChar *date, return (wxChar *)NULL; } - haveHour = haveMin = haveSec = TRUE; + haveHour = haveMin = haveSec = true; hour = tm.tm_hour; min = tm.tm_min; @@ -3061,7 +3165,7 @@ const wxChar *wxDateTime::ParseFormat(const wxChar *date, return (wxChar *)NULL; } - haveHour = haveMin = haveSec = TRUE; + haveHour = haveMin = haveSec = true; Tm tm = dt.GetTm(); hour = tm.hour; @@ -3080,7 +3184,7 @@ const wxChar *wxDateTime::ParseFormat(const wxChar *date, return (wxChar *)NULL; } - haveYear = TRUE; + haveYear = true; // TODO should have an option for roll over date instead of // hard coding it here @@ -3094,7 +3198,7 @@ const wxChar *wxDateTime::ParseFormat(const wxChar *date, return (wxChar *)NULL; } - haveYear = TRUE; + haveYear = true; year = (wxDateTime_t)num; break; @@ -3217,11 +3321,48 @@ const wxChar *wxDateTime::ParseDateTime(const wxChar *date) { wxCHECK_MSG( date, (wxChar *)NULL, _T("NULL pointer in wxDateTime::Parse") ); - // there is a public domain version of getdate.y, but it only works for - // English... - wxFAIL_MSG(_T("TODO")); + // Set to current day and hour, so strings like '14:00' becomes today at + // 14, not some other random date + wxDateTime dtDate = wxDateTime::Today(); + wxDateTime dtTime = wxDateTime::Today(); + + const wxChar* pchTime; - return (wxChar *)NULL; + // Try to parse the beginning of the string as a date + const wxChar* pchDate = dtDate.ParseDate(date); + + // We got a date in the beginning, see if there is a time specified after the date + if ( pchDate ) + { + // Skip spaces, as the ParseTime() function fails on spaces + while ( wxIsspace(*pchDate) ) + pchDate++; + + pchTime = dtTime.ParseTime(pchDate); + } + else // no date in the beginning + { + // check and see if we have a time followed by a date + pchTime = dtTime.ParseTime(date); + if ( pchTime ) + { + while ( wxIsspace(*pchTime) ) + pchTime++; + + pchDate = dtDate.ParseDate(pchTime); + } + } + + // If we have a date specified, set our own data to the same date + if ( !pchDate || !pchTime ) + return NULL; + + Set(dtDate.GetDay(), dtDate.GetMonth(), dtDate.GetYear(), + dtTime.GetHour(), dtTime.GetMinute(), dtTime.GetSecond(), + dtTime.GetMillisecond()); + + // Return endpoint of scan + return pchDate > pchTime ? pchDate : pchTime; } const wxChar *wxDateTime::ParseDate(const wxChar *date) @@ -3252,19 +3393,23 @@ const wxChar *wxDateTime::ParseDate(const wxChar *date) { wxString date = wxGetTranslation(literalDates[n].str); size_t len = date.length(); - if ( wxStrlen(p) >= len && (wxString(p, len).CmpNoCase(date) == 0) ) + if ( wxStrlen(p) >= len ) { - // nothing can follow this, so stop here - p += len; - - int dayDiffFromToday = literalDates[n].dayDiffFromToday; - *this = Today(); - if ( dayDiffFromToday ) + wxString str(p, len); + if ( str.CmpNoCase(date) == 0 ) { - *this += wxDateSpan::Days(dayDiffFromToday); - } + // nothing can follow this, so stop here + p += len; - return p; + int dayDiffFromToday = literalDates[n].dayDiffFromToday; + *this = Today(); + if ( dayDiffFromToday ) + { + *this += wxDateSpan::Days(dayDiffFromToday); + } + + return p; + } } } @@ -3274,10 +3419,10 @@ const wxChar *wxDateTime::ParseDate(const wxChar *date) // have the ability to back track. // what do we have? - bool haveDay = FALSE, // the months day? - haveWDay = FALSE, // the day of week? - haveMon = FALSE, // the month? - haveYear = FALSE; // the year? + bool haveDay = false, // the months day? + haveWDay = false, // the day of week? + haveMon = false, // the month? + haveYear = false; // the year? // and the value of the items we have (init them to get rid of warnings) WeekDay wday = Inv_WeekDay; @@ -3301,29 +3446,40 @@ const wxChar *wxDateTime::ParseDate(const wxChar *date) { // guess what this number is - bool isDay = FALSE, - isMonth = FALSE, - isYear = FALSE; + bool isDay = false, + isMonth = false, + isYear = false; if ( !haveMon && val > 0 && val <= 12 ) { // assume it is month - isMonth = TRUE; + 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 > (unsigned long)maxDays) ) // cast to shut up compiler warning in BCC + if ( haveDay ) { - isYear = TRUE; + // this can only be the year + isYear = true; } - else + else // may be either day or year { - isDay = TRUE; + wxDateTime_t maxDays = (wxDateTime_t)( + haveMon + ? GetNumOfDaysInMonth(haveYear ? year : Inv_Year, mon) + : 31 + ); + + // can it be day? + if ( (val == 0) || (val > (unsigned long)maxDays) ) + { + // no + isYear = true; + } + else // yes, suppose it's the day + { + isDay = true; + } } } @@ -3332,7 +3488,7 @@ const wxChar *wxDateTime::ParseDate(const wxChar *date) if ( haveYear ) break; - haveYear = TRUE; + haveYear = true; year = (wxDateTime_t)val; } @@ -3341,13 +3497,13 @@ const wxChar *wxDateTime::ParseDate(const wxChar *date) if ( haveDay ) break; - haveDay = TRUE; + haveDay = true; day = (wxDateTime_t)val; } else if ( isMonth ) { - haveMon = TRUE; + haveMon = true; mon = (Month)(val - 1); } @@ -3366,8 +3522,8 @@ const wxChar *wxDateTime::ParseDate(const wxChar *date) { // 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; + day = (wxDateTime_t)(mon + 1); + haveDay = true; } else { @@ -3379,7 +3535,7 @@ const wxChar *wxDateTime::ParseDate(const wxChar *date) mon = mon2; - haveMon = TRUE; + haveMon = true; } else // not a valid month name { @@ -3392,7 +3548,7 @@ const wxChar *wxDateTime::ParseDate(const wxChar *date) break; } - haveWDay = TRUE; + haveWDay = true; } else // not a valid weekday name { @@ -3447,7 +3603,7 @@ const wxChar *wxDateTime::ParseDate(const wxChar *date) break; } - haveDay = TRUE; + haveDay = true; day = (wxDateTime_t)(n + 1); } @@ -3488,12 +3644,12 @@ const wxChar *wxDateTime::ParseDate(const wxChar *date) // we're in the current year then if ( (year > 0) && (year <= (int)GetNumOfDaysInMonth(Inv_Year, mon)) ) { - day = year; + day = (wxDateTime_t)year; - haveMon = TRUE; - haveYear = FALSE; + haveMon = true; + haveYear = false; } - //else: no, can't exchange, leave haveMon == FALSE + //else: no, can't exchange, leave haveMon == false } } @@ -3833,11 +3989,11 @@ bool wxDateTimeHolidayAuthority::IsHoliday(const wxDateTime& dt) { if ( ms_authorities[n]->DoIsHoliday(dt) ) { - return TRUE; + return true; } } - return FALSE; + return false; } /* static */ @@ -3877,7 +4033,7 @@ void wxDateTimeHolidayAuthority::AddAuthority(wxDateTimeHolidayAuthority *auth) wxDateTimeHolidayAuthority::~wxDateTimeHolidayAuthority() { - // nothing to do here + // required here for Darwin } // ----------------------------------------------------------------------------