make GetNumOfDaysInMonth static again; in datetimefmt.cpp use GetNumberOfDays instead.

Attempt to fix wxDateTime::ParseFormat(date, "%c") by using strptime() before our own heuristic checks.

git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@59667 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
Francesco Montorsi
2009-03-20 20:45:20 +00:00
parent 9445de1e4f
commit c4e085608a
2 changed files with 67 additions and 54 deletions

View File

@@ -391,8 +391,7 @@ extern const char *wxDumpDate(const wxDateTime* dt)
#endif // Debug #endif // Debug
// get the number of days in the given month of the given year // get the number of days in the given month of the given year
// NOTE: not static because required by datetimefmt.cpp, too static inline
inline
wxDateTime::wxDateTime_t GetNumOfDaysInMonth(int year, wxDateTime::Month month) wxDateTime::wxDateTime_t GetNumOfDaysInMonth(int year, wxDateTime::Month month)
{ {
// the number of days in month in Julian/Gregorian calendar: the first line // the number of days in month in Julian/Gregorian calendar: the first line
@@ -502,41 +501,6 @@ static wxString CallStrftime(const wxString& format, const tm* tm)
#endif // HAVE_STRFTIME #endif // HAVE_STRFTIME
#ifdef HAVE_STRPTIME
#if wxUSE_UNIX && !defined(HAVE_STRPTIME_DECL)
// configure detected that we had strptime() but not its declaration,
// provide it ourselves
extern "C" char *strptime(const char *, const char *, struct tm *);
#endif
// Unicode-friendly strptime() wrapper
static const wxStringCharType *
CallStrptime(const wxStringCharType *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_WCHAR
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_WCHAR
// 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 // if year and/or month have invalid values, replace them with the current ones
static void ReplaceDefaultYearMonthWithCurrent(int *year, static void ReplaceDefaultYearMonthWithCurrent(int *year,
wxDateTime::Month *month) wxDateTime::Month *month)

View File

@@ -79,8 +79,40 @@ static const int MIN_PER_HOUR = 60;
// parsing helpers // parsing helpers
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
// see datetime.cpp: #ifdef HAVE_STRPTIME
wxDateTime::wxDateTime_t GetNumOfDaysInMonth(int year, wxDateTime::Month month);
#if wxUSE_UNIX && !defined(HAVE_STRPTIME_DECL)
// configure detected that we had strptime() but not its declaration,
// provide it ourselves
extern "C" char *strptime(const char *, const char *, struct tm *);
#endif
// Unicode-friendly strptime() wrapper
static const wxStringCharType *
CallStrptime(const wxStringCharType *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_WCHAR
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_WCHAR
// FIXME: this is wrong in presence of surrogates &c
return input + (result - inputMB.data());
#else // ASCII
return result;
#endif // Unicode/Ascii
}
#endif // HAVE_STRPTIME
// return the month if the string is a month name or Inv_Month otherwise // return the month if the string is a month name or Inv_Month otherwise
static wxDateTime::Month GetMonthFromName(const wxString& name, int flags) static wxDateTime::Month GetMonthFromName(const wxString& name, int flags)
@@ -1151,9 +1183,22 @@ wxDateTime::ParseFormat(const wxString& date,
case _T('c'): // locale default date and time representation case _T('c'): // locale default date and time representation
{ {
wxDateTime dt; wxDateTime dt;
Tm tm;
const wxString inc(input); const wxString inc(input);
// NOTE: %c is locale-dependent; try strptime
#ifdef HAVE_STRPTIME
// 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
const wxStringCharType *
result = CallStrptime(input, "%c", &tm);
if ( !result )
{
// strptime() failed; try generic heuristic code
#endif // HAVE_STRPTIME
// try the format which corresponds to ctime() output first // try the format which corresponds to ctime() output first
wxString::const_iterator endc; wxString::const_iterator endc;
if ( !dt.ParseFormat(inc, wxS("%a %b %d %H:%M:%S %Y"), &endc) && if ( !dt.ParseFormat(inc, wxS("%a %b %d %H:%M:%S %Y"), &endc) &&
@@ -1164,7 +1209,13 @@ wxDateTime::ParseFormat(const wxString& date,
return NULL; return NULL;
} }
Tm tm = dt.GetTm(); tm = dt.GetTm();
input += endc - inc.begin();
#ifdef HAVE_STRPTIME
}
else
input = result; // proceed where strptime() ended
#endif // HAVE_STRPTIME
haveDay = haveMon = haveYear = haveDay = haveMon = haveYear =
haveHour = haveMin = haveSec = true; haveHour = haveMin = haveSec = true;
@@ -1176,8 +1227,6 @@ wxDateTime::ParseFormat(const wxString& date,
year = tm.year; year = tm.year;
mon = tm.mon; mon = tm.mon;
mday = tm.mday; mday = tm.mday;
input += endc - inc.begin();
} }
break; break;
@@ -1570,7 +1619,7 @@ wxDateTime::ParseFormat(const wxString& date,
// also always ignore the week day // also always ignore the week day
if ( haveDay ) if ( haveDay )
{ {
if ( mday > GetNumOfDaysInMonth(tm.year, tm.mon) ) if ( mday > GetNumberOfDays(tm.mon, tm.year) )
{ {
wxLogDebug(_T("bad month day in wxDateTime::ParseFormat")); wxLogDebug(_T("bad month day in wxDateTime::ParseFormat"));
@@ -1798,7 +1847,7 @@ wxDateTime::ParseDate(const wxString& date, wxString::const_iterator *end)
// dates like 2/29/1976 which would be rejected otherwise // dates like 2/29/1976 which would be rejected otherwise
wxDateTime_t max_days = (wxDateTime_t)( wxDateTime_t max_days = (wxDateTime_t)(
haveMon haveMon
? GetNumOfDaysInMonth(haveYear ? year : 1976, mon) ? GetNumberOfDays(mon, haveYear ? year : 1976)
: 31 : 31
); );
@@ -1976,7 +2025,7 @@ wxDateTime::ParseDate(const wxString& date, wxString::const_iterator *end)
mon = (wxDateTime::Month)(day - 1); mon = (wxDateTime::Month)(day - 1);
// we're in the current year then // we're in the current year then
if ( (year > 0) && (year <= (int)GetNumOfDaysInMonth(Inv_Year, mon)) ) if ( (year > 0) && (year <= (int)GetNumberOfDays(mon, Inv_Year)) )
{ {
day = (wxDateTime_t)year; day = (wxDateTime_t)year;
@@ -2010,7 +2059,7 @@ wxDateTime::ParseDate(const wxString& date, wxString::const_iterator *end)
{ {
// normally we check the day above but the check is optimistic in case // normally we check the day above but the check is optimistic in case
// we find the day before its month/year so we have to redo it now // we find the day before its month/year so we have to redo it now
if ( day > GetNumOfDaysInMonth(year, mon) ) if ( day > GetNumberOfDays(mon, year) )
return NULL; return NULL;
Set(day, mon, year); Set(day, mon, year);