///////////////////////////////////////////////////////////////////////////////
-// Name: wx/datetime.h
+// Name: src/common/datetime.cpp
// Purpose: implementation of time/date related classes
// Author: Vadim Zeitlin
// Modified by:
// headers
// ----------------------------------------------------------------------------
-#if defined(__GNUG__) && !defined(NO_GCC_PRAGMA)
- #pragma implementation "datetime.h"
-#endif
-
// For compilers that support precompilation, includes "wx.h".
#include "wx/wxprec.h"
#endif
#endif // !WX_TIMEZONE && !WX_GMTOFF_IN_TM
+#if wxUSE_THREADS
+static wxMutex timeLock;
+#endif
+
+#ifndef HAVE_LOCALTIME_R
+struct tm *wxLocaltime_r(const time_t* ticks, struct tm* temp)
+{
+#if wxUSE_THREADS && !defined(__WINDOWS__)
+ // No need to waste time with a mutex on windows since it's using
+ // thread local storage for localtime anyway.
+ wxMutexLocker locker(timeLock);
+#endif
+ memcpy(temp, localtime(ticks), sizeof(struct tm));
+ return temp;
+}
+#endif
+
+#ifndef HAVE_GMTIME_R
+struct tm *wxGmtime_r(const time_t* ticks, struct tm* temp)
+{
+#if wxUSE_THREADS && !defined(__WINDOWS__)
+ // No need to waste time with a mutex on windows since it's
+ // using thread local storage for gmtime anyway.
+ wxMutexLocker locker(timeLock);
+#endif
+ memcpy(temp, gmtime(ticks), sizeof(struct tm));
+ return temp;
+}
+#endif
+
// ----------------------------------------------------------------------------
// macros
// ----------------------------------------------------------------------------
// (i.e. JDN(Jan 1, 1970) = 2440587.5)
static const long EPOCH_JDN = 2440587l;
+// used only in asserts
+#ifdef __WXDEBUG__
// the date of JDN -0.5 (as we don't work with fractional parts, this is the
// reference date for us) is Nov 24, 4714BC
static const int JDN_0_YEAR = -4713;
static const int JDN_0_MONTH = wxDateTime::Nov;
static const int JDN_0_DAY = 24;
+#endif // __WXDEBUG__
// the constants used for JDN calculations
static const long JDN_OFFSET = 32046l;
static bool s_timezoneSet = false;
static long gmtoffset = LONG_MAX; // invalid timezone
- // ensure that the timezone variable is set by calling localtime
+ // ensure that the timezone variable is set by calling wxLocaltime_r
if ( !s_timezoneSet )
{
- // just call localtime() instead of figuring out whether this system
- // supports tzset(), _tzset() or something else
+ // just call wxLocaltime_r() instead of figuring out whether this
+ // system supports tzset(), _tzset() or something else
time_t t = 0;
struct tm *tm;
+ struct tm tmstruct;
- tm = localtime(&t);
+ tm = wxLocaltime_r(&t, &tmstruct);
s_timezoneSet = true;
// note that GMT offset is the opposite of time zone and so to return
#ifdef HAVE_STRPTIME
-// glibc2 doesn't define this in the headers unless _XOPEN_SOURCE is defined
-// which, unfortunately, wreaks havoc elsewhere
-#if defined(__GLIBC__) && (__GLIBC__ == 2)
+#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
wxDateTime::Month *month)
{
struct tm *tmNow = NULL;
+ struct tm tmstruct;
if ( *year == wxDateTime::Inv_Year )
{
- tmNow = wxDateTime::GetTmNow();
+ tmNow = wxDateTime::GetTmNow(&tmstruct);
*year = 1900 + tmNow->tm_year;
}
if ( *month == wxDateTime::Inv_Month )
{
if ( !tmNow )
- tmNow = wxDateTime::GetTmNow();
+ tmNow = wxDateTime::GetTmNow(&tmstruct);
*month = (wxDateTime::Month)tmNow->tm_mon;
}
return wd;
}
+/* static */
+struct tm *wxDateTime::GetTmNow(struct tm *tmstruct)
+{
+ time_t t = GetTimeNow();
+ return wxLocaltime_r(&t, 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)
{
{
// try to guess from the time zone name
time_t t = time(NULL);
- struct tm *tm = localtime(&t);
+ struct tm tmstruct;
+ struct tm *tm = wxLocaltime_r(&t, &tmstruct);
wxString tz = CallStrftime(_T("%Z"), tm);
if ( tz == _T("WET") || tz == _T("WEST") )
_T("Invalid time in wxDateTime::Set()") );
// get the current date from system
- struct tm *tm = GetTmNow();
+ struct tm tmstruct;
+ struct tm *tm = GetTmNow(&tmstruct);
- wxDATETIME_CHECK( tm, _T("localtime() failed") );
+ wxDATETIME_CHECK( tm, _T("wxLocaltime_r() failed") );
// make a copy so it isn't clobbered by the call to mktime() below
struct tm tm1(*tm);
{
unsigned long ddt;
time_t ticks = GetTicks();
- struct tm *tm = localtime(&ticks);
+ struct tm tmstruct;
+ struct tm *tm = wxLocaltime_r(&ticks, &tmstruct);
long year = tm->tm_year;
year -= 80;
if ( time != (time_t)-1 )
{
// use C RTL functions
+ struct tm tmstruct;
tm *tm;
if ( tz.GetOffset() == -GetTimeZone() )
{
// we are working with local time
- tm = localtime(&time);
+ tm = wxLocaltime_r(&time, &tmstruct);
// should never happen
- wxCHECK_MSG( tm, Tm(), _T("localtime() failed") );
+ wxCHECK_MSG( tm, Tm(), _T("wxLocaltime_r() failed") );
}
else
{
if ( time >= 0 )
#endif
{
- tm = gmtime(&time);
+ tm = wxGmtime_r(&time, &tmstruct);
// should never happen
- wxCHECK_MSG( tm, Tm(), _T("gmtime() failed") );
+ wxCHECK_MSG( tm, Tm(), _T("wxGmtime_r() failed") );
}
else
{
time_t timet = GetTicks();
if ( timet != (time_t)-1 )
{
- tm *tm = localtime(&timet);
+ struct tm tmstruct;
+ tm *tm = wxLocaltime_r(&timet, &tmstruct);
- wxCHECK_MSG( tm, -1, _T("localtime() failed") );
+ wxCHECK_MSG( tm, -1, _T("wxLocaltime_r() failed") );
return tm->tm_isdst;
}
if ( (time != (time_t)-1) && !wxStrstr(format, _T("%l")) )
{
// use strftime()
- tm *tm;
+ struct tm tmstruct;
+ struct tm *tm;
if ( tz.GetOffset() == -GetTimeZone() )
{
// we are working with local time
- tm = localtime(&time);
+ tm = wxLocaltime_r(&time, &tmstruct);
// should never happen
- wxCHECK_MSG( tm, wxEmptyString, _T("localtime() failed") );
+ wxCHECK_MSG( tm, wxEmptyString, _T("wxLocaltime_r() failed") );
}
else
{
if ( time >= 0 )
#endif
{
- tm = gmtime(&time);
+ tm = wxGmtime_r(&time, &tmstruct);
// should never happen
- wxCHECK_MSG( tm, wxEmptyString, _T("gmtime() failed") );
+ wxCHECK_MSG( tm, wxEmptyString, _T("wxGmtime_r() failed") );
}
else
{
// find two strings not occurring in format (this is surely
// not the optimal way of doing it... improvements welcome!)
- wxString fmt = format;
+ wxString fmt2 = format;
wxString replacement = (wxChar)-1;
- while ( fmt.Find(replacement) != wxNOT_FOUND )
+ while ( fmt2.Find(replacement) != wxNOT_FOUND )
{
replacement << (wxChar)-1;
}
wxString replacement2 = (wxChar)-2;
- while ( fmt.Find(replacement) != wxNOT_FOUND )
+ while ( fmt2.Find(replacement) != wxNOT_FOUND )
{
replacement << (wxChar)-2;
}
// replace all occurrences of year with it
- bool wasReplaced = fmt.Replace(strYear, replacement) > 0;
+ bool wasReplaced = fmt2.Replace(strYear, replacement) > 0;
if ( !wasReplaced )
- wasReplaced = fmt.Replace(strYear2, replacement2) > 0;
+ wasReplaced = fmt2.Replace(strYear2, replacement2) > 0;
// use strftime() to format the same date but in supported
// year
// the spec was correct, construct the date from the values we found
Set(day, mon, year, hour, min, sec);
- MakeFromTimezone(offset*SEC_PER_MIN);
+ MakeFromTimezone(TimeZone((wxDateTime_t)(offset*SEC_PER_MIN)));
return p;
}
for ( size_t n = 0; n < WXSIZEOF(literalDates); n++ )
{
- wxString date = wxGetTranslation(literalDates[n].str);
- size_t len = date.length();
+ const wxString dateStr = wxGetTranslation(literalDates[n].str);
+ size_t len = dateStr.length();
if ( wxStrlen(p) >= len )
{
wxString str(p, len);
- if ( str.CmpNoCase(date) == 0 )
+ if ( str.CmpNoCase(dateStr) == 0 )
{
// nothing can follow this, so stop here
p += len;
#include "wx/arrimpl.cpp"
-WX_DEFINE_OBJARRAY(wxDateTimeArray);
+WX_DEFINE_OBJARRAY(wxDateTimeArray)
static int wxCMPFUNC_CONV
wxDateTimeCompareFunc(wxDateTime **first, wxDateTime **second)
holidays.Clear();
- size_t count = ms_authorities.size();
- for ( size_t nAuth = 0; nAuth < count; nAuth++ )
+ const size_t countAuth = ms_authorities.size();
+ for ( size_t nAuth = 0; nAuth < countAuth; nAuth++ )
{
ms_authorities[nAuth]->DoGetHolidaysInRange(dtStart, dtEnd, hol);