]> git.saurik.com Git - wxWidgets.git/blame - src/common/time.cpp
Fix assert when editing an item in multi-selection wxTreeCtrl.
[wxWidgets.git] / src / common / time.cpp
CommitLineData
59068d79
VZ
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
173a5ddc
VZ
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
59068d79
VZ
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.
bd362275 39 #if defined(__DARWIN__)
59068d79
VZ
40 #define WX_GMTOFF_IN_TM
41 #endif
42#endif
43
173a5ddc
VZ
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
173a5ddc
VZ
56#ifndef __WXWINCE__
57#include <time.h>
58#else
59#include "wx/msw/private.h"
60#include "wx/msw/wince/time.h"
61#endif
173a5ddc
VZ
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
fb7ce3e8
VZ
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
173a5ddc
VZ
84namespace
85{
86
87const int MILLISECONDS_PER_SECOND = 1000;
88const int MICROSECONDS_PER_MILLISECOND = 1000;
89const int MICROSECONDS_PER_SECOND = 1000*1000;
90
91} // anonymous namespace
92
59068d79
VZ
93// ============================================================================
94// implementation
95// ============================================================================
96
fb7ce3e8
VZ
97// NB: VC8 safe time functions could/should be used for wxMSW as well probably
98#if defined(__WXWINCE__) && defined(__VISUALC8__)
99
100struct 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
106struct 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__)
115static wxMutex timeLock;
116#endif
117
118#ifndef HAVE_LOCALTIME_R
119struct 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
143struct 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
59068d79
VZ
167// returns the time zone in the C sense, i.e. the difference UTC - local
168// (in seconds)
169int 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
8c7114c2
VZ
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
59068d79 234}
173a5ddc
VZ
235
236// Get local time as seconds since 00:00:00, Jan 1st 1970
237long 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
268long wxGetUTCTime()
269{
270 return (long)time(NULL);
271}
272
273#if wxUSE_LONGLONG
274
275wxLongLong wxGetUTCTimeUSec()
276{
277#if defined(__WXMSW__)
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
306wxLongLong 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
bd362275 312#if defined(__WXMSW__)
173a5ddc
VZ
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
360wxLongLong wxGetLocalTimeMillis()
361{
362 return wxGetUTCTimeMillis() - wxGetTimeZone()*MILLISECONDS_PER_SECOND;
363}
364
365#else // !wxUSE_LONGLONG
366
367double wxGetLocalTimeMillis(void)
368{
369 return (double(clock()) / double(CLOCKS_PER_SEC)) * 1000.0;
370}
371
372#endif // wxUSE_LONGLONG/!wxUSE_LONGLONG