os/persistentdata/persistentstorage/sqlite3api/TEST/TCL/tcldistribution/mac/tclMacTime.c
author sl@SLION-WIN7.fritz.box
Fri, 15 Jun 2012 03:10:57 +0200
changeset 0 bde4ae8d615e
permissions -rw-r--r--
First public contribution.
sl@0
     1
/* 
sl@0
     2
 * tclMacTime.c --
sl@0
     3
 *
sl@0
     4
 *	Contains Macintosh specific versions of Tcl functions that
sl@0
     5
 *	obtain time values from the operating system.
sl@0
     6
 *
sl@0
     7
 * Copyright (c) 1995-1997 Sun Microsystems, Inc.
sl@0
     8
 *
sl@0
     9
 * See the file "license.terms" for information on usage and redistribution
sl@0
    10
 * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
sl@0
    11
 *
sl@0
    12
 * RCS: @(#) $Id: tclMacTime.c,v 1.7 2002/01/04 11:21:05 das Exp $
sl@0
    13
 */
sl@0
    14
sl@0
    15
#include "tclInt.h"
sl@0
    16
#include "tclPort.h"
sl@0
    17
#include "tclMacInt.h"
sl@0
    18
#include <OSUtils.h>
sl@0
    19
#include <Timer.h>
sl@0
    20
#include <time.h>
sl@0
    21
sl@0
    22
/*
sl@0
    23
 * Static variables used by the Tcl_GetTime function.
sl@0
    24
 */
sl@0
    25
 
sl@0
    26
static int initalized = false;
sl@0
    27
static unsigned long baseSeconds;
sl@0
    28
static UnsignedWide microOffset;
sl@0
    29
sl@0
    30
static int gmt_initialized = false;
sl@0
    31
static long gmt_offset;
sl@0
    32
static int gmt_isdst;
sl@0
    33
TCL_DECLARE_MUTEX(gmtMutex)
sl@0
    34
sl@0
    35
static int gmt_lastGetDateUseGMT = 0;
sl@0
    36
sl@0
    37
typedef struct _TABLE {
sl@0
    38
    char        *name;
sl@0
    39
    int         type;
sl@0
    40
    time_t      value;
sl@0
    41
} TABLE;
sl@0
    42
sl@0
    43
sl@0
    44
#define HOUR(x)         ((time_t) (3600 * x))
sl@0
    45
sl@0
    46
#define tZONE 0
sl@0
    47
#define tDAYZONE 1
sl@0
    48
sl@0
    49
sl@0
    50
/*
sl@0
    51
 * inverse timezone table, adapted from tclDate.c by removing duplicates and
sl@0
    52
 * adding some made up names for unusual daylight savings
sl@0
    53
 */
sl@0
    54
static TABLE    invTimezoneTable[] = {
sl@0
    55
    { "Z",    -1,     HOUR( 36) },      /* Unknown */
sl@0
    56
    { "GMT",    tZONE,     HOUR( 0) },      /* Greenwich Mean */
sl@0
    57
    { "BST",    tDAYZONE,  HOUR( 0) },      /* British Summer */
sl@0
    58
    { "WAT",    tZONE,     HOUR( 1) },      /* West Africa */
sl@0
    59
    { "WADST",  tDAYZONE,  HOUR( 1) },      /* West Africa Daylight*/
sl@0
    60
    { "AT",     tZONE,     HOUR( 2) },      /* Azores Daylight*/
sl@0
    61
    { "ADST",   tDAYZONE,  HOUR( 2) },      /* Azores */
sl@0
    62
    { "NFT",    tZONE,     HOUR( 7/2) },    /* Newfoundland */
sl@0
    63
    { "NDT",    tDAYZONE,  HOUR( 7/2) },    /* Newfoundland Daylight */
sl@0
    64
    { "AST",    tZONE,     HOUR( 4) },      /* Atlantic Standard */
sl@0
    65
    { "ADT",    tDAYZONE,  HOUR( 4) },      /* Atlantic Daylight */
sl@0
    66
    { "EST",    tZONE,     HOUR( 5) },      /* Eastern Standard */
sl@0
    67
    { "EDT",    tDAYZONE,  HOUR( 5) },      /* Eastern Daylight */
sl@0
    68
    { "CST",    tZONE,     HOUR( 6) },      /* Central Standard */
sl@0
    69
    { "CDT",    tDAYZONE,  HOUR( 6) },      /* Central Daylight */
sl@0
    70
    { "MST",    tZONE,     HOUR( 7) },      /* Mountain Standard */
sl@0
    71
    { "MDT",    tDAYZONE,  HOUR( 7) },      /* Mountain Daylight */
sl@0
    72
    { "PST",    tZONE,     HOUR( 8) },      /* Pacific Standard */
sl@0
    73
    { "PDT",    tDAYZONE,  HOUR( 8) },      /* Pacific Daylight */
sl@0
    74
    { "YST",    tZONE,     HOUR( 9) },      /* Yukon Standard */
sl@0
    75
    { "YDT",    tDAYZONE,  HOUR( 9) },      /* Yukon Daylight */
sl@0
    76
    { "HST",    tZONE,     HOUR(10) },      /* Hawaii Standard */
sl@0
    77
    { "HDT",    tDAYZONE,  HOUR(10) },      /* Hawaii Daylight */
sl@0
    78
    { "NT",     tZONE,     HOUR(11) },      /* Nome */
sl@0
    79
    { "NST",    tDAYZONE,  HOUR(11) },      /* Nome Daylight*/
sl@0
    80
    { "IDLW",   tZONE,     HOUR(12) },      /* International Date Line West */
sl@0
    81
    { "CET",    tZONE,    -HOUR( 1) },      /* Central European */
sl@0
    82
    { "CEST",   tDAYZONE, -HOUR( 1) },      /* Central European Summer */
sl@0
    83
    { "EET",    tZONE,    -HOUR( 2) },      /* Eastern Europe, USSR Zone 1 */
sl@0
    84
    { "EEST",   tDAYZONE, -HOUR( 2) },      /* Eastern Europe, USSR Zone 1 Daylight*/
sl@0
    85
    { "BT",     tZONE,    -HOUR( 3) },      /* Baghdad, USSR Zone 2 */
sl@0
    86
    { "BDST",   tDAYZONE, -HOUR( 3) },      /* Baghdad, USSR Zone 2 Daylight*/
sl@0
    87
    { "IT",     tZONE,    -HOUR( 7/2) },    /* Iran */
sl@0
    88
    { "IDST",   tDAYZONE, -HOUR( 7/2) },    /* Iran Daylight*/
sl@0
    89
    { "ZP4",    tZONE,    -HOUR( 4) },      /* USSR Zone 3 */
sl@0
    90
    { "ZP4S",   tDAYZONE, -HOUR( 4) },      /* USSR Zone 3 */
sl@0
    91
    { "ZP5",    tZONE,    -HOUR( 5) },      /* USSR Zone 4 */
sl@0
    92
    { "ZP5S",   tDAYZONE, -HOUR( 5) },      /* USSR Zone 4 */
sl@0
    93
    { "IST",    tZONE,    -HOUR(11/2) },    /* Indian Standard */
sl@0
    94
    { "ISDST",  tDAYZONE, -HOUR(11/2) },    /* Indian Standard */
sl@0
    95
    { "ZP6",    tZONE,    -HOUR( 6) },      /* USSR Zone 5 */
sl@0
    96
    { "ZP6S",   tDAYZONE, -HOUR( 6) },      /* USSR Zone 5 */
sl@0
    97
    { "WAST",   tZONE,    -HOUR( 7) },      /* West Australian Standard */
sl@0
    98
    { "WADT",   tDAYZONE, -HOUR( 7) },      /* West Australian Daylight */
sl@0
    99
    { "JT",     tZONE,    -HOUR(15/2) },    /* Java (3pm in Cronusland!) */
sl@0
   100
    { "JDST",   tDAYZONE, -HOUR(15/2) },    /* Java (3pm in Cronusland!) */
sl@0
   101
    { "CCT",    tZONE,    -HOUR( 8) },      /* China Coast, USSR Zone 7 */
sl@0
   102
    { "CCST",   tDAYZONE, -HOUR( 8) },      /* China Coast, USSR Zone 7 */
sl@0
   103
    { "JST",    tZONE,    -HOUR( 9) },      /* Japan Standard, USSR Zone 8 */
sl@0
   104
    { "JSDST",  tDAYZONE, -HOUR( 9) },      /* Japan Standard, USSR Zone 8 */
sl@0
   105
    { "CAST",   tZONE,    -HOUR(19/2) },    /* Central Australian Standard */
sl@0
   106
    { "CADT",   tDAYZONE, -HOUR(19/2) },    /* Central Australian Daylight */
sl@0
   107
    { "EAST",   tZONE,    -HOUR(10) },      /* Eastern Australian Standard */
sl@0
   108
    { "EADT",   tDAYZONE, -HOUR(10) },      /* Eastern Australian Daylight */
sl@0
   109
    { "NZT",    tZONE,    -HOUR(12) },      /* New Zealand */
sl@0
   110
    { "NZDT",   tDAYZONE, -HOUR(12) },      /* New Zealand Daylight */
sl@0
   111
    {  NULL  }
sl@0
   112
};
sl@0
   113
sl@0
   114
/*
sl@0
   115
 * Prototypes for procedures that are private to this file:
sl@0
   116
 */
sl@0
   117
sl@0
   118
static void SubtractUnsignedWide _ANSI_ARGS_((UnsignedWide *x,
sl@0
   119
	UnsignedWide *y, UnsignedWide *result));
sl@0
   120

sl@0
   121
/*
sl@0
   122
 *-----------------------------------------------------------------------------
sl@0
   123
 *
sl@0
   124
 * TclpGetGMTOffset --
sl@0
   125
 *
sl@0
   126
 *	This procedure gets the offset seconds that needs to be _added_ to tcl time
sl@0
   127
 *  in seconds (i.e. GMT time) to get local time needed as input to various
sl@0
   128
 *  Mac OS APIs, to convert Mac OS API output to tcl time, _subtract_ this value.
sl@0
   129
 *
sl@0
   130
 * Results:
sl@0
   131
 *	Number of seconds separating GMT time and mac.
sl@0
   132
 *
sl@0
   133
 * Side effects:
sl@0
   134
 *	None.
sl@0
   135
 *
sl@0
   136
 *-----------------------------------------------------------------------------
sl@0
   137
 */
sl@0
   138
sl@0
   139
long
sl@0
   140
TclpGetGMTOffset()
sl@0
   141
{
sl@0
   142
    if (gmt_initialized == false) {
sl@0
   143
	MachineLocation loc;
sl@0
   144
	
sl@0
   145
    Tcl_MutexLock(&gmtMutex);
sl@0
   146
	ReadLocation(&loc);
sl@0
   147
	gmt_offset = loc.u.gmtDelta & 0x00ffffff;
sl@0
   148
	if (gmt_offset & 0x00800000) {
sl@0
   149
	    gmt_offset = gmt_offset | 0xff000000;
sl@0
   150
	}
sl@0
   151
	gmt_isdst=(loc.u.dlsDelta < 0);
sl@0
   152
	gmt_initialized = true;
sl@0
   153
    Tcl_MutexUnlock(&gmtMutex);
sl@0
   154
    }
sl@0
   155
	return (gmt_offset);
sl@0
   156
}
sl@0
   157

sl@0
   158
/*
sl@0
   159
 *-----------------------------------------------------------------------------
sl@0
   160
 *
sl@0
   161
 * TclpGetSeconds --
sl@0
   162
 *
sl@0
   163
 *	This procedure returns the number of seconds from the epoch.  On
sl@0
   164
 *	the Macintosh the epoch is Midnight Jan 1, 1904.  Unfortunatly,
sl@0
   165
 *	the Macintosh doesn't tie the epoch to a particular time zone.  For
sl@0
   166
 *	Tcl we tie the epoch to GMT.  This makes the time zone date parsing
sl@0
   167
 *	code work.  The epoch for Mac-Tcl is: Midnight Jan 1, 1904 GMT.
sl@0
   168
 *
sl@0
   169
 * Results:
sl@0
   170
 *	Number of seconds from the epoch in GMT.
sl@0
   171
 *
sl@0
   172
 * Side effects:
sl@0
   173
 *	None.
sl@0
   174
 *
sl@0
   175
 *-----------------------------------------------------------------------------
sl@0
   176
 */
sl@0
   177
sl@0
   178
unsigned long
sl@0
   179
TclpGetSeconds()
sl@0
   180
{
sl@0
   181
    unsigned long seconds;
sl@0
   182
sl@0
   183
    GetDateTime(&seconds);
sl@0
   184
	return (seconds - TclpGetGMTOffset() + tcl_mac_epoch_offset);
sl@0
   185
}
sl@0
   186

sl@0
   187
/*
sl@0
   188
 *-----------------------------------------------------------------------------
sl@0
   189
 *
sl@0
   190
 * TclpGetClicks --
sl@0
   191
 *
sl@0
   192
 *	This procedure returns a value that represents the highest resolution
sl@0
   193
 *	clock available on the system.  There are no garantees on what the
sl@0
   194
 *	resolution will be.  In Tcl we will call this value a "click".  The
sl@0
   195
 *	start time is also system dependant.
sl@0
   196
 *
sl@0
   197
 * Results:
sl@0
   198
 *	Number of clicks from some start time.
sl@0
   199
 *
sl@0
   200
 * Side effects:
sl@0
   201
 *	None.
sl@0
   202
 *
sl@0
   203
 *-----------------------------------------------------------------------------
sl@0
   204
 */
sl@0
   205
sl@0
   206
unsigned long
sl@0
   207
TclpGetClicks()
sl@0
   208
{
sl@0
   209
    UnsignedWide micros;
sl@0
   210
sl@0
   211
    Microseconds(&micros);
sl@0
   212
    return micros.lo;
sl@0
   213
}
sl@0
   214

sl@0
   215
/*
sl@0
   216
 *----------------------------------------------------------------------
sl@0
   217
 *
sl@0
   218
 * TclpGetTimeZone --
sl@0
   219
 *
sl@0
   220
 *	Get the current time zone.
sl@0
   221
 *
sl@0
   222
 * Results:
sl@0
   223
 *	The return value is the local time zone, measured in
sl@0
   224
 *	minutes away from GMT (-ve for east, +ve for west).
sl@0
   225
 *
sl@0
   226
 * Side effects:
sl@0
   227
 *	None.
sl@0
   228
 *
sl@0
   229
 *----------------------------------------------------------------------
sl@0
   230
 */
sl@0
   231
sl@0
   232
int
sl@0
   233
TclpGetTimeZone (
sl@0
   234
    unsigned long  currentTime)		/* Ignored on Mac. */
sl@0
   235
{
sl@0
   236
    long offset;
sl@0
   237
sl@0
   238
    /*
sl@0
   239
     * Convert the Mac offset from seconds to minutes and
sl@0
   240
     * add an hour if we have daylight savings time.
sl@0
   241
     */
sl@0
   242
    offset = -TclpGetGMTOffset();
sl@0
   243
    offset /= 60;
sl@0
   244
    if (gmt_isdst) {
sl@0
   245
	offset += 60;
sl@0
   246
    }
sl@0
   247
    
sl@0
   248
    return offset;
sl@0
   249
}
sl@0
   250

sl@0
   251
/*
sl@0
   252
 *----------------------------------------------------------------------
sl@0
   253
 *
sl@0
   254
 * Tcl_GetTime --
sl@0
   255
 *
sl@0
   256
 *	Gets the current system time in seconds and microseconds
sl@0
   257
 *	since the beginning of the epoch: 00:00 UCT, January 1, 1970.
sl@0
   258
 *
sl@0
   259
 * Results:
sl@0
   260
 *	Returns the current time (in the local timezone) in timePtr.
sl@0
   261
 *
sl@0
   262
 * Side effects:
sl@0
   263
 *	None.
sl@0
   264
 *
sl@0
   265
 *----------------------------------------------------------------------
sl@0
   266
 */
sl@0
   267
sl@0
   268
void
sl@0
   269
Tcl_GetTime(
sl@0
   270
    Tcl_Time *timePtr)		/* Location to store time information. */
sl@0
   271
{
sl@0
   272
    UnsignedWide micro;
sl@0
   273
#ifndef NO_LONG_LONG
sl@0
   274
    long long *microPtr;
sl@0
   275
#endif
sl@0
   276
	
sl@0
   277
    if (initalized == false) {
sl@0
   278
	GetDateTime(&baseSeconds);
sl@0
   279
	/*
sl@0
   280
	 * Remove the local offset that ReadDateTime() adds.
sl@0
   281
	 */
sl@0
   282
	baseSeconds -= TclpGetGMTOffset() - tcl_mac_epoch_offset;
sl@0
   283
	Microseconds(&microOffset);
sl@0
   284
	initalized = true;
sl@0
   285
    }
sl@0
   286
sl@0
   287
    Microseconds(&micro);
sl@0
   288
sl@0
   289
#ifndef NO_LONG_LONG
sl@0
   290
    microPtr = (long long *) &micro;
sl@0
   291
    *microPtr -= *((long long *) &microOffset);
sl@0
   292
    timePtr->sec = baseSeconds + (*microPtr / 1000000);
sl@0
   293
    timePtr->usec = *microPtr % 1000000;
sl@0
   294
#else
sl@0
   295
    SubtractUnsignedWide(&micro, &microOffset, &micro);
sl@0
   296
sl@0
   297
    /*
sl@0
   298
     * This lovely computation is equal to: base + (micro / 1000000)
sl@0
   299
     * For the .hi part the ratio of 0x100000000 / 1000000 has been
sl@0
   300
     * reduced to avoid overflow.  This computation certainly has 
sl@0
   301
     * problems as the .hi part gets large.  However, your application
sl@0
   302
     * would have to run for a long time to make that happen.
sl@0
   303
     */
sl@0
   304
sl@0
   305
    timePtr->sec = baseSeconds + (micro.lo / 1000000) + 
sl@0
   306
    	(long) (micro.hi * ((double) 33554432.0 / 15625.0));
sl@0
   307
    timePtr->usec = micro.lo % 1000000;
sl@0
   308
#endif
sl@0
   309
}
sl@0
   310

sl@0
   311
/*
sl@0
   312
 *----------------------------------------------------------------------
sl@0
   313
 *
sl@0
   314
 * TclpGetDate --
sl@0
   315
 *
sl@0
   316
 *	Converts raw seconds to a struct tm data structure.  The
sl@0
   317
 *	returned time will be for Greenwich Mean Time if the useGMT flag 
sl@0
   318
 *	is set.  Otherwise, the returned time will be for the local
sl@0
   319
 *	time zone.  This function is meant to be used as a replacement
sl@0
   320
 *	for localtime and gmtime which is broken on most ANSI libs
sl@0
   321
 *	on the Macintosh.
sl@0
   322
 *
sl@0
   323
 * Results:
sl@0
   324
 *	None.
sl@0
   325
 *
sl@0
   326
 * Side effects:
sl@0
   327
 *  	The passed in struct tm data structure is modified.
sl@0
   328
 *
sl@0
   329
 *----------------------------------------------------------------------
sl@0
   330
 */
sl@0
   331
sl@0
   332
struct tm *
sl@0
   333
TclpGetDate(
sl@0
   334
    TclpTime_t time,	/* Time struct to fill. */
sl@0
   335
    int useGMT)		/* True if date should reflect GNT time. */
sl@0
   336
{
sl@0
   337
    const time_t *tp = (const time_t *)time;
sl@0
   338
    DateTimeRec dtr;
sl@0
   339
    unsigned long offset=0L;
sl@0
   340
    static struct tm statictime;
sl@0
   341
    static const short monthday[12] =
sl@0
   342
        {0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334};
sl@0
   343
	    
sl@0
   344
	if(useGMT)
sl@0
   345
		SecondsToDate(*tp - tcl_mac_epoch_offset, &dtr);
sl@0
   346
	else
sl@0
   347
		SecondsToDate(*tp + TclpGetGMTOffset() - tcl_mac_epoch_offset, &dtr);
sl@0
   348
	
sl@0
   349
    statictime.tm_sec = dtr.second;
sl@0
   350
    statictime.tm_min = dtr.minute;
sl@0
   351
    statictime.tm_hour = dtr.hour;
sl@0
   352
    statictime.tm_mday = dtr.day;
sl@0
   353
    statictime.tm_mon = dtr.month - 1;
sl@0
   354
    statictime.tm_year = dtr.year - 1900;
sl@0
   355
    statictime.tm_wday = dtr.dayOfWeek - 1;
sl@0
   356
    statictime.tm_yday = monthday[statictime.tm_mon]
sl@0
   357
	+ statictime.tm_mday - 1;
sl@0
   358
    if (1 < statictime.tm_mon && !(statictime.tm_year & 3)) {
sl@0
   359
	++statictime.tm_yday;
sl@0
   360
    }
sl@0
   361
    if(useGMT)
sl@0
   362
    	statictime.tm_isdst = 0;
sl@0
   363
    else
sl@0
   364
    	statictime.tm_isdst = gmt_isdst;
sl@0
   365
    gmt_lastGetDateUseGMT=useGMT; /* hack to make TclpGetTZName below work */
sl@0
   366
    return(&statictime);
sl@0
   367
}
sl@0
   368

sl@0
   369
/*
sl@0
   370
 *----------------------------------------------------------------------
sl@0
   371
 *
sl@0
   372
 * TclpGetTZName --
sl@0
   373
 *
sl@0
   374
 *	Gets the current timezone string.
sl@0
   375
 *
sl@0
   376
 * Results:
sl@0
   377
 *	Returns a pointer to a static string, or NULL on failure.
sl@0
   378
 *
sl@0
   379
 * Side effects:
sl@0
   380
 *	None.
sl@0
   381
 *
sl@0
   382
 *----------------------------------------------------------------------
sl@0
   383
 */
sl@0
   384
sl@0
   385
char *
sl@0
   386
TclpGetTZName(int dst)
sl@0
   387
{
sl@0
   388
    register TABLE *tp;
sl@0
   389
	long zonevalue=-TclpGetGMTOffset();
sl@0
   390
		
sl@0
   391
    if (gmt_isdst)
sl@0
   392
        zonevalue += HOUR(1);
sl@0
   393
sl@0
   394
	if(gmt_lastGetDateUseGMT) /* hack: if last TclpGetDate was called */
sl@0
   395
		zonevalue=0;          /* with useGMT==1 then we're using GMT  */
sl@0
   396
sl@0
   397
    for (tp = invTimezoneTable; tp->name; tp++) {
sl@0
   398
        if ((tp->value == zonevalue) && (tp->type == dst)) break;
sl@0
   399
    }
sl@0
   400
	if(!tp->name)
sl@0
   401
		tp = invTimezoneTable; /* default to unknown */
sl@0
   402
sl@0
   403
    return tp->name;
sl@0
   404
}
sl@0
   405

sl@0
   406
#ifdef NO_LONG_LONG
sl@0
   407
/*
sl@0
   408
 *----------------------------------------------------------------------
sl@0
   409
 *
sl@0
   410
 * SubtractUnsignedWide --
sl@0
   411
 *
sl@0
   412
 *	Subtracts one UnsignedWide value from another.
sl@0
   413
 *
sl@0
   414
 * Results:
sl@0
   415
 *  	The subtracted value.
sl@0
   416
 *
sl@0
   417
 * Side effects:
sl@0
   418
 *	None.
sl@0
   419
 *
sl@0
   420
 *----------------------------------------------------------------------
sl@0
   421
 */
sl@0
   422
sl@0
   423
static void
sl@0
   424
SubtractUnsignedWide(
sl@0
   425
    UnsignedWide *x,		/* Ptr to wide int. */
sl@0
   426
    UnsignedWide *y,		/* Ptr to wide int. */
sl@0
   427
    UnsignedWide *result)	/* Ptr to result. */
sl@0
   428
{
sl@0
   429
    result->hi = x->hi - y->hi;
sl@0
   430
    if (x->lo < y->lo) {
sl@0
   431
	result->hi--;
sl@0
   432
    }
sl@0
   433
    result->lo = x->lo - y->lo;
sl@0
   434
}
sl@0
   435
#endif