// Licence: wxWindows licence
///////////////////////////////////////////////////////////////////////////////
-// TODO: for $DEITY sake, someone please fix the #ifdef __WXWINCE__ everywhere,
-// the proper way to do it is to implement (subset of) wxStrftime() for
-// CE instead of this horror!!
-
/*
* Implementation notes:
*
#if !defined(wxUSE_DATETIME) || wxUSE_DATETIME
#ifndef WX_PRECOMP
+ #ifdef __WXMSW__
+ #include "wx/msw/wrapwin.h"
+ #endif
#include "wx/string.h"
#include "wx/log.h"
#include "wx/intl.h"
#include "wx/stopwatch.h" // for wxGetLocalTimeMillis()
+ #include "wx/module.h"
+ #include "wx/crt.h"
#endif // WX_PRECOMP
#include "wx/thread.h"
#include "wx/tokenzr.h"
-#include "wx/module.h"
#include <ctype.h>
#ifdef __WINDOWS__
- #include "wx/msw/wrapwin.h"
#include <winnls.h>
#ifndef __WXWINCE__
#include <locale.h>
#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
#define WX_TIMEZONE wxGetTimeZone()
#elif defined(__DARWIN__)
#define WX_GMTOFF_IN_TM
+ #elif defined(__WXWINCE__) && defined(__VISUALC8__)
+ #define WX_TIMEZONE _timezone
#else // unknown platform - try timezone
#define WX_TIMEZONE timezone
#endif
#endif // !WX_TIMEZONE && !WX_GMTOFF_IN_TM
+// everyone has strftime except Win CE unless VC8 is used
+#if !defined(__WXWINCE__) || defined(__VISUALC8__)
+ #define HAVE_STRFTIME
+#endif
+
+// NB: VC8 safe time functions could/should be used for wxMSW as well probably
+#if defined(__WXWINCE__) && defined(__VISUALC8__)
+
+struct tm *wxLocaltime_r(const time_t *t, struct tm* tm)
+{
+ __time64_t t64 = *t;
+ return _localtime64_s(tm, &t64) == 0 ? tm : NULL;
+}
+
+struct tm *wxGmtime_r(const time_t* t, struct tm* tm)
+{
+ __time64_t t64 = *t;
+ return _gmtime64_s(tm, &t64) == 0 ? tm : NULL;
+}
+
+#else // !wxWinCE with VC8
+
#if (!defined(HAVE_LOCALTIME_R) || !defined(HAVE_GMTIME_R)) && wxUSE_THREADS && !defined(__WINDOWS__)
static wxMutex timeLock;
#endif
// thread local storage for localtime anyway.
wxMutexLocker locker(timeLock);
#endif
- memcpy(temp, localtime(ticks), sizeof(struct tm));
+
+ // Borland CRT crashes when passed 0 ticks for some reason, see SF bug 1704438
+#ifdef __BORLANDC__
+ if ( !*ticks )
+ return NULL;
+#endif
+
+ const tm * const t = localtime(ticks);
+ if ( !t )
+ return NULL;
+
+ memcpy(temp, t, sizeof(struct tm));
return temp;
}
-#endif
+#endif // !HAVE_LOCALTIME_R
#ifndef HAVE_GMTIME_R
struct tm *wxGmtime_r(const time_t* ticks, struct tm* temp)
// using thread local storage for gmtime anyway.
wxMutexLocker locker(timeLock);
#endif
+
+#ifdef __BORLANDC__
+ if ( !*ticks )
+ return NULL;
+#endif
+
+ const tm * const t = gmtime(ticks);
+ if ( !t )
+ return NULL;
+
memcpy(temp, gmtime(ticks), sizeof(struct tm));
return temp;
}
-#endif
+#endif // !HAVE_GMTIME_R
+
+#endif // wxWinCE with VC8/other platforms
// ----------------------------------------------------------------------------
// macros
- JDN_OFFSET;
}
-#ifndef __WXWINCE__
+#ifdef HAVE_STRFTIME
+
// this function is a wrapper around strftime(3) adding error checking
-static wxString CallStrftime(const wxChar *format, const tm* tm)
+static wxString CallStrftime(const wxString& format, const tm* tm)
{
wxChar buf[4096];
// Create temp wxString here to work around mingw/cygwin bug 1046059
s = buf;
return s;
}
-#endif
+
+#endif // HAVE_STRFTIME
#ifdef HAVE_STRPTIME
// compute the week day from day/month/year: we use the dumbest algorithm
// possible: just compute our JDN and then use the (simple to derive)
// formula: weekday = (JDN + 1.5) % 7
- wday = (wxDateTime::wxDateTime_t)((wxDateTime::WeekDay)(GetTruncatedJDN(mday, mon, year) + 2) % 7);
+ wday = (wxDateTime::wxDateTime_t)((GetTruncatedJDN(mday, mon, year) + 2) % 7);
}
void wxDateTime::Tm::AddMonths(int monDiff)
case wxDateTime::GMT10:
case wxDateTime::GMT11:
case wxDateTime::GMT12:
+ case wxDateTime::GMT13:
m_offset = 3600*(tz - wxDateTime::GMT0);
break;
wxDateTime::NameFlags flags)
{
wxCHECK_MSG( month != Inv_Month, wxEmptyString, _T("invalid month") );
-#ifndef __WXWINCE__
+#ifdef HAVE_STRFTIME
// notice that we must set all the fields to avoid confusing libc (GNU one
// gets confused to a crash if we don't do this)
tm tm;
tm.tm_mon = month;
return CallStrftime(flags == Name_Abbr ? _T("%b") : _T("%B"), &tm);
-#else
+#else // !HAVE_STRFTIME
wxString ret;
switch(month)
{
break;
}
return ret;
-#endif
+#endif // HAVE_STRFTIME/!HAVE_STRFTIME
}
/* static */
wxDateTime::NameFlags flags)
{
wxCHECK_MSG( wday != Inv_WeekDay, wxEmptyString, _T("invalid weekday") );
-#ifndef __WXWINCE__
+#ifdef HAVE_STRFTIME
// take some arbitrary Sunday (but notice that the day should be such that
// after adding wday to it below we still have a valid date, e.g. don't
// take 28 here!)
// ... and call strftime()
return CallStrftime(flags == Name_Abbr ? _T("%a") : _T("%A"), &tm);
-#else
+#else // !HAVE_STRFTIME
wxString ret;
switch(wday)
{
break;
}
return ret;
-
-#endif
+#endif // HAVE_STRFTIME/!HAVE_STRFTIME
}
/* static */
ms_country = USA;
}
}
-#else
+#else // __WXWINCE__
ms_country = USA;
-#endif
+#endif // !__WXWINCE__/__WXWINCE__
return ms_country;
}
return *this;
}
+wxDateTime wxDateTime::GetDateOnly() const
+{
+ Tm tm = GetTm();
+ tm.msec =
+ tm.sec =
+ tm.min =
+ tm.hour = 0;
+ return wxDateTime(tm);
+}
+
// ----------------------------------------------------------------------------
// DOS Date and Time Format functions
// ----------------------------------------------------------------------------
// wxDateTime to/from text representations
// ----------------------------------------------------------------------------
-wxString wxDateTime::Format(const wxChar *format, const TimeZone& tz) const
+wxString wxDateTime::Format(const wxString& format, const TimeZone& tz) const
{
- wxCHECK_MSG( format, wxEmptyString, _T("NULL format in wxDateTime::Format") );
+ wxCHECK_MSG( !format.empty(), wxEmptyString,
+ _T("NULL format in wxDateTime::Format") );
// we have to use our own implementation if the date is out of range of
// strftime() or if we use non standard specificators
+#ifdef HAVE_STRFTIME
time_t time = GetTicks();
+
if ( (time != (time_t)-1) && !wxStrstr(format, _T("%l")) )
{
// use strftime()
tm = (struct tm *)NULL;
}
}
-#ifndef __WXWINCE__
- //Windows CE doesn't support strftime or wcsftime, so we use the generic implementation
+
if ( tm )
{
return CallStrftime(format, tm);
}
-#endif
- //else: use generic code below
}
+ //else: use generic code below
+#endif // HAVE_STRFTIME
// we only parse ANSI C format specifications here, no POSIX 2
// complications, no GNU extensions but we do add support for a "%l" format
tmTimeOnly.tm_isdst = 0; // no DST, we adjust for tz ourselves
wxString tmp, res, fmt;
- for ( const wxChar *p = format; *p; p++ )
+ for ( wxString::const_iterator p = format.begin(); p != format.end(); ++p )
{
if ( *p != _T('%') )
{
}
// set the default format
- switch ( *++p )
+ switch ( (*++p).GetValue() )
{
case _T('Y'): // year has 4 digits
fmt = _T("%04d");
restart = false;
// start of the format specification
- switch ( *p )
+ switch ( (*p).GetValue() )
{
case _T('a'): // a weekday name
case _T('A'):
case _T('c'): // locale default date and time representation
case _T('x'): // locale default date representation
-#ifndef __WXWINCE__
+#ifdef HAVE_STRFTIME
//
// the problem: there is no way to know what do these format
// specifications correspond to for the current locale.
// replace all occurrences of year with it
bool wasReplaced = fmt2.Replace(strYear, replacement) > 0;
// evaluation order ensures we always attempt the replacement.
- wasReplaced = (fmt2.Replace(strYear2, replacement2) > 0) | wasReplaced ;
+ wasReplaced = (fmt2.Replace(strYear2, replacement2) > 0) || wasReplaced;
// use strftime() to format the same date but in supported
// year
res += str;
}
-#else
- //Use "%m/%d/%y %H:%M:%S" format instead
+#else // !HAVE_STRFTIME
+ // Use "%m/%d/%y %H:%M:%S" format instead
res += wxString::Format(wxT("%02d/%02d/%04d %02d:%02d:%02d"),
tm.mon+1,tm.mday, tm.year, tm.hour, tm.min, tm.sec);
-#endif
+#endif // HAVE_STRFTIME/!HAVE_STRFTIME
break;
case _T('d'): // day of a month (01-31)
break;
case _T('p'): // AM or PM string
-#ifndef __WXWINCE__
+#ifdef HAVE_STRFTIME
res += CallStrftime(_T("%p"), &tmTimeOnly);
-#else
+#else // !HAVE_STRFTIME
res += (tmTimeOnly.tm_hour > 12) ? wxT("pm") : wxT("am");
-#endif
+#endif // HAVE_STRFTIME/!HAVE_STRFTIME
break;
case _T('S'): // second as a decimal number (00-61)
case _T('X'): // locale default time representation
// just use strftime() to format the time for us
-#ifndef __WXWINCE__
+#ifdef HAVE_STRFTIME
res += CallStrftime(_T("%X"), &tmTimeOnly);
-#else
+#else // !HAVE_STRFTIME
res += wxString::Format(wxT("%02d:%02d:%02d"),tm.hour, tm.min, tm.sec);
-#endif
+#endif // HAVE_STRFTIME/!HAVE_STRFTIME
break;
case _T('y'): // year without century (00-99)
break;
case _T('Z'): // timezone name
-#ifndef __WXWINCE__
+#ifdef HAVE_STRFTIME
res += CallStrftime(_T("%Z"), &tmTimeOnly);
#endif
break;
#endif // __WINDOWS__
const wxChar *wxDateTime::ParseFormat(const wxChar *date,
- const wxChar *format,
+ const wxString& format,
const wxDateTime& dateDef)
{
- wxCHECK_MSG( date && format, (wxChar *)NULL,
+ wxCHECK_MSG( date && !format.empty(), (wxChar *)NULL,
_T("NULL pointer in wxDateTime::ParseFormat()") );
wxString str;
int year = 0;
const wxChar *input = date;
- for ( const wxChar *fmt = format; *fmt; fmt++ )
+ for ( wxString::const_iterator fmt = format.begin(); fmt != format.end(); ++fmt )
{
if ( *fmt != _T('%') )
{
// the default widths for the various fields
if ( !width )
{
- switch ( *fmt )
+ switch ( (*fmt).GetValue() )
{
case _T('Y'): // year has 4 digits
width = 4;
}
// then the format itself
- switch ( *fmt )
+ switch ( (*fmt).GetValue() )
{
case _T('a'): // a weekday name
case _T('A'):
// And, to be better than MFC :-), we also have
// %E number of wEeks
// %l milliseconds (000 - 999)
-wxString wxTimeSpan::Format(const wxChar *format) const
+wxString wxTimeSpan::Format(const wxString& format) const
{
- wxCHECK_MSG( format, wxEmptyString, _T("NULL format in wxTimeSpan::Format") );
+ wxCHECK_MSG( !format.empty(), wxEmptyString,
+ _T("NULL format in wxTimeSpan::Format") );
wxString str;
- str.Alloc(wxStrlen(format));
+ str.Alloc(format.length());
// Suppose we have wxTimeSpan ts(1 /* hour */, 2 /* min */, 3 /* sec */)
//
// we remember the most important unit found so far
TimeSpanPart partBiggest = Part_MSec;
- for ( const wxChar *pch = format; *pch; pch++ )
+ for ( wxString::const_iterator pch = format.begin(); pch != format.end(); ++pch )
{
wxChar ch = *pch;