X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/7d3e806d86a159f3af1db1744a75de162e0e1a8d..22e3c5bd85233ba23fbb62cd421a7dd173adfa73:/src/common/datetime.cpp diff --git a/src/common/datetime.cpp b/src/common/datetime.cpp index 7f1f7924a0..d0e828f406 100644 --- a/src/common/datetime.cpp +++ b/src/common/datetime.cpp @@ -127,6 +127,18 @@ wxCUSTOM_TYPE_INFO(wxDateTime, wxToStringConverter , wxFromStringCon #undef HAVE_STRPTIME #endif // broken strptime() +#if defined(HAVE_STRPTIME) && defined(__DARWIN__) && defined(_MSL_USING_MW_C_HEADERS) && _MSL_USING_MW_C_HEADERS + // configure detects strptime as linkable because it's in the OS X + // System library but MSL headers don't declare it. + +// char *strptime(const char *, const char *, struct tm *); + // However, we DON'T want to just provide it here because we would + // crash and/or overwrite data when strptime from OS X tries + // to fill in MW's struct tm which is two fields shorter (no TZ stuff) + // So for now let's just say we don't have strptime + #undef HAVE_STRPTIME +#endif + #if defined(__MWERKS__) && wxUSE_UNICODE #include #endif @@ -2846,10 +2858,12 @@ const wxChar *wxDateTime::ParseRfc822Date(const wxChar* date) #ifdef __WINDOWS__ -// Get's current locale's date formatting string and stores it in fmt if -// the locale is set; otherwise or in case of failure, leaves fmt unchanged -static void GetLocaleDateFormat(wxString *fmt) +// returns the string containing strftime() format used for short dates in the +// current locale or an empty string +static wxString GetLocaleDateFormat() { + wxString fmtWX; + // there is no setlocale() under Windows CE, so just always query the // system there #ifndef __WXWINCE__ @@ -2865,45 +2879,139 @@ static void GetLocaleDateFormat(wxString *fmt) #else LCID lcid = GetThreadLocale(); #endif - wxChar delim[5]; // fields deliminer, 4 chars max - if ( GetLocaleInfo(lcid, LOCALE_SDATE, delim, 5) ) + // according to MSDN 80 chars is max allowed for short date format + wxChar fmt[81]; + if ( ::GetLocaleInfo(lcid, LOCALE_SSHORTDATE, fmt, WXSIZEOF(fmt)) ) { - wxChar centurybuf[2]; // use %y or %Y, 1 char max - wxChar century = 'y'; - if ( GetLocaleInfo(lcid, LOCALE_ICENTURY, centurybuf, 2) ) - { - if ( centurybuf[0] == _T('1') ) - century = 'Y'; - // else 'y' as above - } - - wxChar order[2]; // order code, 1 char max - if ( GetLocaleInfo(lcid, LOCALE_IDATE, order, 2) ) + wxChar chLast = _T('\0'); + size_t lastCount = 0; + for ( const wxChar *p = fmt; /* NUL handled inside */; p++ ) { - if ( order[0] == _T('0') ) // M-D-Y + if ( *p == chLast ) { - *fmt = wxString::Format(_T("%%m%s%%d%s%%%c"), - delim, delim, century); - } - else if ( order[0] == _T('1') ) // D-M-Y - { - *fmt = wxString::Format(_T("%%d%s%%m%s%%%c"), - delim, delim, century); - } - else if ( order[0] == _T('2') ) // Y-M-D - { - *fmt = wxString::Format(_T("%%%c%s%%m%s%%d"), - century, delim, delim); + lastCount++; + continue; } - else + + switch ( *p ) { - wxFAIL_MSG(_T("unexpected GetLocaleInfo return value")); + // these characters come in groups, start counting them + case _T('d'): + case _T('M'): + case _T('y'): + case _T('g'): + chLast = *p; + lastCount = 1; + break; + + default: + // first deal with any special characters we have had + if ( lastCount ) + { + switch ( chLast ) + { + case _T('d'): + switch ( lastCount ) + { + case 1: // d + case 2: // dd + // these two are the same as we + // don't distinguish between 1 and + // 2 digits for days + fmtWX += _T("%d"); + break; + + case 3: // ddd + fmtWX += _T("%a"); + break; + + case 4: // dddd + fmtWX += _T("%A"); + break; + + default: + wxFAIL_MSG( _T("too many 'd's") ); + } + break; + + case _T('M'): + switch ( lastCount ) + { + case 1: // M + case 2: // MM + // as for 'd' and 'dd' above + fmtWX += _T("%m"); + break; + + case 3: + fmtWX += _T("%b"); + break; + + case 4: + fmtWX += _T("%B"); + break; + + default: + wxFAIL_MSG( _T("too many 'M's") ); + } + break; + + case _T('y'): + switch ( lastCount ) + { + case 1: // y + case 2: // yy + fmtWX += _T("%y"); + break; + + case 4: // yyyy + fmtWX += _T("%Y"); + break; + + default: + wxFAIL_MSG( _T("wrong number of 'y's") ); + } + break; + + case _T('g'): + // strftime() doesn't have era string, + // ignore this format + wxASSERT_MSG( lastCount <= 2, + _T("too many 'g's") ); + break; + + default: + wxFAIL_MSG( _T("unreachable") ); + } + + chLast = _T('\0'); + lastCount = 0; + } + + // not a special character so must be just a separator, + // treat as is + if ( *p != _T('\0') ) + { + if ( *p == _T('%') ) + { + // this one needs to be escaped + fmtWX += _T('%'); + } + + fmtWX += *p; + } } + + if ( *p == _T('\0') ) + break; } } - // if we failed, leave fmtDate value unchanged and - // try our luck with the default set above + //else: GetLocaleInfo() failed, leave fmtDate value unchanged and + // try our luck with the default formats } + //else: default C locale, default formats should work + + return fmtWX; } #endif // __WINDOWS__ @@ -3270,30 +3378,32 @@ const wxChar *wxDateTime::ParseFormat(const wxChar *date, { wxDateTime dt; - - wxString fmtDate, fmtDateAlt; - - if ( IsWestEuropeanCountry(GetCountry()) || - GetCountry() == Russia ) - { - fmtDate = _T("%d/%m/%y"); - fmtDateAlt = _T("%m/%d/%y"); - } - else // assume USA - { - fmtDate = _T("%m/%d/%y"); - fmtDateAlt = _T("%d/%m/%y"); - } + wxString fmtDate, + fmtDateAlt; #ifdef __WINDOWS__ // The above doesn't work for all locales, try to query // Windows for the right way of formatting the date: - GetLocaleDateFormat(&fmtDate); + fmtDate = GetLocaleDateFormat(); + if ( fmtDate.empty() ) #endif + { + if ( IsWestEuropeanCountry(GetCountry()) || + GetCountry() == Russia ) + { + fmtDate = _T("%d/%m/%y"); + fmtDateAlt = _T("%m/%d/%y"); + } + else // assume USA + { + fmtDate = _T("%m/%d/%y"); + fmtDateAlt = _T("%d/%m/%y"); + } + } const wxChar *result = dt.ParseFormat(input, fmtDate); - if ( !result ) + if ( !result && !fmtDateAlt.empty() ) { // ok, be nice and try another one result = dt.ParseFormat(input, fmtDateAlt);