X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/59068d79f7fcc94d320cf41ce1ed7f0a8851b125..13b4df952c77383f50696e51fcbaa2d8bbd3b3b9:/src/common/time.cpp diff --git a/src/common/time.cpp b/src/common/time.cpp index d3e1bd6193..03df19ec62 100644 --- a/src/common/time.cpp +++ b/src/common/time.cpp @@ -25,6 +25,14 @@ #include "wx/time.h" +#ifndef WX_PRECOMP + #ifdef __WXMSW__ + #include "wx/msw/wrapwin.h" + #endif + #include "wx/intl.h" + #include "wx/log.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. @@ -33,10 +41,137 @@ #endif #endif +#if defined(__VISAGECPP__) && !defined(HAVE_FTIME) + #define HAVE_FTIME +# if __IBMCPP__ >= 400 + # define ftime(x) _ftime(x) +# endif +#endif + +#if defined(__MWERKS__) && defined(__WXMSW__) +# undef HAVE_FTIME +# undef HAVE_GETTIMEOFDAY +#endif + +#ifndef __WXPALMOS5__ +#ifndef __WXWINCE__ +#include +#else +#include "wx/msw/private.h" +#include "wx/msw/wince/time.h" +#endif +#endif // __WXPALMOS5__ + + +#if !defined(__WXMAC__) && !defined(__WXWINCE__) + #include // for time_t +#endif + +#if defined(HAVE_GETTIMEOFDAY) + #include + #include +#elif defined(HAVE_FTIME) + #include +#endif + +#ifdef __WXPALMOS__ + #include + #include + #include +#endif + +#if defined(__MWERKS__) && wxUSE_UNICODE + #include +#endif + +#if defined(__DJGPP__) || defined(__WINE__) + #include + #include +#endif + +namespace +{ + +const int MILLISECONDS_PER_SECOND = 1000; +const int MICROSECONDS_PER_MILLISECOND = 1000; +const int MICROSECONDS_PER_SECOND = 1000*1000; + +} // anonymous namespace + // ============================================================================ // implementation // ============================================================================ +// 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 + +#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 + + // 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 // !HAVE_LOCALTIME_R + +#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 + +#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 // !HAVE_GMTIME_R + +#endif // wxWinCE with VC8/other platforms + // returns the time zone in the C sense, i.e. the difference UTC - local // (in seconds) int wxGetTimeZone() @@ -98,3 +233,153 @@ int wxGetTimeZone() return timezone; #endif // WX_GMTOFF_IN_TM/!WX_GMTOFF_IN_TM } + +// Get local time as seconds since 00:00:00, Jan 1st 1970 +long wxGetLocalTime() +{ + struct tm tm; + time_t t0, t1; + + // This cannot be made static because mktime can overwrite it. + // + memset(&tm, 0, sizeof(tm)); + tm.tm_year = 70; + tm.tm_mon = 0; + tm.tm_mday = 5; // not Jan 1st 1970 due to mktime 'feature' + tm.tm_hour = 0; + tm.tm_min = 0; + tm.tm_sec = 0; + tm.tm_isdst = -1; // let mktime guess + + // Note that mktime assumes that the struct tm contains local time. + // + t1 = time(&t1); // now + t0 = mktime(&tm); // origin + + // Return the difference in seconds. + // + if (( t0 != (time_t)-1 ) && ( t1 != (time_t)-1 )) + return (long)difftime(t1, t0) + (60 * 60 * 24 * 4); + + wxLogSysError(_("Failed to get the local system time")); + return -1; +} + +// Get UTC time as seconds since 00:00:00, Jan 1st 1970 +long wxGetUTCTime() +{ + return (long)time(NULL); +} + +#if wxUSE_LONGLONG + +wxLongLong wxGetUTCTimeUSec() +{ +#if defined(__WXMSW__) + FILETIME ft; + ::GetSystemTimeAsFileTime(&ft); + + // FILETIME is in 100ns or 0.1us since 1601-01-01, transform to us since + // 1970-01-01. + wxLongLong t(ft.dwHighDateTime, ft.dwLowDateTime); + t /= 10; + t -= wxLL(11644473600000000); // Unix - Windows epochs difference in us. + return t; +#else // non-MSW + +#ifdef HAVE_GETTIMEOFDAY + timeval tv; + if ( wxGetTimeOfDay(&tv) != -1 ) + { + wxLongLong val(tv.tv_sec); + val *= MICROSECONDS_PER_SECOND; + val += tv.tv_usec; + return val; + } +#endif // HAVE_GETTIMEOFDAY + + // Fall back to lesser precision function. + return wxGetUTCTimeMillis()*MICROSECONDS_PER_MILLISECOND; +#endif // MSW/!MSW +} + +// Get local time as milliseconds since 00:00:00, Jan 1st 1970 +wxLongLong wxGetUTCTimeMillis() +{ + wxLongLong val = MILLISECONDS_PER_SECOND; + + // If possible, use a function which avoids conversions from + // broken-up time structures to milliseconds +#if defined(__WXPALMOS__) + DateTimeType thenst; + thenst.second = 0; + thenst.minute = 0; + thenst.hour = 0; + thenst.day = 1; + thenst.month = 1; + thenst.year = 1970; + thenst.weekDay = 5; + uint32_t now = TimGetSeconds(); + uint32_t then = TimDateTimeToSeconds (&thenst); + return SysTimeToMilliSecs(SysTimeInSecs(now - then)); +#elif defined(__WXMSW__) + FILETIME ft; + ::GetSystemTimeAsFileTime(&ft); + + // FILETIME is expressed in 100ns (or 0.1us) units since 1601-01-01, + // transform them to ms since 1970-01-01. + wxLongLong t(ft.dwHighDateTime, ft.dwLowDateTime); + t /= 10000; + t -= wxLL(11644473600000); // Unix - Windows epochs difference in ms. + return t; +#elif defined(HAVE_GETTIMEOFDAY) + struct timeval tp; + if ( wxGetTimeOfDay(&tp) != -1 ) + { + val *= tp.tv_sec; + return (val + (tp.tv_usec / MICROSECONDS_PER_MILLISECOND)); + } + else + { + wxLogError(_("wxGetTimeOfDay failed.")); + return 0; + } +#elif defined(HAVE_FTIME) + struct timeb tp; + + // ftime() is void and not int in some mingw32 headers, so don't + // test the return code (well, it shouldn't fail anyhow...) + (void)::ftime(&tp); + val *= tp.time; + return (val + tp.millitm); +#else // no gettimeofday() nor ftime() + // If your platform/compiler does not support ms resolution please + // do NOT just shut off these warnings, drop me a line instead at + // + + #if defined(__VISUALC__) || defined (__WATCOMC__) + #pragma message("wxStopWatch will be up to second resolution!") + #elif defined(__BORLANDC__) + #pragma message "wxStopWatch will be up to second resolution!" + #else + #warning "wxStopWatch will be up to second resolution!" + #endif // compiler + + val *= wxGetUTCTime(); + return val; +#endif // time functions +} + +wxLongLong wxGetLocalTimeMillis() +{ + return wxGetUTCTimeMillis() - wxGetTimeZone()*MILLISECONDS_PER_SECOND; +} + +#else // !wxUSE_LONGLONG + +double wxGetLocalTimeMillis(void) +{ + return (double(clock()) / double(CLOCKS_PER_SEC)) * 1000.0; +} + +#endif // wxUSE_LONGLONG/!wxUSE_LONGLONG