]> git.saurik.com Git - wxWidgets.git/blobdiff - src/common/datetime.cpp
Check for decimal separator inconsistency in wxLocale::GetInfo().
[wxWidgets.git] / src / common / datetime.cpp
index 2adec8c242846d5da92cc88f9553b97b53df5016..49bfa98e1a61487ef90a8e387214a46b76737d10 100644 (file)
@@ -117,69 +117,18 @@ wxCUSTOM_TYPE_INFO(wxDateTime, wxToStringConverter<wxDateTime> , wxFromStringCon
     #include <wtime.h>
 #endif
 
-#if !defined(WX_TIMEZONE) && !defined(WX_GMTOFF_IN_TM)
-    #if defined(__WXPALMOS__)
-        #define WX_GMTOFF_IN_TM
-    #elif defined(__BORLANDC__) || defined(__MINGW32__) || defined(__VISAGECPP__)
-        #define WX_TIMEZONE _timezone
-    #elif defined(__MWERKS__)
-        long wxmw_timezone = 28800;
-        #define WX_TIMEZONE wxmw_timezone
-    #elif defined(__DJGPP__) || defined(__WINE__)
-        #include <sys/timeb.h>
-        #include <values.h>
-        static long wxGetTimeZone()
-        {
-            static long timezone = MAXLONG; // invalid timezone
-            if (timezone == MAXLONG)
-            {
-                struct timeb tb;
-                ftime(&tb);
-                timezone = tb.timezone;
-            }
-            return timezone;
-        }
-        #define WX_TIMEZONE wxGetTimeZone()
-    #elif defined(__DARWIN__)
+#if defined(__DJGPP__) || defined(__WINE__)
+    #include <sys/timeb.h>
+    #include <values.h>
+#endif
+
+#ifndef WX_GMTOFF_IN_TM
+    // Define it for some systems which don't (always) use configure but are
+    // known to have tm_gmtoff field.
+    #if defined(__WXPALMOS__) || defined(__DARWIN__)
         #define WX_GMTOFF_IN_TM
-    #elif defined(__WXWINCE__) && defined(__VISUALC8__)
-        // _timezone is not present in dynamic run-time library
-        #if 0
-        // Solution (1): use the function equivalent of _timezone
-        static long wxGetTimeZone()
-        {
-            static long s_Timezone = MAXLONG; // invalid timezone
-            if (s_Timezone == MAXLONG)
-            {
-                int t;
-                _get_timezone(& t);
-                s_Timezone = (long) t;
-            }
-            return s_Timezone;
-        }
-        #define WX_TIMEZONE wxGetTimeZone()
-        #elif 1
-        // Solution (2): using GetTimeZoneInformation
-        static long wxGetTimeZone()
-        {
-            static long timezone = MAXLONG; // invalid timezone
-            if (timezone == MAXLONG)
-            {
-                TIME_ZONE_INFORMATION tzi;
-                ::GetTimeZoneInformation(&tzi);
-                timezone = tzi.Bias;
-            }
-            return timezone;
-        }
-        #define WX_TIMEZONE wxGetTimeZone()
-        #else
-        // Old method using _timezone: this symbol doesn't exist in the dynamic run-time library (i.e. using /MD)
-        #define WX_TIMEZONE _timezone
-        #endif
-    #else // unknown platform - try timezone
-        #define WX_TIMEZONE timezone
     #endif
-#endif // !WX_TIMEZONE && !WX_GMTOFF_IN_TM
+#endif
 
 // NB: VC8 safe time functions could/should be used for wxMSW as well probably
 #if defined(__WXWINCE__) && defined(__VISUALC8__)
@@ -296,8 +245,6 @@ static const int SEC_PER_MIN = 60;
 
 static const int MIN_PER_HOUR = 60;
 
-static const int HOURS_PER_DAY = 24;
-
 static const long SECONDS_PER_DAY = 86400l;
 
 static const int DAYS_PER_WEEK = 7;
@@ -338,8 +285,8 @@ const long wxDateTime::TIME_T_FACTOR = 1000l;
 // global data
 // ----------------------------------------------------------------------------
 
-const char *wxDefaultDateTimeFormat = "%c";
-const char *wxDefaultTimeSpanFormat = "%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
@@ -371,7 +318,7 @@ wxDateTime::wxDateTime_t GetNumOfDaysInMonth(int year, wxDateTime::Month month)
 {
     // the number of days in month in Julian/Gregorian calendar: the first line
     // is for normal years, the second one is for the leap ones
-    static wxDateTime::wxDateTime_t daysInMonth[2][MONTHS_IN_YEAR] =
+    static const wxDateTime::wxDateTime_t daysInMonth[2][MONTHS_IN_YEAR] =
     {
         { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 },
         { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }
@@ -385,6 +332,7 @@ wxDateTime::wxDateTime_t GetNumOfDaysInMonth(int year, wxDateTime::Month month)
 // NOTE: not static because used by datetimefmt.cpp
 int GetTimeZone()
 {
+#ifdef WX_GMTOFF_IN_TM
     // set to true when the timezone is set
     static bool s_timezoneSet = false;
     static long gmtoffset = LONG_MAX; // invalid timezone
@@ -400,17 +348,40 @@ int GetTimeZone()
         wxLocaltime_r(&t, &tm);
         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;
-#else // !WX_GMTOFF_IN_TM
-        gmtoffset = WX_TIMEZONE;
-#endif // WX_GMTOFF_IN_TM/!WX_GMTOFF_IN_TM
     }
-
     return (int)gmtoffset;
+#elif defined(__DJGPP__) || defined(__WINE__)
+    struct timeb tb;
+    ftime(&tb);
+    return tb.timezone*60;
+#elif defined(__VISUALC__)
+    // We must initialize the time zone information before using it (this will
+    // be done only once internally).
+    _tzset();
+
+    // Starting with VC++ 8 timezone variable is deprecated and is not even
+    // available in some standard library version so use the new function for
+    // accessing it instead.
+    #if wxCHECK_VISUALC_VERSION(8)
+        long t;
+        _get_timezone(&t);
+        return t;
+    #else // VC++ < 8
+        return timezone;
+    #endif
+#elif defined(WX_TIMEZONE) // If WX_TIMEZONE was defined by configure, use it.
+    return WX_TIMEZONE;
+#elif defined(__BORLANDC__) || defined(__MINGW32__) || defined(__VISAGECPP__)
+    return _timezone;
+#elif defined(__MWERKS__)
+    return 28800;
+#else // unknown platform -- assume it has timezone
+    return timezone;
+#endif // WX_GMTOFF_IN_TM/!WX_GMTOFF_IN_TM
 }
 
 // return the integral part of the JDN for the midnight of the given date (to
@@ -526,8 +497,12 @@ wxDateTime::Tm::Tm()
 {
     year = (wxDateTime_t)wxDateTime::Inv_Year;
     mon = wxDateTime::Inv_Month;
-    mday = 0;
-    hour = min = sec = msec = 0;
+    mday =
+    yday = 0;
+    hour =
+    min =
+    sec =
+    msec = 0;
     wday = wxDateTime::Inv_WeekDay;
 }
 
@@ -547,9 +522,17 @@ wxDateTime::Tm::Tm(const struct tm& tm, const TimeZone& tz)
 
 bool wxDateTime::Tm::IsValid() const
 {
+    if ( mon == wxDateTime::Inv_Month )
+        return false;
+
+    // We need to check this here to avoid crashing in GetNumOfDaysInMonth() if
+    // somebody passed us "(wxDateTime::Month)1000".
+    wxCHECK_MSG( mon >= wxDateTime::Jan && mon < wxDateTime::Inv_Month, false,
+                 wxS("Invalid month value") );
+
     // we allow for the leap seconds, although we don't use them (yet)
     return (year != wxDateTime::Inv_Year) && (mon != wxDateTime::Inv_Month) &&
-           (mday <= GetNumOfDaysInMonth(year, mon)) &&
+           (mday > 0 && mday <= GetNumOfDaysInMonth(year, mon)) &&
            (hour < 24) && (min < 60) && (sec < 62) && (msec < 1000);
 }
 
@@ -836,7 +819,7 @@ wxString wxDateTime::GetEnglishMonthName(Month month, NameFlags flags)
 {
     wxCHECK_MSG( month != Inv_Month, wxEmptyString, "invalid month" );
 
-    static const char *monthNames[2][MONTHS_IN_YEAR] =
+    static const char *const monthNames[2][MONTHS_IN_YEAR] =
     {
         { "January", "February", "March", "April", "May", "June",
           "July", "August", "September", "October", "November", "December" },
@@ -875,7 +858,7 @@ wxString wxDateTime::GetEnglishWeekDayName(WeekDay wday, NameFlags flags)
 {
     wxCHECK_MSG( wday != Inv_WeekDay, wxEmptyString, wxT("invalid weekday") );
 
-    static const char *weekdayNames[2][DAYS_PER_WEEK] =
+    static const char *const weekdayNames[2][DAYS_PER_WEEK] =
     {
         { "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday",
           "Saturday" },
@@ -1630,6 +1613,7 @@ wxDateTime::Tm wxDateTime::GetTm(const TimeZone& tz) const
     // construct Tm from these values
     Tm tm;
     tm.year = (int)year;
+    tm.yday = (wxDateTime_t)(dayOfYear - 1); // use C convention for day number
     tm.mon = (Month)(month - 1); // algorithm yields 1 for January, not 0
     tm.mday = (wxDateTime_t)day;
     tm.msec = (wxDateTime_t)(timeOnly % 1000);
@@ -2070,16 +2054,22 @@ wxDateTime::wxDateTime_t wxDateTime::GetWeekOfMonth(wxDateTime::WeekFlags flags,
                                                     const TimeZone& tz) const
 {
     Tm tm = GetTm(tz);
-    wxDateTime dtMonthStart = wxDateTime(1, tm.mon, tm.year);
-    int nWeek = GetWeekOfYear(flags) - dtMonthStart.GetWeekOfYear(flags) + 1;
-    if ( nWeek < 0 )
+    const wxDateTime dateFirst = wxDateTime(1, tm.mon, tm.year);
+    const wxDateTime::WeekDay wdFirst = dateFirst.GetWeekDay();
+
+    if ( flags == Default_First )
     {
-        // this may happen for January when Jan, 1 is the last week of the
-        // previous year
-        nWeek += IsLeapYear(tm.year - 1) ? 53 : 52;
+        flags = GetCountry() == USA ? Sunday_First : Monday_First;
     }
 
-    return (wxDateTime::wxDateTime_t)nWeek;
+    // compute offset of dateFirst from the beginning of the week
+    int firstOffset;
+    if ( flags == Sunday_First )
+        firstOffset = wdFirst - Sun;
+    else
+        firstOffset = wdFirst == Sun ? DAYS_PER_WEEK - 1 : wdFirst - Mon;
+
+    return (wxDateTime::wxDateTime_t)((tm.mday - 1 + firstOffset)/7 + 1);
 }
 
 wxDateTime& wxDateTime::SetToYearDay(wxDateTime::wxDateTime_t yday)
@@ -2356,7 +2346,15 @@ wxDateTime& wxDateTime::SetFromMSWSysTime(const SYSTEMTIME& st)
     return Set(st.wDay,
             static_cast<wxDateTime::Month>(wxDateTime::Jan + st.wMonth - 1),
             st.wYear,
-            0, 0, 0);
+            st.wHour, st.wMinute, st.wSecond, st.wMilliseconds);
+}
+
+wxDateTime& wxDateTime::SetFromMSWSysDate(const SYSTEMTIME& st)
+{
+    return Set(st.wDay,
+            static_cast<wxDateTime::Month>(wxDateTime::Jan + st.wMonth - 1),
+            st.wYear,
+            0, 0, 0, 0);
 }
 
 void wxDateTime::GetAsMSWSysTime(SYSTEMTIME* st) const
@@ -2367,12 +2365,28 @@ void wxDateTime::GetAsMSWSysTime(SYSTEMTIME* st) const
     st->wMonth = (WXWORD)(tm.mon - wxDateTime::Jan + 1);
     st->wDay = tm.mday;
 
+    st->wDayOfWeek = 0;
+    st->wHour = tm.hour;
+    st->wMinute = tm.min;
+    st->wSecond = tm.sec;
+    st->wMilliseconds = tm.msec;
+}
+
+void wxDateTime::GetAsMSWSysDate(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