No changes, just moved wxLocaltime_r() and wxGmtime_r() to wx/time.h.
[wxWidgets.git] / src / common / time.cpp
1 ///////////////////////////////////////////////////////////////////////////////
2 // Name: src/common/time.cpp
3 // Purpose: Implementation of time-related functions.
4 // Author: Vadim Zeitlin
5 // Created: 2011-11-26
6 // RCS-ID: $Id: wxhead.cpp,v 1.11 2010-04-22 12:44:51 zeitlin Exp $
7 // Copyright: (c) 2011 Vadim Zeitlin <vadim@wxwidgets.org>
8 // Licence: wxWindows licence
9 ///////////////////////////////////////////////////////////////////////////////
10
11 // ============================================================================
12 // declarations
13 // ============================================================================
14
15 // ----------------------------------------------------------------------------
16 // headers
17 // ----------------------------------------------------------------------------
18
19 // for compilers that support precompilation, includes "wx.h".
20 #include "wx/wxprec.h"
21
22 #ifdef __BORLANDC__
23 #pragma hdrstop
24 #endif
25
26 #include "wx/time.h"
27
28 #ifndef WX_PRECOMP
29 #ifdef __WXMSW__
30 #include "wx/msw/wrapwin.h"
31 #endif
32 #include "wx/intl.h"
33 #include "wx/log.h"
34 #endif
35
36 #ifndef WX_GMTOFF_IN_TM
37 // Define it for some systems which don't (always) use configure but are
38 // known to have tm_gmtoff field.
39 #if defined(__WXPALMOS__) || defined(__DARWIN__)
40 #define WX_GMTOFF_IN_TM
41 #endif
42 #endif
43
44 #if defined(__VISAGECPP__) && !defined(HAVE_FTIME)
45 #define HAVE_FTIME
46 # if __IBMCPP__ >= 400
47 # define ftime(x) _ftime(x)
48 # endif
49 #endif
50
51 #if defined(__MWERKS__) && defined(__WXMSW__)
52 # undef HAVE_FTIME
53 # undef HAVE_GETTIMEOFDAY
54 #endif
55
56 #ifndef __WXPALMOS5__
57 #ifndef __WXWINCE__
58 #include <time.h>
59 #else
60 #include "wx/msw/private.h"
61 #include "wx/msw/wince/time.h"
62 #endif
63 #endif // __WXPALMOS5__
64
65
66 #if !defined(__WXMAC__) && !defined(__WXWINCE__)
67 #include <sys/types.h> // for time_t
68 #endif
69
70 #if defined(HAVE_GETTIMEOFDAY)
71 #include <sys/time.h>
72 #include <unistd.h>
73 #elif defined(HAVE_FTIME)
74 #include <sys/timeb.h>
75 #endif
76
77 #ifdef __WXPALMOS__
78 #include <DateTime.h>
79 #include <TimeMgr.h>
80 #include <SystemMgr.h>
81 #endif
82
83 #if defined(__MWERKS__) && wxUSE_UNICODE
84 #include <wtime.h>
85 #endif
86
87 #if defined(__DJGPP__) || defined(__WINE__)
88 #include <sys/timeb.h>
89 #include <values.h>
90 #endif
91
92 namespace
93 {
94
95 const int MILLISECONDS_PER_SECOND = 1000;
96 const int MICROSECONDS_PER_MILLISECOND = 1000;
97 const int MICROSECONDS_PER_SECOND = 1000*1000;
98
99 } // anonymous namespace
100
101 // ============================================================================
102 // implementation
103 // ============================================================================
104
105 // NB: VC8 safe time functions could/should be used for wxMSW as well probably
106 #if defined(__WXWINCE__) && defined(__VISUALC8__)
107
108 struct tm *wxLocaltime_r(const time_t *t, struct tm* tm)
109 {
110 __time64_t t64 = *t;
111 return _localtime64_s(tm, &t64) == 0 ? tm : NULL;
112 }
113
114 struct tm *wxGmtime_r(const time_t* t, struct tm* tm)
115 {
116 __time64_t t64 = *t;
117 return _gmtime64_s(tm, &t64) == 0 ? tm : NULL;
118 }
119
120 #else // !wxWinCE with VC8
121
122 #if (!defined(HAVE_LOCALTIME_R) || !defined(HAVE_GMTIME_R)) && wxUSE_THREADS && !defined(__WINDOWS__)
123 static wxMutex timeLock;
124 #endif
125
126 #ifndef HAVE_LOCALTIME_R
127 struct tm *wxLocaltime_r(const time_t* ticks, struct tm* temp)
128 {
129 #if wxUSE_THREADS && !defined(__WINDOWS__)
130 // No need to waste time with a mutex on windows since it's using
131 // thread local storage for localtime anyway.
132 wxMutexLocker locker(timeLock);
133 #endif
134
135 // Borland CRT crashes when passed 0 ticks for some reason, see SF bug 1704438
136 #ifdef __BORLANDC__
137 if ( !*ticks )
138 return NULL;
139 #endif
140
141 const tm * const t = localtime(ticks);
142 if ( !t )
143 return NULL;
144
145 memcpy(temp, t, sizeof(struct tm));
146 return temp;
147 }
148 #endif // !HAVE_LOCALTIME_R
149
150 #ifndef HAVE_GMTIME_R
151 struct tm *wxGmtime_r(const time_t* ticks, struct tm* temp)
152 {
153 #if wxUSE_THREADS && !defined(__WINDOWS__)
154 // No need to waste time with a mutex on windows since it's
155 // using thread local storage for gmtime anyway.
156 wxMutexLocker locker(timeLock);
157 #endif
158
159 #ifdef __BORLANDC__
160 if ( !*ticks )
161 return NULL;
162 #endif
163
164 const tm * const t = gmtime(ticks);
165 if ( !t )
166 return NULL;
167
168 memcpy(temp, gmtime(ticks), sizeof(struct tm));
169 return temp;
170 }
171 #endif // !HAVE_GMTIME_R
172
173 #endif // wxWinCE with VC8/other platforms
174
175 // returns the time zone in the C sense, i.e. the difference UTC - local
176 // (in seconds)
177 int wxGetTimeZone()
178 {
179 #ifdef WX_GMTOFF_IN_TM
180 // set to true when the timezone is set
181 static bool s_timezoneSet = false;
182 static long gmtoffset = LONG_MAX; // invalid timezone
183
184 // ensure that the timezone variable is set by calling wxLocaltime_r
185 if ( !s_timezoneSet )
186 {
187 // just call wxLocaltime_r() instead of figuring out whether this
188 // system supports tzset(), _tzset() or something else
189 time_t t = time(NULL);
190 struct tm tm;
191
192 wxLocaltime_r(&t, &tm);
193 s_timezoneSet = true;
194
195 // note that GMT offset is the opposite of time zone and so to return
196 // consistent results in both WX_GMTOFF_IN_TM and !WX_GMTOFF_IN_TM
197 // cases we have to negate it
198 gmtoffset = -tm.tm_gmtoff;
199
200 // this function is supposed to return the same value whether DST is
201 // enabled or not, so we need to use an additional offset if DST is on
202 // as tm_gmtoff already does include it
203 if ( tm.tm_isdst )
204 gmtoffset += 3600;
205 }
206 return (int)gmtoffset;
207 #elif defined(__DJGPP__) || defined(__WINE__)
208 struct timeb tb;
209 ftime(&tb);
210 return tb.timezone*60;
211 #elif defined(__VISUALC__)
212 // We must initialize the time zone information before using it (this will
213 // be done only once internally).
214 _tzset();
215
216 // Starting with VC++ 8 timezone variable is deprecated and is not even
217 // available in some standard library version so use the new function for
218 // accessing it instead.
219 #if wxCHECK_VISUALC_VERSION(8)
220 long t;
221 _get_timezone(&t);
222 return t;
223 #else // VC++ < 8
224 return timezone;
225 #endif
226 #elif defined(WX_TIMEZONE) // If WX_TIMEZONE was defined by configure, use it.
227 return WX_TIMEZONE;
228 #elif defined(__BORLANDC__) || defined(__MINGW32__) || defined(__VISAGECPP__)
229 return _timezone;
230 #elif defined(__MWERKS__)
231 return 28800;
232 #else // unknown platform -- assume it has timezone
233 return timezone;
234 #endif // WX_GMTOFF_IN_TM/!WX_GMTOFF_IN_TM
235 }
236
237 // Get local time as seconds since 00:00:00, Jan 1st 1970
238 long wxGetLocalTime()
239 {
240 struct tm tm;
241 time_t t0, t1;
242
243 // This cannot be made static because mktime can overwrite it.
244 //
245 memset(&tm, 0, sizeof(tm));
246 tm.tm_year = 70;
247 tm.tm_mon = 0;
248 tm.tm_mday = 5; // not Jan 1st 1970 due to mktime 'feature'
249 tm.tm_hour = 0;
250 tm.tm_min = 0;
251 tm.tm_sec = 0;
252 tm.tm_isdst = -1; // let mktime guess
253
254 // Note that mktime assumes that the struct tm contains local time.
255 //
256 t1 = time(&t1); // now
257 t0 = mktime(&tm); // origin
258
259 // Return the difference in seconds.
260 //
261 if (( t0 != (time_t)-1 ) && ( t1 != (time_t)-1 ))
262 return (long)difftime(t1, t0) + (60 * 60 * 24 * 4);
263
264 wxLogSysError(_("Failed to get the local system time"));
265 return -1;
266 }
267
268 // Get UTC time as seconds since 00:00:00, Jan 1st 1970
269 long wxGetUTCTime()
270 {
271 return (long)time(NULL);
272 }
273
274 #if wxUSE_LONGLONG
275
276 wxLongLong wxGetUTCTimeUSec()
277 {
278 #if defined(__WXMSW__)
279 FILETIME ft;
280 ::GetSystemTimeAsFileTime(&ft);
281
282 // FILETIME is in 100ns or 0.1us since 1601-01-01, transform to us since
283 // 1970-01-01.
284 wxLongLong t(ft.dwHighDateTime, ft.dwLowDateTime);
285 t /= 10;
286 t -= wxLL(11644473600000000); // Unix - Windows epochs difference in us.
287 return t;
288 #else // non-MSW
289
290 #ifdef HAVE_GETTIMEOFDAY
291 timeval tv;
292 if ( wxGetTimeOfDay(&tv) != -1 )
293 {
294 wxLongLong val(tv.tv_sec);
295 val *= MICROSECONDS_PER_SECOND;
296 val += tv.tv_usec;
297 return val;
298 }
299 #endif // HAVE_GETTIMEOFDAY
300
301 // Fall back to lesser precision function.
302 return wxGetUTCTimeMillis()*MICROSECONDS_PER_MILLISECOND;
303 #endif // MSW/!MSW
304 }
305
306 // Get local time as milliseconds since 00:00:00, Jan 1st 1970
307 wxLongLong wxGetUTCTimeMillis()
308 {
309 wxLongLong val = MILLISECONDS_PER_SECOND;
310
311 // If possible, use a function which avoids conversions from
312 // broken-up time structures to milliseconds
313 #if defined(__WXPALMOS__)
314 DateTimeType thenst;
315 thenst.second = 0;
316 thenst.minute = 0;
317 thenst.hour = 0;
318 thenst.day = 1;
319 thenst.month = 1;
320 thenst.year = 1970;
321 thenst.weekDay = 5;
322 uint32_t now = TimGetSeconds();
323 uint32_t then = TimDateTimeToSeconds (&thenst);
324 return SysTimeToMilliSecs(SysTimeInSecs(now - then));
325 #elif defined(__WXMSW__)
326 FILETIME ft;
327 ::GetSystemTimeAsFileTime(&ft);
328
329 // FILETIME is expressed in 100ns (or 0.1us) units since 1601-01-01,
330 // transform them to ms since 1970-01-01.
331 wxLongLong t(ft.dwHighDateTime, ft.dwLowDateTime);
332 t /= 10000;
333 t -= wxLL(11644473600000); // Unix - Windows epochs difference in ms.
334 return t;
335 #elif defined(HAVE_GETTIMEOFDAY)
336 struct timeval tp;
337 if ( wxGetTimeOfDay(&tp) != -1 )
338 {
339 val *= tp.tv_sec;
340 return (val + (tp.tv_usec / MICROSECONDS_PER_MILLISECOND));
341 }
342 else
343 {
344 wxLogError(_("wxGetTimeOfDay failed."));
345 return 0;
346 }
347 #elif defined(HAVE_FTIME)
348 struct timeb tp;
349
350 // ftime() is void and not int in some mingw32 headers, so don't
351 // test the return code (well, it shouldn't fail anyhow...)
352 (void)::ftime(&tp);
353 val *= tp.time;
354 return (val + tp.millitm);
355 #else // no gettimeofday() nor ftime()
356 // If your platform/compiler does not support ms resolution please
357 // do NOT just shut off these warnings, drop me a line instead at
358 // <guille@iies.es>
359
360 #if defined(__VISUALC__) || defined (__WATCOMC__)
361 #pragma message("wxStopWatch will be up to second resolution!")
362 #elif defined(__BORLANDC__)
363 #pragma message "wxStopWatch will be up to second resolution!"
364 #else
365 #warning "wxStopWatch will be up to second resolution!"
366 #endif // compiler
367
368 val *= wxGetUTCTime();
369 return val;
370 #endif // time functions
371 }
372
373 wxLongLong wxGetLocalTimeMillis()
374 {
375 return wxGetUTCTimeMillis() - wxGetTimeZone()*MILLISECONDS_PER_SECOND;
376 }
377
378 #else // !wxUSE_LONGLONG
379
380 double wxGetLocalTimeMillis(void)
381 {
382 return (double(clock()) / double(CLOCKS_PER_SEC)) * 1000.0;
383 }
384
385 #endif // wxUSE_LONGLONG/!wxUSE_LONGLONG