X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/cb73e6001f891ae46b12a1e4ca39b93649cb6099..aa99e0cd2242db04fe1f9bb7d91aea545def2422:/src/common/datetime.cpp diff --git a/src/common/datetime.cpp b/src/common/datetime.cpp index 7e0815799c..2b208928df 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 @@ -839,14 +839,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(); } } @@ -1272,6 +1287,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 +1337,7 @@ wxDateTime& wxDateTime::ResetTime() wxDateTime& wxDateTime::SetFromDOS(unsigned long ddt) { struct tm tm; + InitTm(tm); long year = ddt & 0xFE000000; year >>= 25; @@ -1871,7 +1898,7 @@ 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); @@ -1888,8 +1915,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); @@ -2865,6 +2892,8 @@ const wxChar *wxDateTime::ParseFormat(const wxChar *date, wxString am, pm, token = GetAlphaToken(input); GetAmPmStrings(&am, &pm); + if (am.IsEmpty() && pm.IsEmpty()) + return (wxChar *)NULL; // no am/pm strings defined if ( token.CmpNoCase(pm) == 0 ) { isPM = TRUE; @@ -3217,11 +3246,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; + + // 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 (wxChar *)NULL; + // Return endpoint of scan + return pchDate > pchTime ? pchDate : pchTime; } const wxChar *wxDateTime::ParseDate(const wxChar *date) @@ -3312,18 +3378,27 @@ const wxChar *wxDateTime::ParseDate(const wxChar *date) } 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 ) { + // this can only be the year isYear = TRUE; } - else + else // may be either day or year { - isDay = TRUE; + wxDateTime_t maxDays = 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; + } } }