parse the strings such as {\tt "tomorrow"}, {\tt "March first"} and even
{\tt "next Sunday"}.
+Finally notice that each of the parsing functions is available in several
+overloads: if the input string is a narrow (\texttt{char *}) string, then a
+narrow pointer is returned. If the input string is a wide string, a wide char
+pointer is returned. Finally, if the input parameter is a wxString, a narrow
+char pointer is also returned for backwards compatibility but there is also an
+additional argument of wxString::const\_iterator type in which, if it is not
+\NULL, an iterator pointing to the end of the scanned string part is returned.
+
\helpref{ParseRfc822Date}{wxdatetimeparserfc822date}\\
\helpref{ParseFormat}{wxdatetimeparseformat}\\
\helpref{ParseDateTime}{wxdatetimeparsedatetime}\\
\membersection{wxDateTime::ParseRfc822Date}\label{wxdatetimeparserfc822date}
-\func{const wxChar *}{ParseRfc822Date}{\param{const wxChar* }{date}}
+\func{const char *}{ParseRfc822Date}{\param{const wxString\& }{date}, \param{wxString::const\_iterator *}{end = \NULL}}
+
+\func{const char *}{ParseRfc822Date}{\param{const char* }{date}}
+
+\func{const wchar\_t *}{ParseRfc822Date}{\param{const wchar\_t* }{date}}
-Parses the string {\it date} looking for a date formatted according to the RFC
+Parses the string \arg{date} looking for a date formatted according to the RFC
822 in it. The exact description of this format may, of course, be found in
the RFC (section $5$), but, briefly, this is the format used in the headers of
Internet email messages and one of the most common strings expressing date in
\membersection{wxDateTime::ParseFormat}\label{wxdatetimeparseformat}
-\func{const wxChar *}{ParseFormat}{\param{const wxChar *}{date}, \param{const wxChar *}{format = wxDefaultDateTimeFormat}, \param{const wxDateTime\& }{dateDef = wxDefaultDateTime}}
+\func{const char *}{ParseFormat}{\param{const wxString\& }{date}, \param{const wxString\& }{format = wxDefaultDateTimeFormat}, \param{const wxDateTime\& }{dateDef = wxDefaultDateTime}, \param{wxString::const\_iterator *}{end = \NULL}}
+
+\func{const char *}{ParseFormat}{\param{const char *}{date}, \param{const wxString\& }{format = wxDefaultDateTimeFormat}, \param{const wxDateTime\& }{dateDef = wxDefaultDateTime}}
+
+\func{const wchar\_t *}{ParseFormat}{\param{const wchar\_t *}{date}, \param{const wxString\& }{format = wxDefaultDateTimeFormat}, \param{const wxDateTime\& }{dateDef = wxDefaultDateTime}}
This function parses the string {\it date} according to the given
{\it format}. The system {\tt strptime(3)} function is used whenever available,
\membersection{wxDateTime::ParseDateTime}\label{wxdatetimeparsedatetime}
-\func{const wxChar *}{ParseDateTime}{\param{const wxChar *}{datetime}}
+\func{const char *}{ParseDateTime}{\param{const wxString\& }{datetime}, \param{wxString::const\_iterator *}{end = \NULL}}
+
+\func{const char *}{ParseDateTime}{\param{const char *}{datetime}}
+
+\func{const wchar\_t *}{ParseDateTime}{\param{const wchar\_t *}{datetime}}
Parses the string {\it datetime} containing the date and time in free format.
This function tries as hard as it can to interpret the given string as date
\membersection{wxDateTime::ParseDate}\label{wxdatetimeparsedate}
-\func{const wxChar *}{ParseDate}{\param{const wxChar *}{date}}
+\func{const char *}{ParseDate}{\param{const wxString\& }{date}, \param{wxString::const\_iterator *}{end = \NULL}}
+
+\func{const char *}{ParseDate}{\param{const char *}{date}}
+
+\func{const wchar\_t *}{ParseDate}{\param{const wchar\_t *}{date}}
This function is like \helpref{ParseDateTime}{wxdatetimeparsedatetime}, but it
only allows the date to be specified. It is thus less flexible then
\membersection{wxDateTime::ParseTime}\label{wxdatetimeparsetime}
-\func{const wxChar *}{ParseTime}{\param{const wxChar *}{time}}
+\func{const char *}{ParseTime}{\param{const wxString\& }{time}, \param{wxString::const\_iterator *}{end = \NULL}}
+
+\func{const char *}{ParseTime}{\param{const char *}{time}}
+
+\func{const wchar\_t *}{ParseTime}{\param{const wchar\_t *}{time}}
This functions is like \helpref{ParseDateTime}{wxdatetimeparsedatetime}, but
only allows the time to be specified in the input string.
// wxInvalidDateTime)
class WXDLLIMPEXP_FWD_BASE wxDateTime;
-extern WXDLLIMPEXP_DATA_BASE(const wxChar*) wxDefaultDateTimeFormat;
-extern WXDLLIMPEXP_DATA_BASE(const wxChar*) wxDefaultTimeSpanFormat;
+extern WXDLLIMPEXP_DATA_BASE(const char *) wxDefaultDateTimeFormat;
+extern WXDLLIMPEXP_DATA_BASE(const char *) wxDefaultTimeSpanFormat;
extern WXDLLIMPEXP_DATA_BASE(const wxDateTime) wxDefaultDateTime;
#define wxInvalidDateTime wxDefaultDateTime
// conversion to/from text: all conversions from text return the pointer to
// the next character following the date specification (i.e. the one where
- // the scan had to stop) or NULL on failure; for the versions returning
- // iterators, end iterator is returned instead of NULL
+ // the scan had to stop) or NULL on failure; for the versions taking
+ // wxString or wxCStrData, we don't know if the user code needs char* or
+ // wchar_t* pointer and so we return char* one for compatibility with the
+ // existing ANSI code and also return iterator in another output parameter
+ // (it will be equal to end if the entire string was parsed)
// ------------------------------------------------------------------------
// parse a string in RFC 822 format (found e.g. in mail headers and
// having the form "Wed, 10 Feb 1999 19:07:07 +0100")
- wxString::const_iterator ParseRfc822Date(const wxString& date);
+ const char *ParseRfc822Date(const wxString& date,
+ wxString::const_iterator *end = NULL);
+ const char *ParseRfc822Date(const wxCStrData& date,
+ wxString::const_iterator *end = NULL)
+ {
+ return ParseRfc822Date(date.AsString(), end);
+ }
+
const wchar_t *ParseRfc822Date(const wchar_t* date)
{
+ return ReturnEndAsWidePtr(&wxDateTime::ParseRfc822Date, date);
}
const char *ParseRfc822Date(const char* date)
{
+ return ParseRfc822Date(wxString(date));
}
// parse a date/time in the given format (see strptime(3)), fill in
// the missing (in the string) fields with the values of dateDef (by
// default, they will not change if they had valid values or will
// default to Today() otherwise)
- const wxChar *ParseFormat(const wxChar *date,
- const wxString& format = wxDefaultDateTimeFormat,
- const wxDateTime& dateDef = wxDefaultDateTime);
+ const char *ParseFormat(const wxString& date,
+ const wxString& format = wxDefaultDateTimeFormat,
+ const wxDateTime& dateDef = wxDefaultDateTime,
+ wxString::const_iterator *end = NULL);
+
+ const char *ParseFormat(const wxString& date,
+ const char *format = wxDefaultDateTimeFormat,
+ const wxDateTime& dateDef = wxDefaultDateTime,
+ wxString::const_iterator *end = NULL)
+ {
+ return ParseFormat(date, wxString(format), dateDef, end);
+ }
+
+ const char *ParseFormat(const wxString& date,
+ const wxString& format = wxDefaultDateTimeFormat,
+ wxString::const_iterator *end = NULL)
+ {
+ return ParseFormat(date, format, wxDefaultDateTime, end);
+ }
+
+ const char *ParseFormat(const wxCStrData& date,
+ const wxString& format = wxDefaultDateTimeFormat,
+ const wxDateTime& dateDef = wxDefaultDateTime,
+ wxString::const_iterator *end = NULL)
+ {
+ return ParseFormat(date.AsString(), format, dateDef, end);
+ }
+
+ const wchar_t *ParseFormat(const wchar_t *date,
+ const wxString& format = wxDefaultDateTimeFormat,
+ const wxDateTime& dateDef = wxDefaultDateTime)
+ {
+ const wxString datestr(date);
+ wxString::const_iterator end;
+ if ( !ParseFormat(datestr, format, dateDef, &end) )
+ return NULL;
+
+ return date + (end - datestr.begin());
+ }
+
+ const char *ParseFormat(const char *date,
+ const wxString& format = wxDefaultDateTimeFormat,
+ const wxDateTime& dateDef = wxDefaultDateTime)
+ {
+ return ParseFormat(wxString(date), format, dateDef);
+ }
+
// parse a string containing the date/time in "free" format, this
// function will try to make an educated guess at the string contents
- const wxChar *ParseDateTime(const wxChar *datetime);
+ const char *ParseDateTime(const wxString& datetime,
+ wxString::const_iterator *end = NULL);
+
+ const char *ParseDateTime(const wxCStrData& datetime,
+ wxString::const_iterator *end = NULL)
+ {
+ return ParseDateTime(datetime.AsString(), end);
+ }
+
+ const wchar_t *ParseDateTime(const wchar_t *datetime)
+ {
+ return ReturnEndAsWidePtr(&wxDateTime::ParseDateTime, datetime);
+ }
+
+ const char *ParseDateTime(const char *datetime)
+ {
+ return ParseDateTime(wxString(datetime));
+ }
+
// parse a string containing the date only in "free" format (less
// flexible than ParseDateTime)
- const wxChar *ParseDate(const wxChar *date);
+ const char *ParseDate(const wxString& date,
+ wxString::const_iterator *end = NULL);
+
+ const char *ParseDate(const wxCStrData& date,
+ wxString::const_iterator *end = NULL)
+ {
+ return ParseDate(date.AsString(), end);
+ }
+
+ const wchar_t *ParseDate(const wchar_t *date)
+ {
+ return ReturnEndAsWidePtr(&wxDateTime::ParseDate, date);
+ }
+
+ const char *ParseDate(const char *date)
+ {
+ return ParseDate(wxString(date));
+ }
+
// parse a string containing the time only in "free" format
- const wxChar *ParseTime(const wxChar *time);
+ const char *ParseTime(const wxString& time,
+ wxString::const_iterator *end = NULL);
+
+ const char *ParseTime(const wxCStrData& time,
+ wxString::const_iterator *end = NULL)
+ {
+ return ParseTime(time.AsString(), end);
+ }
+
+ const wchar_t *ParseTime(const wchar_t *time)
+ {
+ return ReturnEndAsWidePtr(&wxDateTime::ParseTime, time);
+ }
+
+ const char *ParseTime(const char *time)
+ {
+ return ParseTime(wxString(time));
+ }
// this function accepts strftime()-like format string (default
// argument corresponds to the preferred date and time representation
static struct tm *GetTmNow(struct tm *tmstruct);
private:
+ // helper function for defining backward-compatible wrappers for code
+ // using wchar_t* pointer instead of wxString iterators
+ typedef
+ const char *(wxDateTime::*StringMethod)(const wxString& s,
+ wxString::const_iterator *end);
+
+ const wchar_t *ReturnEndAsWidePtr(StringMethod func, const wchar_t *p)
+ {
+ const wxString s(p);
+ wxString::const_iterator end;
+ if ( !(this->*func)(s, &end) )
+ return NULL;
+
+ return p + (end - s.begin());
+ }
+
+
// the current country - as it's the same for all program objects (unless
// it runs on a _really_ big cluster system :-), this is a static member:
// see SetCountry() and GetCountry()
case wxCMD_LINE_VAL_DATE:
{
wxDateTime dt;
- // FIXME-UTF8: ParseDate API will need changes
- const wxChar *res = dt.ParseDate(value.c_str());
+ const char *res = dt.ParseDate(value);
if ( !res || *res )
{
errorMsg << wxString::Format(_("Option '%s': '%s' cannot be converted to a date."),
// global data
// ----------------------------------------------------------------------------
-const wxChar * wxDefaultDateTimeFormat = wxT("%c");
-const wxChar * wxDefaultTimeSpanFormat = wxT("%H:%M:%S");
+const char *wxDefaultDateTimeFormat = "%c";
+const char *wxDefaultTimeSpanFormat = "%H:%M:%S";
// in the fine tradition of ANSI C we use our equivalent of (time_t)-1 to
// indicate an invalid wxDateTime object
#endif
// Unicode-friendly strptime() wrapper
-static const wxChar *
-CallStrptime(const wxChar *input, const char *fmt, tm *tm)
+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
+#if wxUSE_UNICODE_WCHAR
wxCharBuffer inputMB(wxConvertWX2MB(input));
#else // ASCII
const char * const inputMB = input;
if ( !result )
return NULL;
-#if wxUSE_UNICODE
+#if wxUSE_UNICODE_WCHAR
// FIXME: this is wrong in presence of surrogates &c
return input + (result - inputMB.data());
#else // ASCII
}
// scans all digits (but no more than len) and returns the resulting number
-static bool GetNumericToken(size_t len, const wxChar*& p, unsigned long *number)
+static bool GetNumericToken(size_t len,
+ const wxStringCharType*& p,
+ unsigned long *number)
{
size_t n = 1;
wxString s;
}
// scans all alphabetic characters and returns the resulting string
-static wxString GetAlphaToken(const wxChar*& p)
+static wxString GetAlphaToken(const wxStringCharType*& p)
{
wxString s;
while ( wxIsalpha(*p) )
// RFC822 time specs.
//
// TODO a great candidate for using reg exps
-const wxChar *wxDateTime::ParseRfc822Date(const wxChar* date)
+const char *
+wxDateTime::ParseRfc822Date(const wxString& date, wxString::const_iterator *end)
{
- wxCHECK_MSG( date, (wxChar *)NULL, _T("NULL pointer in wxDateTime::Parse") );
-
- const wxChar *p = date;
- const wxChar *comma = wxStrchr(p, _T(','));
+ // TODO: rewrite using iterators instead of wxChar pointers
+ const wxStringCharType *p = date.wx_str();
+ const wxStringCharType *comma = wxStrchr(p, wxS(','));
if ( comma )
{
// the part before comma is the weekday
{
wxLogDebug(_T("no space after weekday in RFC822 time spec"));
- return (wxChar *)NULL;
+ return NULL;
}
p++; // skip space
{
wxLogDebug(_T("day number expected in RFC822 time spec, none found"));
- return (wxChar *)NULL;
+ return NULL;
}
wxDateTime_t day = (wxDateTime_t)(*p++ - _T('0'));
if ( *p++ != _T(' ') )
{
- return (wxChar *)NULL;
+ return NULL;
}
// the following 3 letters specify the month
{
wxLogDebug(_T("Invalid RFC 822 month name '%s'"), monName.c_str());
- return (wxChar *)NULL;
+ return NULL;
}
p += 3;
if ( *p++ != _T(' ') )
{
- return (wxChar *)NULL;
+ return NULL;
}
// next is the year
if ( !wxIsdigit(*p) )
{
// no year?
- return (wxChar *)NULL;
+ return NULL;
}
int year = *p++ - _T('0');
if ( !wxIsdigit(*p) )
{
// should have at least 2 digits in the year
- return (wxChar *)NULL;
+ return NULL;
}
year *= 10;
if ( !wxIsdigit(*p) )
{
// no 3 digit years please
- return (wxChar *)NULL;
+ return NULL;
}
year *= 10;
if ( *p++ != _T(' ') )
{
- return (wxChar *)NULL;
+ return NULL;
}
// time is in the format hh:mm:ss and seconds are optional
if ( !wxIsdigit(*p) )
{
- return (wxChar *)NULL;
+ return NULL;
}
wxDateTime_t hour = (wxDateTime_t)(*p++ - _T('0'));
if ( !wxIsdigit(*p) )
{
- return (wxChar *)NULL;
+ return NULL;
}
hour *= 10;
if ( *p++ != _T(':') )
{
- return (wxChar *)NULL;
+ return NULL;
}
if ( !wxIsdigit(*p) )
{
- return (wxChar *)NULL;
+ return NULL;
}
wxDateTime_t min = (wxDateTime_t)(*p++ - _T('0'));
if ( !wxIsdigit(*p) )
{
- return (wxChar *)NULL;
+ return NULL;
}
min *= 10;
{
if ( !wxIsdigit(*p) )
{
- return (wxChar *)NULL;
+ return NULL;
}
sec = (wxDateTime_t)(*p++ - _T('0'));
if ( !wxIsdigit(*p) )
{
- return (wxChar *)NULL;
+ return NULL;
}
sec *= 10;
if ( *p++ != _T(' ') )
{
- return (wxChar *)NULL;
+ return NULL;
}
// and now the interesting part: the timezone
if ( !wxIsdigit(*p) || !wxIsdigit(*(p + 1)) )
{
- return (wxChar *)NULL;
+ return NULL;
}
// hours
if ( !wxIsdigit(*p) || !wxIsdigit(*(p + 1)) )
{
- return (wxChar *)NULL;
+ return NULL;
}
// minutes
{
wxLogDebug(_T("Invalid militaty timezone '%c'"), *p);
- return (wxChar *)NULL;
+ return NULL;
}
offset = offsets[*p++ - _T('A')];
{
wxLogDebug(_T("Unknown RFC 822 timezone '%s'"), p);
- return (wxChar *)NULL;
+ return NULL;
}
p += tz.length();
Set(day, mon, year, hour, min, sec);
MakeFromTimezone(TimeZone::Make(offset*SEC_PER_MIN));
- return p;
+ const size_t endpos = p - date.wx_str();
+ if ( end )
+ *end = date.begin() + endpos;
+
+ return date.c_str() + endpos;
}
#ifdef __WINDOWS__
#endif // __WINDOWS__
-const wxChar *wxDateTime::ParseFormat(const wxChar *date,
- const wxString& format,
- const wxDateTime& dateDef)
+const char *
+wxDateTime::ParseFormat(const wxString& date,
+ const wxString& format,
+ const wxDateTime& dateDef,
+ wxString::const_iterator *end)
{
- wxCHECK_MSG( date && !format.empty(), (wxChar *)NULL,
- _T("NULL pointer in wxDateTime::ParseFormat()") );
+ wxCHECK_MSG( !format.empty(), NULL, "format can't be empty" );
wxString str;
unsigned long num;
wxDateTime::Month mon = Inv_Month;
int year = 0;
- const wxChar *input = date;
+ const wxStringCharType *input = date.wx_str();
for ( wxString::const_iterator fmt = format.begin(); fmt != format.end(); ++fmt )
{
if ( *fmt != _T('%') )
if ( *input++ != *fmt )
{
// no match
- return (wxChar *)NULL;
+ return NULL;
}
}
if ( wday == Inv_WeekDay )
{
// no match
- return (wxChar *)NULL;
+ return NULL;
}
}
haveWDay = true;
if ( mon == Inv_Month )
{
// no match
- return (wxChar *)NULL;
+ return NULL;
}
}
haveMon = true;
{
wxDateTime dt;
- // this is the format which corresponds to ctime() output
- // and strptime("%c") should parse it, so try it first
- static const wxChar *fmtCtime = _T("%a %b %d %H:%M:%S %Y");
+ const wxString inc(input);
- const wxChar *result = dt.ParseFormat(input, fmtCtime);
- if ( !result )
- {
- result = dt.ParseFormat(input, _T("%x %X"));
- }
-
- if ( !result )
- {
- result = dt.ParseFormat(input, _T("%X %x"));
- }
-
- if ( !result )
+ // try the format which corresponds to ctime() output first
+ wxString::const_iterator endc;
+ if ( !dt.ParseFormat(inc, wxS("%a %b %d %H:%M:%S %Y"), &endc) &&
+ !dt.ParseFormat(inc, wxS("%x %X"), &endc) &&
+ !dt.ParseFormat(inc, wxS("%X %x"), &endc) )
{
// we've tried everything and still no match
- return (wxChar *)NULL;
+ return NULL;
}
Tm tm = dt.GetTm();
mon = tm.mon;
mday = tm.mday;
- input = result;
+ input += endc - inc.begin();
}
break;
(num > 31) || (num < 1) )
{
// no match
- return (wxChar *)NULL;
+ return NULL;
}
// we can't check whether the day range is correct yet, will
if ( !GetNumericToken(width, input, &num) || (num > 23) )
{
// no match
- return (wxChar *)NULL;
+ return NULL;
}
haveHour = true;
if ( !GetNumericToken(width, input, &num) || !num || (num > 12) )
{
// no match
- return (wxChar *)NULL;
+ return NULL;
}
haveHour = true;
if ( !GetNumericToken(width, input, &num) || !num || (num > 366) )
{
// no match
- return (wxChar *)NULL;
+ return NULL;
}
haveYDay = true;
if ( !GetNumericToken(width, input, &num) || !num || (num > 12) )
{
// no match
- return (wxChar *)NULL;
+ return NULL;
}
haveMon = true;
if ( !GetNumericToken(width, input, &num) || (num > 59) )
{
// no match
- return (wxChar *)NULL;
+ return NULL;
}
haveMin = true;
GetAmPmStrings(&am, &pm);
if (am.empty() && pm.empty())
- return (wxChar *)NULL; // no am/pm strings defined
+ return NULL; // no am/pm strings defined
if ( token.CmpNoCase(pm) == 0 )
{
isPM = true;
else if ( token.CmpNoCase(am) != 0 )
{
// no match
- return (wxChar *)NULL;
+ return NULL;
}
}
break;
if ( !input )
{
// no match
- return (wxChar *)NULL;
+ return NULL;
}
haveHour = haveMin = haveSec = true;
if ( !input )
{
// no match
- return (wxChar *)NULL;
+ return NULL;
}
haveHour = haveMin = true;
if ( !GetNumericToken(width, input, &num) || (num > 61) )
{
// no match
- return (wxChar *)NULL;
+ return NULL;
}
haveSec = true;
if ( !input )
{
// no match
- return (wxChar *)NULL;
+ return NULL;
}
haveHour = haveMin = haveSec = true;
if ( !GetNumericToken(width, input, &num) || (wday > 6) )
{
// no match
- return (wxChar *)NULL;
+ return NULL;
}
haveWDay = true;
{
struct tm tm;
- const wxChar *result = CallStrptime(input, "%x", &tm);
+ const wxStringCharType *
+ result = CallStrptime(input, "%x", &tm);
if ( result )
{
input = result;
// Windows for the right way of formatting the date:
fmtDate = GetLocaleDateFormat();
if ( fmtDate.empty() )
-#endif
+#endif // __WINDOWS__
{
if ( IsWestEuropeanCountry(GetCountry()) ||
GetCountry() == Russia )
}
}
- const wxChar *result = dt.ParseFormat(input, fmtDate);
-
- if ( !result && !fmtDateAlt.empty() )
- {
- // ok, be nice and try another one
- result = dt.ParseFormat(input, fmtDateAlt);
- }
-
- if ( !result )
+ const wxString indate(input);
+ wxString::const_iterator endDate;
+ if ( !dt.ParseFormat(indate, fmtDate, &endDate) )
{
- // bad luck
- return (wxChar *)NULL;
+ // try another one if we have it
+ if ( fmtDateAlt.empty() ||
+ !dt.ParseFormat(indate, fmtDateAlt, &endDate) )
+ {
+ return NULL;
+ }
}
Tm tm = dt.GetTm();
- haveDay = haveMon = haveYear = true;
+ haveDay =
+ haveMon =
+ haveYear = true;
year = tm.year;
mon = tm.mon;
mday = tm.mday;
- input = result;
+ input += endDate - indate.begin();
}
break;
input = CallStrptime(input, "%X", &tm);
if ( !input )
{
- return (wxChar *)NULL;
+ return NULL;
}
haveHour = haveMin = haveSec = true;
if ( !result )
{
// no match
- return (wxChar *)NULL;
+ return NULL;
}
haveHour = haveMin = haveSec = true;
if ( !GetNumericToken(width, input, &num) || (num > 99) )
{
// no match
- return (wxChar *)NULL;
+ return NULL;
}
haveYear = true;
if ( !GetNumericToken(width, input, &num) )
{
// no match
- return (wxChar *)NULL;
+ return NULL;
}
haveYear = true;
if ( *input++ != _T('%') )
{
// no match
- return (wxChar *)NULL;
+ return NULL;
}
break;
// fall through
default: // not a known format spec
- return (wxChar *)NULL;
+ return NULL;
}
}
{
wxLogDebug(_T("bad month day in wxDateTime::ParseFormat"));
- return (wxChar *)NULL;
+ return NULL;
}
tm.mon = mon;
{
wxLogDebug(_T("bad year day in wxDateTime::ParseFormat"));
- return (wxChar *)NULL;
+ return NULL;
}
Tm tm2 = wxDateTime(1, Jan, tm.year).SetToYearDay(yday).GetTm();
return NULL;
}
- return input;
+ const size_t endpos = input - date.wx_str();
+ if ( end )
+ *end = date.begin() + endpos;
+
+ return date.c_str() + endpos;
}
-const wxChar *wxDateTime::ParseDateTime(const wxChar *date)
+const char *
+wxDateTime::ParseDateTime(const wxString& date, wxString::const_iterator *end)
{
- wxCHECK_MSG( date, (wxChar *)NULL, _T("NULL pointer in wxDateTime::Parse") );
-
// 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);
+ wxString::const_iterator
+ endTime,
+ endDate,
+ endBoth;
- // We got a date in the beginning, see if there is a time specified after the date
- if ( pchDate )
+ // If we got a date in the beginning, see if there is a time specified
+ // after the date
+ if ( dtDate.ParseDate(date, &endDate) )
{
// Skip spaces, as the ParseTime() function fails on spaces
- while ( wxIsspace(*pchDate) )
- pchDate++;
+ while ( endDate != date.end() && wxIsspace(*endDate) )
+ ++endDate;
- pchTime = dtTime.ParseTime(pchDate);
+ const wxString timestr(endDate, date.end());
+ if ( !dtTime.ParseTime(timestr, &endTime) )
+ return NULL;
+
+ endBoth = endDate + (endTime - timestr.begin());
}
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++;
+ // check if we have a time followed by a date
+ if ( !dtTime.ParseTime(date, &endTime) )
+ return NULL;
- pchDate = dtDate.ParseDate(pchTime);
- }
- }
+ while ( endTime != date.end() && wxIsspace(*endTime) )
+ ++endTime;
- // If we have a date specified, set our own data to the same date
- if ( !pchDate || !pchTime )
- return NULL;
+ const wxString datestr(endTime, date.end());
+ if ( !dtDate.ParseDate(datestr, &endDate) )
+ return NULL;
+
+ endBoth = endTime + (endDate - datestr.begin());
+ }
Set(dtDate.GetDay(), dtDate.GetMonth(), dtDate.GetYear(),
dtTime.GetHour(), dtTime.GetMinute(), dtTime.GetSecond(),
dtTime.GetMillisecond());
// Return endpoint of scan
- return pchDate > pchTime ? pchDate : pchTime;
+ if ( end )
+ *end = endBoth;
+
+ return date.c_str() + (endBoth - date.begin());
}
-const wxChar *wxDateTime::ParseDate(const wxChar *date)
+const char *
+wxDateTime::ParseDate(const wxString& date, wxString::const_iterator *end)
{
// this is a simplified version of ParseDateTime() which understands only
// "today" (for wxDate compatibility) and digits only otherwise (and not
// all esoteric constructions ParseDateTime() knows about)
- wxCHECK_MSG( date, (wxChar *)NULL, _T("NULL pointer in wxDateTime::Parse") );
-
- const wxChar *p = date;
+ const wxStringCharType *p = date.wx_str();
while ( wxIsspace(*p) )
p++;
*this += wxDateSpan::Days(dayDiffFromToday);
}
- return p;
+ const size_t endpos = p - date.wx_str();
+
+ if ( end )
+ *end = date.begin() + endpos;
+ return date.c_str() + endpos;
}
}
}
// tokenize the string
size_t nPosCur = 0;
- static const wxChar *dateDelimiters = _T(".,/-\t\r\n ");
+ static const wxStringCharType *dateDelimiters = wxS(".,/-\t\r\n ");
wxStringTokenizer tok(p, dateDelimiters);
while ( tok.HasMoreTokens() )
{
// inconsistency detected
wxLogDebug(_T("ParseDate: inconsistent day/weekday."));
- return (wxChar *)NULL;
+ return NULL;
}
}
}
p--;
}
- return p;
+ const size_t endpos = p - date.wx_str();
+ if ( end )
+ *end = date.begin() + endpos;
+
+ return date.c_str() + endpos;
}
-const wxChar *wxDateTime::ParseTime(const wxChar *time)
+const char *
+wxDateTime::ParseTime(const wxString& time, wxString::const_iterator *end)
{
- wxCHECK_MSG( time, (wxChar *)NULL, _T("NULL pointer in wxDateTime::Parse") );
-
// first try some extra things
static const struct
{
// casts required by DigitalMars
Set(stdTimes[n].hour, wxDateTime_t(0), wxDateTime_t(0));
- return time + len;
+ if ( end )
+ *end = time.begin() + len;
+
+ return time.c_str() + len;
}
}
// try all time formats we may think about in the order from longest to
// shortest
-
- // 12hour with AM/PM?
- const wxChar *result = ParseFormat(time, _T("%I:%M:%S %p"));
-
- if ( !result )
- {
- // normally, it's the same, but why not try it?
- result = ParseFormat(time, _T("%H:%M:%S"));
- }
-
- if ( !result )
+ static const char *timeFormats[] =
{
- // 12hour with AM/PM but without seconds?
- result = ParseFormat(time, _T("%I:%M %p"));
- }
+ "%I:%M:%S %p", // 12hour with AM/PM
+ "%H:%M:%S", // could be the same or 24 hour one so try it too
+ "%I:%M %p", // 12hour with AM/PM but without seconds
+ "%H:%M:%S", // and a possibly 24 hour version without seconds
+ "%X", // possibly something from above or maybe something
+ // completely different -- try it last
- if ( !result )
- {
- // without seconds?
- result = ParseFormat(time, _T("%H:%M"));
- }
-
- if ( !result )
- {
- // just the hour and AM/PM?
- result = ParseFormat(time, _T("%I %p"));
- }
-
- if ( !result )
- {
- // just the hour?
- result = ParseFormat(time, _T("%H"));
- }
+ // TODO: parse timezones
+ };
- if ( !result )
+ for ( size_t nFmt = 0; nFmt < WXSIZEOF(timeFormats); nFmt++ )
{
- // parse the standard format: normally it is one of the formats above
- // but it may be set to something completely different by the user
- result = ParseFormat(time, _T("%X"));
+ const char *result = ParseFormat(time, timeFormats[nFmt], end);
+ if ( result )
+ return result;
}
- // TODO: parse timezones
-
- return result;
+ return NULL;
}
// ----------------------------------------------------------------------------
static const struct
{
CompareKind compareKind;
- const wxChar *format;
+ const char *format;
} formatTestFormats[] =
{
- { CompareYear, _T("---> %c") }, // %c could use 2 digit years
- { CompareDate, _T("Date is %A, %d of %B, in year %Y") },
- { CompareYear, _T("Date is %x, time is %X") }, // %x could use 2 digits
- { CompareTime, _T("Time is %H:%M:%S or %I:%M:%S %p") },
- { CompareNone, _T("The day of year: %j, the week of year: %W") },
- { CompareDate, _T("ISO date without separators: %Y%m%d") },
+ { CompareYear, "---> %c" }, // %c could use 2 digit years
+ { CompareDate, "Date is %A, %d of %B, in year %Y" },
+ { CompareYear, "Date is %x, time is %X" }, // %x could use 2 digits
+ { CompareTime, "Time is %H:%M:%S or %I:%M:%S %p" },
+ { CompareNone, "The day of year: %j, the week of year: %W" },
+ { CompareDate, "ISO date without separators: %Y%m%d" },
};
static const Date formatTestDates[] =
wxDateTime dt = formatTestDates[d].DT();
for ( size_t n = 0; n < WXSIZEOF(formatTestFormats); n++ )
{
- const wxChar *fmt = formatTestFormats[n].format;
+ const char *fmt = formatTestFormats[n].format;
wxString s = dt.Format(fmt);
// what can we recover?
// convert back
wxDateTime dt2;
- const wxChar *result = dt2.ParseFormat(s.c_str(), fmt);
+ const char *result = dt2.ParseFormat(s, fmt);
if ( !result )
{
// converion failed - should it have?
static const struct TimeSpanFormatTestData
{
long h, min, sec, msec;
- const wxChar *fmt;
- const wxChar *result;
+ const char *fmt;
+ const char *result;
} testSpans[] =
{
- { 12, 34, 56, 789, _T("%H:%M:%S.%l"), _T("12:34:56.789") },
- { 1, 2, 3, 0, _T("%H:%M:%S"), _T("01:02:03") },
- { 1, 2, 3, 0, _T("%S"), _T("3723") },
- { -1, -2, -3, 0, _T("%S"), _T("-3723") },
- { -1, -2, -3, 0, _T("%H:%M:%S"), _T("-01:02:03") },
- { 26, 0, 0, 0, _T("%H"), _T("26") },
- { 26, 0, 0, 0, _T("%D, %H"), _T("1, 02") },
- { -26, 0, 0, 0, _T("%H"), _T("-26") },
- { -26, 0, 0, 0, _T("%D, %H"), _T("-1, 02") },
- { 219, 0, 0, 0, _T("%H"), _T("219") },
- { 219, 0, 0, 0, _T("%D, %H"), _T("9, 03") },
- { 219, 0, 0, 0, _T("%E, %D, %H"), _T("1, 2, 03") },
+ { 12, 34, 56, 789, "%H:%M:%S.%l", "12:34:56.789" },
+ { 1, 2, 3, 0, "%H:%M:%S", "01:02:03" },
+ { 1, 2, 3, 0, "%S", "3723" },
+ { -1, -2, -3, 0, "%S", "-3723" },
+ { -1, -2, -3, 0, "%H:%M:%S", "-01:02:03" },
+ { 26, 0, 0, 0, "%H", "26" },
+ { 26, 0, 0, 0, "%D, %H", "1, 02" },
+ { -26, 0, 0, 0, "%H", "-26" },
+ { -26, 0, 0, 0, "%D, %H", "-1, 02" },
+ { 219, 0, 0, 0, "%H", "219" },
+ { 219, 0, 0, 0, "%D, %H", "9, 03" },
+ { 219, 0, 0, 0, "%E, %D, %H", "1, 2, 03" },
};
for ( size_t n = 0; n < WXSIZEOF(testSpans); n++ )
{
static const struct ParseTestData
{
- const wxChar *rfc822;
+ const char *rfc822;
Date date; // NB: this should be in UTC
bool good;
} parseTestDates[] =
{
{
- _T("Sat, 18 Dec 1999 00:46:40 +0100"),
+ "Sat, 18 Dec 1999 00:46:40 +0100",
{ 17, wxDateTime::Dec, 1999, 23, 46, 40 },
true
},
{
- _T("Wed, 1 Dec 1999 05:17:20 +0300"),
+ "Wed, 1 Dec 1999 05:17:20 +0300",
{ 1, wxDateTime::Dec, 1999, 2, 17, 20 },
true
},
{
- _T("Sun, 28 Aug 2005 03:31:30 +0200"),
+ "Sun, 28 Aug 2005 03:31:30 +0200",
{ 28, wxDateTime::Aug, 2005, 1, 31, 30 },
true
},
{
- _T("Sat, 18 Dec 1999 10:48:30 -0500"),
+ "Sat, 18 Dec 1999 10:48:30 -0500",
{ 18, wxDateTime::Dec, 1999, 15, 48, 30 },
true
},
for ( unsigned n = 0; n < WXSIZEOF(parseTestDates); n++ )
{
- const wxChar * const datestr = parseTestDates[n].rfc822;
+ const char * const datestr = parseTestDates[n].rfc822;
wxDateTime dt;
if ( dt.ParseRfc822Date(datestr) )
{
static const struct ParseTestData
{
- const wxChar *str;
+ const char *str;
Date date; // NB: this should be in UTC
bool good;
} parseTestDates[] =
{
- { _T("21 Mar 2006"), { 21, wxDateTime::Mar, 2006 }, true },
- { _T("29 Feb 1976"), { 29, wxDateTime::Feb, 1976 }, true },
- { _T("Feb 29 1976"), { 29, wxDateTime::Feb, 1976 }, true },
- { _T("31/03/06"), { 31, wxDateTime::Mar, 6 }, true },
- { _T("31/03/2006"), { 31, wxDateTime::Mar, 2006 }, true },
+ { "21 Mar 2006", { 21, wxDateTime::Mar, 2006 }, true },
+ { "29 Feb 1976", { 29, wxDateTime::Feb, 1976 }, true },
+ { "Feb 29 1976", { 29, wxDateTime::Feb, 1976 }, true },
+ { "31/03/06", { 31, wxDateTime::Mar, 6 }, true },
+ { "31/03/2006", { 31, wxDateTime::Mar, 2006 }, true },
// some invalid ones too
- { _T("29 Feb 2006") },
- { _T("31/04/06") },
- { _T("bloordyblop") },
+ { "29 Feb 2006" },
+ { "31/04/06" },
+ { "bloordyblop" },
};
// special cases
{
static const struct ParseTestData
{
- const wxChar *str;
+ const char *str;
Date date; // NB: this should be in UTC
bool good;
} parseTestDates[] =
{
- { _T("Thu 22 Nov 2007 07:40:00 PM"),
+ { "Thu 22 Nov 2007 07:40:00 PM",
{ 22, wxDateTime::Nov, 2007, 19, 40, 0}, true },
};