]> git.saurik.com Git - wxWidgets.git/blobdiff - src/common/datetime.cpp
allow specifying the mask colour in wxImage::ConvertAlphaToMask() (closes #10143)
[wxWidgets.git] / src / common / datetime.cpp
index 06dd58caa62500c1f55b707509738d5781ae2889..16ccbc4094dd29d4fe4125044e81fa4bf610eb0b 100644 (file)
@@ -93,17 +93,17 @@ const long wxDateTime::TIME_T_FACTOR = 1000l;
 
 template<> void wxStringReadValue(const wxString &s , wxDateTime &data )
 {
-    data.ParseFormat(s,wxT("%Y-%m-%d %H:%M:%S")) ;
+    data.ParseFormat(s,"%Y-%m-%d %H:%M:%S", NULL);
 }
 
 template<> void wxStringWriteValue(wxString &s , const wxDateTime &data )
 {
-    s = data.Format(wxT("%Y-%m-%d %H:%M:%S")) ;
+    s = data.Format("%Y-%m-%d %H:%M:%S");
 }
 
 wxCUSTOM_TYPE_INFO(wxDateTime, wxToStringConverter<wxDateTime> , wxFromStringConverter<wxDateTime>)
 
-#endif
+#endif // wxUSE_EXTENDED_RTTI
 
 //
 // ----------------------------------------------------------------------------
@@ -138,13 +138,6 @@ wxCUSTOM_TYPE_INFO(wxDateTime, wxToStringConverter<wxDateTime> , wxFromStringCon
     #include <wtime.h>
 #endif
 
-// define a special symbol for VC8 instead of writing tests for 1400 repeatedly
-#ifdef __VISUALC__
-    #if __VISUALC__ >= 1400
-        #define __VISUALC8__
-    #endif
-#endif
-
 #if !defined(WX_TIMEZONE) && !defined(WX_GMTOFF_IN_TM)
     #if defined(__WXPALMOS__)
         #define WX_GMTOFF_IN_TM
@@ -368,8 +361,8 @@ static const wxDateTime::wxDateTime_t gs_cumulatedDays[2][MONTHS_IN_YEAR] =
 // 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
@@ -383,11 +376,14 @@ wxDateTime::Country wxDateTime::ms_country = wxDateTime::Country_Unknown;
 
 // debugger helper: shows what the date really is
 #ifdef __WXDEBUG__
-extern const wxChar *wxDumpDate(const wxDateTime* dt)
+extern const char *wxDumpDate(const wxDateTime* dt)
 {
-    static wxChar buf[128];
+    static char buf[128];
 
-    wxStrcpy(buf, dt->Format(_T("%Y-%m-%d (%a) %H:%M:%S")));
+    wxString fmt(dt->Format("%Y-%m-%d (%a) %H:%M:%S"));
+    wxStrlcpy(buf,
+              (fmt + " (" + dt->GetValue().ToString() + " ticks)").ToAscii(),
+              WXSIZEOF(buf));
 
     return buf;
 }
@@ -492,8 +488,10 @@ static wxString CallStrftime(const wxString& format, const tm* tm)
 
     if ( !wxStrftime(buf, WXSIZEOF(buf), format, tm) )
     {
-        // buffer is too small?
+        // if the format is valid, buffer must be too small?
         wxFAIL_MSG(_T("strftime() failed"));
+
+        buf[0] = '\0';
     }
 
     s = buf;
@@ -511,13 +509,13 @@ static wxString CallStrftime(const wxString& format, const tm* tm)
 #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;
@@ -527,7 +525,7 @@ CallStrptime(const wxChar *input, const char *fmt, tm *tm)
     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
@@ -643,7 +641,9 @@ struct tm *wxDateTime::GetTmNow(struct tm *tmstruct)
 }
 
 // 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;
@@ -659,7 +659,7 @@ static bool GetNumericToken(size_t len, const wxChar*& p, unsigned long *number)
 }
 
 // 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) )
@@ -1231,9 +1231,6 @@ wxDateTime wxDateTime::GetBeginDST(int year, Country country)
         }
 
         dt += wxTimeSpan::Hours(1);
-
-        // disable DST tests because it could result in an infinite recursion!
-        dt.MakeGMT(true);
     }
     else switch ( country )
     {
@@ -1332,9 +1329,6 @@ wxDateTime wxDateTime::GetEndDST(int year, Country country)
         }
 
         dt += wxTimeSpan::Hours(1);
-
-        // disable DST tests because it could result in an infinite recursion!
-        dt.MakeGMT(true);
     }
     else switch ( country )
     {
@@ -1613,6 +1607,7 @@ unsigned long wxDateTime::GetAsDOS() const
     time_t ticks = GetTicks();
     struct tm tmstruct;
     struct tm *tm = wxLocaltime_r(&ticks, &tmstruct);
+    wxCHECK_MSG( tm, ULONG_MAX, _T("time can't be represented in DOS format") );
 
     long year = tm->tm_year;
     year -= 80;
@@ -2694,12 +2689,12 @@ wxString wxDateTime::Format(const wxString& format, const TimeZone& tz) const
 // 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
@@ -2712,7 +2707,7 @@ const wxChar *wxDateTime::ParseRfc822Date(const wxChar* date)
         {
             wxLogDebug(_T("no space after weekday in RFC822 time spec"));
 
-            return (wxChar *)NULL;
+            return NULL;
         }
 
         p++; // skip space
@@ -2723,7 +2718,7 @@ const wxChar *wxDateTime::ParseRfc822Date(const wxChar* date)
     {
         wxLogDebug(_T("day number expected in RFC822 time spec, none found"));
 
-        return (wxChar *)NULL;
+        return NULL;
     }
 
     wxDateTime_t day = (wxDateTime_t)(*p++ - _T('0'));
@@ -2735,7 +2730,7 @@ const wxChar *wxDateTime::ParseRfc822Date(const wxChar* date)
 
     if ( *p++ != _T(' ') )
     {
-        return (wxChar *)NULL;
+        return NULL;
     }
 
     // the following 3 letters specify the month
@@ -2769,21 +2764,21 @@ const wxChar *wxDateTime::ParseRfc822Date(const wxChar* date)
     {
         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');
@@ -2791,7 +2786,7 @@ const wxChar *wxDateTime::ParseRfc822Date(const wxChar* date)
     if ( !wxIsdigit(*p) )
     {
         // should have at least 2 digits in the year
-        return (wxChar *)NULL;
+        return NULL;
     }
 
     year *= 10;
@@ -2806,7 +2801,7 @@ const wxChar *wxDateTime::ParseRfc822Date(const wxChar* date)
         if ( !wxIsdigit(*p) )
         {
             // no 3 digit years please
-            return (wxChar *)NULL;
+            return NULL;
         }
 
         year *= 10;
@@ -2815,20 +2810,20 @@ const wxChar *wxDateTime::ParseRfc822Date(const wxChar* date)
 
     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;
@@ -2836,37 +2831,38 @@ const wxChar *wxDateTime::ParseRfc822Date(const wxChar* date)
 
     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;
     min = (wxDateTime_t)(min + *p++ - _T('0'));
 
     wxDateTime_t sec = 0;
-    if ( *p++ == _T(':') )
+    if ( *p == _T(':') )
     {
+        p++;
         if ( !wxIsdigit(*p) )
         {
-            return (wxChar *)NULL;
+            return NULL;
         }
 
         sec = (wxDateTime_t)(*p++ - _T('0'));
 
         if ( !wxIsdigit(*p) )
         {
-            return (wxChar *)NULL;
+            return NULL;
         }
 
         sec *= 10;
@@ -2875,7 +2871,7 @@ const wxChar *wxDateTime::ParseRfc822Date(const wxChar* date)
 
     if ( *p++ != _T(' ') )
     {
-        return (wxChar *)NULL;
+        return NULL;
     }
 
     // and now the interesting part: the timezone
@@ -2887,7 +2883,7 @@ const wxChar *wxDateTime::ParseRfc822Date(const wxChar* date)
 
         if ( !wxIsdigit(*p) || !wxIsdigit(*(p + 1)) )
         {
-            return (wxChar *)NULL;
+            return NULL;
         }
 
         // hours
@@ -2897,7 +2893,7 @@ const wxChar *wxDateTime::ParseRfc822Date(const wxChar* date)
 
         if ( !wxIsdigit(*p) || !wxIsdigit(*(p + 1)) )
         {
-            return (wxChar *)NULL;
+            return NULL;
         }
 
         // minutes
@@ -2929,7 +2925,7 @@ const wxChar *wxDateTime::ParseRfc822Date(const wxChar* date)
             {
                 wxLogDebug(_T("Invalid militaty timezone '%c'"), *p);
 
-                return (wxChar *)NULL;
+                return NULL;
             }
 
             offset = offsets[*p++ - _T('A')];
@@ -2964,7 +2960,7 @@ const wxChar *wxDateTime::ParseRfc822Date(const wxChar* date)
             {
                 wxLogDebug(_T("Unknown RFC 822 timezone '%s'"), p);
 
-                return (wxChar *)NULL;
+                return NULL;
             }
 
             p += tz.length();
@@ -2976,9 +2972,13 @@ const wxChar *wxDateTime::ParseRfc822Date(const wxChar* date)
 
     // the spec was correct, construct the date from the values we found
     Set(day, mon, year, hour, min, sec);
-    MakeFromTimezone(TimeZone((wxDateTime_t)(offset*SEC_PER_MIN)));
+    MakeFromTimezone(TimeZone::Make(offset*SEC_PER_MIN));
+
+    const size_t endpos = p - date.wx_str();
+    if ( end )
+        *end = date.begin() + endpos;
 
-    return p;
+    return date.c_str() + endpos;
 }
 
 #ifdef __WINDOWS__
@@ -3141,12 +3141,13 @@ static wxString GetLocaleDateFormat()
 
 #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;
@@ -3174,7 +3175,7 @@ const wxChar *wxDateTime::ParseFormat(const wxChar *date,
     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('%') )
@@ -3195,7 +3196,7 @@ const wxChar *wxDateTime::ParseFormat(const wxChar *date,
                 if ( *input++ != *fmt )
                 {
                     // no match
-                    return (wxChar *)NULL;
+                    return NULL;
                 }
             }
 
@@ -3248,7 +3249,7 @@ const wxChar *wxDateTime::ParseFormat(const wxChar *date,
                     if ( wday == Inv_WeekDay )
                     {
                         // no match
-                        return (wxChar *)NULL;
+                        return NULL;
                     }
                 }
                 haveWDay = true;
@@ -3262,7 +3263,7 @@ const wxChar *wxDateTime::ParseFormat(const wxChar *date,
                     if ( mon == Inv_Month )
                     {
                         // no match
-                        return (wxChar *)NULL;
+                        return NULL;
                     }
                 }
                 haveMon = true;
@@ -3272,25 +3273,16 @@ const wxChar *wxDateTime::ParseFormat(const wxChar *date,
                 {
                     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 wxChar *result = dt.ParseFormat(input, fmtCtime);
-                    if ( !result )
-                    {
-                        result = dt.ParseFormat(input, _T("%x %X"));
-                    }
-
-                    if ( !result )
-                    {
-                        result = dt.ParseFormat(input, _T("%X %x"));
-                    }
+                    const wxString inc(input);
 
-                    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();
@@ -3306,7 +3298,7 @@ const wxChar *wxDateTime::ParseFormat(const wxChar *date,
                     mon = tm.mon;
                     mday = tm.mday;
 
-                    input = result;
+                    input += endc - inc.begin();
                 }
                 break;
 
@@ -3315,7 +3307,7 @@ const wxChar *wxDateTime::ParseFormat(const wxChar *date,
                         (num > 31) || (num < 1) )
                 {
                     // no match
-                    return (wxChar *)NULL;
+                    return NULL;
                 }
 
                 // we can't check whether the day range is correct yet, will
@@ -3328,7 +3320,7 @@ const wxChar *wxDateTime::ParseFormat(const wxChar *date,
                 if ( !GetNumericToken(width, input, &num) || (num > 23) )
                 {
                     // no match
-                    return (wxChar *)NULL;
+                    return NULL;
                 }
 
                 haveHour = true;
@@ -3339,7 +3331,7 @@ const wxChar *wxDateTime::ParseFormat(const wxChar *date,
                 if ( !GetNumericToken(width, input, &num) || !num || (num > 12) )
                 {
                     // no match
-                    return (wxChar *)NULL;
+                    return NULL;
                 }
 
                 haveHour = true;
@@ -3351,7 +3343,7 @@ const wxChar *wxDateTime::ParseFormat(const wxChar *date,
                 if ( !GetNumericToken(width, input, &num) || !num || (num > 366) )
                 {
                     // no match
-                    return (wxChar *)NULL;
+                    return NULL;
                 }
 
                 haveYDay = true;
@@ -3362,7 +3354,7 @@ const wxChar *wxDateTime::ParseFormat(const wxChar *date,
                 if ( !GetNumericToken(width, input, &num) || !num || (num > 12) )
                 {
                     // no match
-                    return (wxChar *)NULL;
+                    return NULL;
                 }
 
                 haveMon = true;
@@ -3373,7 +3365,7 @@ const wxChar *wxDateTime::ParseFormat(const wxChar *date,
                 if ( !GetNumericToken(width, input, &num) || (num > 59) )
                 {
                     // no match
-                    return (wxChar *)NULL;
+                    return NULL;
                 }
 
                 haveMin = true;
@@ -3386,7 +3378,7 @@ const wxChar *wxDateTime::ParseFormat(const wxChar *date,
 
                     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;
@@ -3394,7 +3386,7 @@ const wxChar *wxDateTime::ParseFormat(const wxChar *date,
                     else if ( token.CmpNoCase(am) != 0 )
                     {
                         // no match
-                        return (wxChar *)NULL;
+                        return NULL;
                     }
                 }
                 break;
@@ -3402,11 +3394,11 @@ const wxChar *wxDateTime::ParseFormat(const wxChar *date,
             case _T('r'):       // time as %I:%M:%S %p
                 {
                     wxDateTime dt;
-                    input = dt.ParseFormat(input, _T("%I:%M:%S %p"));
+                    input = dt.ParseFormat(input, wxS("%I:%M:%S %p"));
                     if ( !input )
                     {
                         // no match
-                        return (wxChar *)NULL;
+                        return NULL;
                     }
 
                     haveHour = haveMin = haveSec = true;
@@ -3421,11 +3413,11 @@ const wxChar *wxDateTime::ParseFormat(const wxChar *date,
             case _T('R'):       // time as %H:%M
                 {
                     wxDateTime dt;
-                    input = dt.ParseFormat(input, _T("%H:%M"));
+                    input = dt.ParseFormat(input, wxS("%H:%M"));
                     if ( !input )
                     {
                         // no match
-                        return (wxChar *)NULL;
+                        return NULL;
                     }
 
                     haveHour = haveMin = true;
@@ -3440,7 +3432,7 @@ const wxChar *wxDateTime::ParseFormat(const wxChar *date,
                 if ( !GetNumericToken(width, input, &num) || (num > 61) )
                 {
                     // no match
-                    return (wxChar *)NULL;
+                    return NULL;
                 }
 
                 haveSec = true;
@@ -3454,7 +3446,7 @@ const wxChar *wxDateTime::ParseFormat(const wxChar *date,
                     if ( !input )
                     {
                         // no match
-                        return (wxChar *)NULL;
+                        return NULL;
                     }
 
                     haveHour = haveMin = haveSec = true;
@@ -3470,7 +3462,7 @@ const wxChar *wxDateTime::ParseFormat(const wxChar *date,
                 if ( !GetNumericToken(width, input, &num) || (wday > 6) )
                 {
                     // no match
-                    return (wxChar *)NULL;
+                    return NULL;
                 }
 
                 haveWDay = true;
@@ -3485,7 +3477,8 @@ const wxChar *wxDateTime::ParseFormat(const wxChar *date,
                 {
                     struct tm tm;
 
-                    const wxChar *result = CallStrptime(input, "%x", &tm);
+                    const wxStringCharType *
+                        result = CallStrptime(input, "%x", &tm);
                     if ( result )
                     {
                         input = result;
@@ -3511,7 +3504,7 @@ const wxChar *wxDateTime::ParseFormat(const wxChar *date,
                     // Windows for the right way of formatting the date:
                     fmtDate = GetLocaleDateFormat();
                     if ( fmtDate.empty() )
-#endif
+#endif // __WINDOWS__
                     {
                         if ( IsWestEuropeanCountry(GetCountry()) ||
                              GetCountry() == Russia )
@@ -3526,29 +3519,29 @@ const wxChar *wxDateTime::ParseFormat(const wxChar *date,
                         }
                     }
 
-                    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;
@@ -3561,7 +3554,7 @@ const wxChar *wxDateTime::ParseFormat(const wxChar *date,
                     input = CallStrptime(input, "%X", &tm);
                     if ( !input )
                     {
-                        return (wxChar *)NULL;
+                        return NULL;
                     }
 
                     haveHour = haveMin = haveSec = true;
@@ -3580,19 +3573,22 @@ const wxChar *wxDateTime::ParseFormat(const wxChar *date,
                     // common cases
                     wxDateTime dt;
 
-                    const wxChar *result = dt.ParseFormat(input, _T("%T"));
+                    const wxStringCharType *
+                        result = dt.ParseFormat(input, wxS("%T"));
                     if ( !result )
                     {
-                        result = dt.ParseFormat(input, _T("%r"));
+                        result = dt.ParseFormat(input, wxS("%r"));
                     }
 
                     if ( !result )
                     {
                         // no match
-                        return (wxChar *)NULL;
+                        return NULL;
                     }
 
-                    haveHour = haveMin = haveSec = true;
+                    haveHour =
+                    haveMin =
+                    haveSec = true;
 
                     Tm tm = dt.GetTm();
                     hour = tm.hour;
@@ -3608,7 +3604,7 @@ const wxChar *wxDateTime::ParseFormat(const wxChar *date,
                 if ( !GetNumericToken(width, input, &num) || (num > 99) )
                 {
                     // no match
-                    return (wxChar *)NULL;
+                    return NULL;
                 }
 
                 haveYear = true;
@@ -3622,7 +3618,7 @@ const wxChar *wxDateTime::ParseFormat(const wxChar *date,
                 if ( !GetNumericToken(width, input, &num) )
                 {
                     // no match
-                    return (wxChar *)NULL;
+                    return NULL;
                 }
 
                 haveYear = true;
@@ -3637,7 +3633,7 @@ const wxChar *wxDateTime::ParseFormat(const wxChar *date,
                 if ( *input++ != _T('%') )
                 {
                     // no match
-                    return (wxChar *)NULL;
+                    return NULL;
                 }
                 break;
 
@@ -3647,7 +3643,7 @@ const wxChar *wxDateTime::ParseFormat(const wxChar *date,
                 // fall through
 
             default:            // not a known format spec
-                return (wxChar *)NULL;
+                return NULL;
         }
     }
 
@@ -3672,6 +3668,11 @@ const wxChar *wxDateTime::ParseFormat(const wxChar *date,
     Tm tm = tmDef;
 
     // set the date
+    if ( haveMon )
+    {
+        tm.mon = mon;
+    }
+
     if ( haveYear )
     {
         tm.year = year;
@@ -3680,16 +3681,15 @@ const wxChar *wxDateTime::ParseFormat(const wxChar *date,
     // TODO we don't check here that the values are consistent, if both year
     //      day and month/day were found, we just ignore the year day and we
     //      also always ignore the week day
-    if ( haveMon && haveDay )
+    if ( haveDay )
     {
-        if ( mday > GetNumOfDaysInMonth(tm.year, mon) )
+        if ( mday > GetNumOfDaysInMonth(tm.year, tm.mon) )
         {
             wxLogDebug(_T("bad month day in wxDateTime::ParseFormat"));
 
-            return (wxChar *)NULL;
+            return NULL;
         }
 
-        tm.mon = mon;
         tm.mday = mday;
     }
     else if ( haveYDay )
@@ -3698,7 +3698,7 @@ const wxChar *wxDateTime::ParseFormat(const wxChar *date,
         {
             wxLogDebug(_T("bad year day in wxDateTime::ParseFormat"));
 
-            return (wxChar *)NULL;
+            return NULL;
         }
 
         Tm tm2 = wxDateTime(1, Jan, tm.year).SetToYearDay(yday).GetTm();
@@ -3741,66 +3741,75 @@ const wxChar *wxDateTime::ParseFormat(const wxChar *date,
         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;
+    wxString::const_iterator
+        endTime,
+        endDate,
+        endBoth;
 
-    // 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 )
+    // 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;
+
+        const wxString timestr(endDate, date.end());
+        if ( !dtTime.ParseTime(timestr, &endTime) )
+            return NULL;
 
-        pchTime = dtTime.ParseTime(pchDate);
+        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++;
 
@@ -3835,7 +3844,11 @@ const wxChar *wxDateTime::ParseDate(const wxChar *date)
                     *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;
             }
         }
     }
@@ -3859,7 +3872,7 @@ const wxChar *wxDateTime::ParseDate(const wxChar *date)
 
     // 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() )
     {
@@ -3968,8 +3981,8 @@ const wxChar *wxDateTime::ParseDate(const wxChar *date)
             }
             else // not a valid month name
             {
-                wday = GetWeekDayFromName(token, Name_Full | Name_Abbr);
-                if ( wday != Inv_WeekDay )
+                WeekDay wday2 = GetWeekDayFromName(token, Name_Full | Name_Abbr);
+                if ( wday2 != Inv_WeekDay )
                 {
                     // a week day
                     if ( haveWDay )
@@ -3977,6 +3990,8 @@ const wxChar *wxDateTime::ParseDate(const wxChar *date)
                         break;
                     }
 
+                    wday = wday2;
+
                     haveWDay = true;
                 }
                 else // not a valid weekday name
@@ -4118,7 +4133,7 @@ const wxChar *wxDateTime::ParseDate(const wxChar *date)
                 // inconsistency detected
                 wxLogDebug(_T("ParseDate: inconsistent day/weekday."));
 
-                return (wxChar *)NULL;
+                return NULL;
             }
         }
     }
@@ -4138,13 +4153,16 @@ const wxChar *wxDateTime::ParseDate(const wxChar *date)
         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
     {
@@ -4166,56 +4184,35 @@ const wxChar *wxDateTime::ParseTime(const wxChar *time)
             // 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 )
-    {
-        // 12hour with AM/PM but without seconds?
-        result = ParseFormat(time, _T("%I:%M %p"));
-    }
-
-    if ( !result )
-    {
-        // without seconds?
-        result = ParseFormat(time, _T("%H:%M"));
-    }
-
-    if ( !result )
+    static const char *timeFormats[] =
     {
-        // just the hour and AM/PM?
-        result = ParseFormat(time, _T("%I %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 )
-    {
-        // 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;
 }
 
 // ----------------------------------------------------------------------------
@@ -4277,6 +4274,14 @@ enum TimeSpanPart
 //  %l          milliseconds (000 - 999)
 wxString wxTimeSpan::Format(const wxString& format) const
 {
+    // we deal with only positive time spans here and just add the sign in
+    // front for the negative ones
+    if ( IsNegative() )
+    {
+        wxString str(Negate().Format(format));
+        return "-" + str;
+    }
+
     wxCHECK_MSG( !format.empty(), wxEmptyString,
                  _T("NULL format in wxTimeSpan::Format") );
 
@@ -4348,13 +4353,6 @@ wxString wxTimeSpan::Format(const wxString& format) const
                     n = GetHours();
                     if ( partBiggest < Part_Hour )
                     {
-                        if ( n < 0 )
-                        {
-                            // the sign has already been taken into account
-                            // when outputting the biggest part
-                            n = -n;
-                        }
-
                         n %= HOURS_PER_DAY;
                     }
                     else
@@ -4369,9 +4367,6 @@ wxString wxTimeSpan::Format(const wxString& format) const
                     n = GetMilliseconds().ToLong();
                     if ( partBiggest < Part_MSec )
                     {
-                        if ( n < 0 )
-                            n = -n;
-
                         n %= 1000;
                     }
                     //else: no need to reset partBiggest to Part_MSec, it is
@@ -4384,9 +4379,6 @@ wxString wxTimeSpan::Format(const wxString& format) const
                     n = GetMinutes();
                     if ( partBiggest < Part_Min )
                     {
-                        if ( n < 0 )
-                            n = -n;
-
                         n %= MIN_PER_HOUR;
                     }
                     else
@@ -4401,9 +4393,6 @@ wxString wxTimeSpan::Format(const wxString& format) const
                     n = GetSeconds().ToLong();
                     if ( partBiggest < Part_Sec )
                     {
-                        if ( n < 0 )
-                            n = -n;
-
                         n %= SEC_PER_MIN;
                     }
                     else
@@ -4417,10 +4406,6 @@ wxString wxTimeSpan::Format(const wxString& format) const
 
             if ( digits )
             {
-                // negative numbers need one extra position for '-' display
-                if ( n < 0 )
-                    digits++;
-
                 fmtPrefix << _T("0") << digits;
             }
 
@@ -4601,4 +4586,30 @@ WXDLLIMPEXP_BASE void wxPrevWDay(wxDateTime::WeekDay& wd)
                                : (wxDateTime::WeekDay)(wd - 1);
 }
 
+#ifdef __WXMSW__
+
+wxDateTime& wxDateTime::SetFromMSWSysTime(const SYSTEMTIME& st)
+{
+    return Set(st.wDay,
+            static_cast<wxDateTime::Month>(wxDateTime::Jan + st.wMonth - 1),
+            st.wYear,
+            0, 0, 0);
+}
+
+void wxDateTime::GetAsMSWSysTime(SYSTEMTIME* st) const
+{
+    const wxDateTime::Tm tm(GetTm());
+
+    st->wYear = (WXWORD)tm.year;
+    st->wMonth = (WXWORD)(tm.mon - wxDateTime::Jan + 1);
+    st->wDay = tm.mday;
+
+    st->wDayOfWeek =
+    st->wHour =
+    st->wMinute =
+    st->wSecond =
+    st->wMilliseconds = 0;
+}
+#endif // __WXMSW__
+
 #endif // wxUSE_DATETIME