os/persistentdata/persistentstorage/sqlite3api/TEST/TCL/tcldistribution/unix/tclUnixTime.c
Update contrib.
4 * Contains Unix specific versions of Tcl functions that
5 * obtain time values from the operating system.
7 * Copyright (c) 1995 Sun Microsystems, Inc.
8 * Portions Copyright (c) 2007-2008 Nokia Corporation and/or its subsidiaries. All rights reserved.
10 * See the file "license.terms" for information on usage and redistribution
11 * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
13 * RCS: @(#) $Id: tclUnixTime.c,v 1.15.2.6 2007/04/21 19:52:15 kennykb Exp $
19 #define TM_YEAR_BASE 1900
20 #define IsLeapYear(x) ((x % 4 == 0) && (x % 100 != 0 || x % 400 == 0))
23 * TclpGetDate is coded to return a pointer to a 'struct tm'. For
24 * thread safety, this structure must be in thread-specific data.
25 * The 'tmKey' variable is the key to this buffer.
28 static Tcl_ThreadDataKey tmKey;
29 typedef struct ThreadSpecificData {
31 struct tm localtime_buf;
35 * If we fall back on the thread-unsafe versions of gmtime and localtime,
36 * use this mutex to try to protect them.
39 TCL_DECLARE_MUTEX(tmMutex)
41 static char* lastTZ = NULL; /* Holds the last setting of the
42 * TZ environment variable, or an
43 * empty string if the variable was
46 /* Static functions declared in this file */
48 static void SetTZIfNecessary _ANSI_ARGS_((void));
49 static void CleanupMemory _ANSI_ARGS_((ClientData));
52 *-----------------------------------------------------------------------------
56 * This procedure returns the number of seconds from the epoch. On
57 * most Unix systems the epoch is Midnight Jan 1, 1970 GMT.
60 * Number of seconds from the epoch.
65 *-----------------------------------------------------------------------------
71 return time((time_t *) NULL);
75 *-----------------------------------------------------------------------------
79 * This procedure returns a value that represents the highest resolution
80 * clock available on the system. There are no garantees on what the
81 * resolution will be. In Tcl we will call this value a "click". The
82 * start time is also system dependant.
85 * Number of clicks from some start time.
90 *-----------------------------------------------------------------------------
105 now = (unsigned long) times(&dummy);
107 gettimeofday(&date, &tz);
108 now = date.tv_sec*1000000 + date.tv_usec;
115 *----------------------------------------------------------------------
119 * Determines the current timezone. The method varies wildly
120 * between different platform implementations, so its hidden in
124 * The return value is the local time zone, measured in
125 * minutes away from GMT (-ve for east, +ve for west).
130 *----------------------------------------------------------------------
134 TclpGetTimeZone (currentTime)
135 Tcl_WideInt currentTime;
138 * We prefer first to use the time zone in "struct tm" if the
139 * structure contains such a member. Following that, we try
140 * to locate the external 'timezone' variable and use its value.
141 * If both of those methods fail, we attempt to convert a known
142 * time to local time and use the difference from UTC as the local
143 * time zone. In all cases, we need to undo any Daylight Saving Time
147 #if defined(HAVE_TM_TZADJ)
148 # define TCL_GOT_TIMEZONE
150 /* Struct tm contains tm_tzadj - that value may be used. */
152 time_t curTime = (time_t) currentTime;
153 struct tm *timeDataPtr = TclpLocaltime((TclpTime_t) &curTime);
156 timeZone = timeDataPtr->tm_tzadj / 60;
157 if (timeDataPtr->tm_isdst) {
165 #if defined(HAVE_TM_GMTOFF) && !defined (TCL_GOT_TIMEZONE)
166 # define TCL_GOT_TIMEZONE
168 /* Struct tm contains tm_gmtoff - that value may be used. */
170 time_t curTime = (time_t) currentTime;
171 struct tm *timeDataPtr = TclpLocaltime((TclpTime_t) &curTime);
174 timeZone = -(timeDataPtr->tm_gmtoff / 60);
175 if (timeDataPtr->tm_isdst) {
183 #if defined(HAVE_TIMEZONE_VAR) && !defined(TCL_GOT_TIMEZONE) && !defined(USE_DELTA_FOR_TZ)
184 # define TCL_GOT_TIMEZONE
188 /* The 'timezone' external var is present and may be used. */
193 * Note: this is not a typo in "timezone" below! See tzset
194 * documentation for details.
197 timeZone = timezone / 60;
202 #if !defined(TCL_GOT_TIMEZONE)
203 #define TCL_GOT_TIMEZONE 1
205 * Fallback - determine time zone with a known reference time.
211 tt = 849268800L; /* 1996-11-29 12:00:00 GMT */
212 stm = TclpLocaltime((TclpTime_t) &tt); /* eg 1996-11-29 6:00:00 CST6CDT */
213 /* The calculation below assumes a max of +12 or -12 hours from GMT */
214 timeZone = (12 - stm->tm_hour)*60 + (0 - stm->tm_min);
215 if ( stm -> tm_isdst ) {
218 return timeZone; /* eg +360 for CST6CDT */
221 #ifndef TCL_GOT_TIMEZONE
223 * Cause compile error, we don't know how to get timezone.
226 #error autoconf did not figure out how to determine the timezone.
233 *----------------------------------------------------------------------
237 * Gets the current system time in seconds and microseconds
238 * since the beginning of the epoch: 00:00 UCT, January 1, 1970.
241 * Returns the current time in timePtr.
246 *----------------------------------------------------------------------
251 Tcl_Time *timePtr; /* Location to store time information. */
256 (void) gettimeofday(&tv, &tz);
257 timePtr->sec = tv.tv_sec;
258 timePtr->usec = tv.tv_usec;
262 *----------------------------------------------------------------------
266 * This function converts between seconds and struct tm. If
267 * useGMT is true, then the returned date will be in Greenwich
268 * Mean Time (GMT). Otherwise, it will be in the local time zone.
271 * Returns a static tm structure.
276 *----------------------------------------------------------------------
280 TclpGetDate(time, useGMT)
285 return TclpGmtime(time);
287 return TclpLocaltime(time);
292 *----------------------------------------------------------------------
296 * On Unix, we can safely call the native strftime implementation,
297 * and also ignore the useGMT parameter.
300 * The normal strftime result.
305 *----------------------------------------------------------------------
309 TclpStrftime(s, maxsize, format, t, useGMT)
316 if (format[0] == '%' && format[1] == 'Q') {
317 /* Format as a stardate */
318 sprintf(s, "Stardate %2d%03d.%01d",
319 (((t->tm_year + TM_YEAR_BASE) + 377) - 2323),
320 (((t->tm_yday + 1) * 1000) /
321 (365 + IsLeapYear((t->tm_year + TM_YEAR_BASE)))),
322 (((t->tm_hour * 60) + t->tm_min)/144));
325 setlocale(LC_TIME, "");
326 return strftime(s, maxsize, format, t);
330 *----------------------------------------------------------------------
334 * Wrapper around the 'gmtime' library function to make it thread
338 * Returns a pointer to a 'struct tm' in thread-specific data.
341 * Invokes gmtime or gmtime_r as appropriate.
343 *----------------------------------------------------------------------
350 CONST time_t *timePtr = (CONST time_t *) tt;
351 /* Pointer to the number of seconds
352 * since the local system's epoch */
355 * Get a thread-local buffer to hold the returned time.
358 ThreadSpecificData *tsdPtr = TCL_TSD_INIT( &tmKey );
360 gmtime_r(timePtr, &( tsdPtr->gmtime_buf ));
362 Tcl_MutexLock( &tmMutex );
363 memcpy( (VOID *) &( tsdPtr->gmtime_buf ),
364 (VOID *) gmtime( timePtr ),
365 sizeof( struct tm ) );
366 Tcl_MutexUnlock( &tmMutex );
368 return &( tsdPtr->gmtime_buf );
371 * Forwarder for obsolete item in Stubs
374 TclpGmtime_unix( timePtr )
375 TclpTime_t_CONST timePtr;
377 return TclpGmtime( timePtr );
381 *----------------------------------------------------------------------
385 * Wrapper around the 'localtime' library function to make it thread
389 * Returns a pointer to a 'struct tm' in thread-specific data.
392 * Invokes localtime or localtime_r as appropriate.
394 *----------------------------------------------------------------------
401 CONST time_t *timePtr = (CONST time_t *) tt;
402 /* Pointer to the number of seconds
403 * since the local system's epoch */
405 * Get a thread-local buffer to hold the returned time.
408 ThreadSpecificData *tsdPtr = TCL_TSD_INIT( &tmKey );
410 #ifdef HAVE_LOCALTIME_R
411 localtime_r( timePtr, &( tsdPtr->localtime_buf ) );
413 Tcl_MutexLock( &tmMutex );
414 memcpy( (VOID *) &( tsdPtr -> localtime_buf ),
415 (VOID *) localtime( timePtr ),
416 sizeof( struct tm ) );
417 Tcl_MutexUnlock( &tmMutex );
419 return &( tsdPtr->localtime_buf );
422 * Forwarder for obsolete item in Stubs
425 TclpLocaltime_unix( timePtr )
426 TclpTime_t_CONST timePtr;
428 return TclpLocaltime( timePtr );
432 *----------------------------------------------------------------------
434 * SetTZIfNecessary --
436 * Determines whether a call to 'tzset' is needed prior to the
437 * next call to 'localtime' or examination of the 'timezone' variable.
443 * If 'tzset' has never been called in the current process, or if
444 * the value of the environment variable TZ has changed since the
445 * last call to 'tzset', then 'tzset' is called again.
447 *----------------------------------------------------------------------
453 CONST char* newTZ = getenv( "TZ" );
454 Tcl_MutexLock(&tmMutex);
455 if ( newTZ == NULL ) {
458 if ( lastTZ == NULL || strcmp( lastTZ, newTZ ) ) {
460 if ( lastTZ == NULL ) {
461 Tcl_CreateExitHandler( CleanupMemory, (ClientData) NULL );
465 lastTZ = ckalloc( strlen( newTZ ) + 1 );
466 strcpy( lastTZ, newTZ );
468 Tcl_MutexUnlock(&tmMutex);
473 *----------------------------------------------------------------------
477 * Releases the private copy of the TZ environment variable
478 * upon exit from Tcl.
484 * Frees allocated memory.
486 *----------------------------------------------------------------------
490 CleanupMemory( ClientData ignored )