+// 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
+
+#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
+