X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/62ae2780a8049aa777ccb75e14fa395024c9d80c..532c773634cccf5c19f42aac5d2425ed3e7bb12a:/src/common/datetime.cpp diff --git a/src/common/datetime.cpp b/src/common/datetime.cpp index eb28a5c0b0..ce2814825e 100644 --- a/src/common/datetime.cpp +++ b/src/common/datetime.cpp @@ -13,7 +13,7 @@ // so long as the above copyright and this permission statement // are retained in all copies. // -// Licence: wxWindows license +// Licence: wxWindows licence /////////////////////////////////////////////////////////////////////////////// /* @@ -52,7 +52,7 @@ // headers // ---------------------------------------------------------------------------- -#ifdef __GNUG__ +#if defined(__GNUG__) && !defined(NO_GCC_PRAGMA) #pragma implementation "datetime.h" #endif @@ -75,18 +75,36 @@ #include "wx/tokenzr.h" #include "wx/module.h" -#define wxDEFINE_TIME_CONSTANTS // before including datetime.h - #include #include "wx/datetime.h" -#include "wx/timer.h" // for wxGetLocalTimeMillis() +#include "wx/stopwatch.h" // for wxGetLocalTimeMillis() + +const long wxDateTime::TIME_T_FACTOR = 1000l; + +#if wxUSE_EXTENDED_RTTI + +template<> void wxStringReadValue(const wxString &s , wxDateTime &data ) +{ + data.ParseFormat(s,wxT("%Y-%m-%d %H:%M:%S")) ; +} + +template<> void wxStringWriteValue(wxString &s , const wxDateTime &data ) +{ + s = data.Format(wxT("%Y-%m-%d %H:%M:%S")) ; +} + +wxCUSTOM_TYPE_INFO(wxDateTime, wxToStringConverter , wxFromStringConverter) + +#endif +// // ---------------------------------------------------------------------------- // conditional compilation // ---------------------------------------------------------------------------- -#if defined(HAVE_STRPTIME) && defined(__LINUX__) +#if defined(HAVE_STRPTIME) && defined(__GLIBC__) && \ + ((__GLIBC__ == 2) && (__GLIBC_MINOR__ == 0)) // glibc 2.0.7 strptime() is broken - the following snippet causes it to // crash (instead of just failing): // @@ -97,6 +115,10 @@ #undef HAVE_STRPTIME #endif // broken strptime() +#if defined(__MWERKS__) && wxUSE_UNICODE + #include +#endif + #if !defined(WX_TIMEZONE) && !defined(WX_GMTOFF_IN_TM) #if defined(__BORLANDC__) || defined(__MINGW32__) || defined(__VISAGECPP__) #define WX_TIMEZONE _timezone @@ -155,7 +177,7 @@ public: virtual void OnExit() { wxDateTimeHolidayAuthority::ClearAllAuthorities(); - wxDateTimeHolidayAuthority::ms_authorities.Clear(); + wxDateTimeHolidayAuthority::ms_authorities.clear(); } private: @@ -217,16 +239,6 @@ const wxDateTime wxDefaultDateTime; wxDateTime::Country wxDateTime::ms_country = wxDateTime::Country_Unknown; -// ---------------------------------------------------------------------------- -// private globals -// ---------------------------------------------------------------------------- - -// a critical section is needed to protect GetTimeZone() static -// variable in MT case -#if wxUSE_THREADS - static wxCriticalSection gs_critsectTimezone; -#endif // wxUSE_THREADS - // ---------------------------------------------------------------------------- // private functions // ---------------------------------------------------------------------------- @@ -262,13 +274,10 @@ wxDateTime::wxDateTime_t GetNumOfDaysInMonth(int year, wxDateTime::Month month) // (in seconds) static int GetTimeZone() { +#ifdef WX_GMTOFF_IN_TM // set to TRUE when the timezone is set static bool s_timezoneSet = FALSE; -#ifdef WX_GMTOFF_IN_TM static long gmtoffset = LONG_MAX; // invalid timezone -#endif - - wxCRIT_SECT_LOCKER(lock, gs_critsectTimezone); // ensure that the timezone variable is set by calling localtime if ( !s_timezoneSet ) @@ -281,19 +290,16 @@ static int GetTimeZone() tm = localtime(&t); s_timezoneSet = TRUE; -#ifdef WX_GMTOFF_IN_TM // 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 // cases we have to negate it gmtoffset = -tm->tm_gmtoff; -#endif } -#ifdef WX_GMTOFF_IN_TM return (int)gmtoffset; -#else +#else // !WX_GMTOFF_IN_TM return (int)WX_TIMEZONE; -#endif +#endif // WX_GMTOFF_IN_TM/!WX_GMTOFF_IN_TM } // return the integral part of the JDN for the midnight of the given date (to @@ -336,7 +342,7 @@ static long GetTruncatedJDN(wxDateTime::wxDateTime_t day, - JDN_OFFSET; } -// this function is a wrapper around strftime(3) +// this function is a wrapper around strftime(3) adding error checking static wxString CallStrftime(const wxChar *format, const tm* tm) { wxChar buf[4096]; @@ -349,6 +355,41 @@ static wxString CallStrftime(const wxChar *format, const tm* tm) return wxString(buf); } +#ifdef HAVE_STRPTIME + +// glibc2 doesn't define this in the headers unless _XOPEN_SOURCE is defined +// which, unfortunately, wreaks havoc elsewhere +#if defined(__GLIBC__) && (__GLIBC__ == 2) + extern "C" char *strptime(const char *, const char *, struct tm *); +#endif + +// Unicode-friendly strptime() wrapper +static const wxChar * +CallStrptime(const wxChar *input, const char *fmt, tm *tm) +{ + // the problem here is that strptime() returns pointer into the string we + // passed to it while we're really interested in the pointer into the + // original, Unicode, string so we try to transform the pointer back +#if wxUSE_UNICODE + wxCharBuffer inputMB(wxConvertWX2MB(input)); +#else // ASCII + const char * const inputMB = input; +#endif // Unicode/Ascii + + const char *result = strptime(inputMB, fmt, tm); + if ( !result ) + return NULL; + +#if wxUSE_UNICODE + // FIXME: this is wrong in presence of surrogates &c + return input + (result - inputMB.data()); +#else // ASCII + return result; +#endif // Unicode/Ascii +} + +#endif // HAVE_STRPTIME + // if year and/or month have invalid values, replace them with the current ones static void ReplaceDefaultYearMonthWithCurrent(int *year, wxDateTime::Month *month) @@ -2646,7 +2687,7 @@ const wxChar *wxDateTime::ParseFormat(const wxChar *date, // parse the optional width size_t width = 0; - while ( isdigit(*++fmt) ) + while ( wxIsdigit(*++fmt) ) { width *= 10; width += *fmt - _T('0'); @@ -2915,12 +2956,13 @@ const wxChar *wxDateTime::ParseFormat(const wxChar *date, case _T('x'): // locale default date representation #ifdef HAVE_STRPTIME - // try using strptime() - it may fail even if the input is + // try using strptime() -- it may fail even if the input is // correct but the date is out of range, so we will fall back - // to our generic code anyhow (FIXME !Unicode friendly) + // to our generic code anyhow { struct tm tm; - const wxChar *result = strptime(input, "%x", &tm); + + const wxChar *result = CallStrptime(input, "%x", &tm); if ( result ) { input = result; @@ -2985,7 +3027,7 @@ const wxChar *wxDateTime::ParseFormat(const wxChar *date, { // use strptime() to do it for us (FIXME !Unicode friendly) struct tm tm; - input = strptime(input, "%X", &tm); + input = CallStrptime(input, "%X", &tm); if ( !input ) { return (wxChar *)NULL; @@ -3160,6 +3202,14 @@ const wxChar *wxDateTime::ParseFormat(const wxChar *date, Set(tm); + // finally check that the week day is consistent -- if we had it + if ( haveWDay && GetWeekDay() != wday ) + { + wxLogDebug(_T("inconsistsnet week day in wxDateTime::ParseFormat()")); + + return NULL; + } + return input; } @@ -3167,11 +3217,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); - return (wxChar *)NULL; + // 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) @@ -3436,8 +3523,7 @@ const wxChar *wxDateTime::ParseDate(const wxChar *date) mon = (wxDateTime::Month)(day - 1); // we're in the current year then - if ( (year > 0) && - (unsigned)year <= GetNumOfDaysInMonth(Inv_Year, mon) ) + if ( (year > 0) && (year <= (int)GetNumOfDaysInMonth(Inv_Year, mon)) ) { day = year; @@ -3524,7 +3610,8 @@ const wxChar *wxDateTime::ParseTime(const wxChar *time) size_t len = timeString.length(); if ( timeString.CmpNoCase(wxString(time, len)) == 0 ) { - Set(stdTimes[n].hour, 0, 0); + // casts required by DigitalMars + Set(stdTimes[n].hour, wxDateTime_t(0), wxDateTime_t(0)); return time + len; } @@ -3778,7 +3865,7 @@ wxHolidayAuthoritiesArray wxDateTimeHolidayAuthority::ms_authorities; /* static */ bool wxDateTimeHolidayAuthority::IsHoliday(const wxDateTime& dt) { - size_t count = ms_authorities.GetCount(); + size_t count = ms_authorities.size(); for ( size_t n = 0; n < count; n++ ) { if ( ms_authorities[n]->DoIsHoliday(dt) ) @@ -3798,9 +3885,9 @@ wxDateTimeHolidayAuthority::GetHolidaysInRange(const wxDateTime& dtStart, { wxDateTimeArray hol; - holidays.Empty(); + holidays.Clear(); - size_t count = ms_authorities.GetCount(); + size_t count = ms_authorities.size(); for ( size_t nAuth = 0; nAuth < count; nAuth++ ) { ms_authorities[nAuth]->DoGetHolidaysInRange(dtStart, dtEnd, hol); @@ -3810,7 +3897,7 @@ wxDateTimeHolidayAuthority::GetHolidaysInRange(const wxDateTime& dtStart, holidays.Sort(wxDateTimeCompareFunc); - return holidays.GetCount(); + return holidays.size(); } /* static */ @@ -3822,7 +3909,12 @@ void wxDateTimeHolidayAuthority::ClearAllAuthorities() /* static */ void wxDateTimeHolidayAuthority::AddAuthority(wxDateTimeHolidayAuthority *auth) { - ms_authorities.Add(auth); + ms_authorities.push_back(auth); +} + +wxDateTimeHolidayAuthority::~wxDateTimeHolidayAuthority() +{ + // nothing to do here } // ----------------------------------------------------------------------------