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