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