Complete disaster-recovery snapshot: engine/game source, game data assets, VC6 toolchain + DX SDKs, build outputs, deployed game, and _UNUSED archive. Large binaries in Git LFS; text preserved byte-for-byte (core.autocrlf=false, no eol attributes). See RECOVERY.md for the one-clone rebuild procedure.
934 lines
29 KiB
C++
934 lines
29 KiB
C++
/***
|
|
*tzset.c - set timezone information and see if we're in daylight time
|
|
*
|
|
* Copyright (c) 1985-1998, Microsoft Corporation. All rights reserved.
|
|
*
|
|
*Purpose:
|
|
* defines _tzset() - set timezone and daylight saving time vars
|
|
*
|
|
*******************************************************************************/
|
|
|
|
#ifdef _WIN32
|
|
|
|
|
|
#include <cruntime.h>
|
|
#include <ctype.h>
|
|
#include <ctime.h>
|
|
#include <time.h>
|
|
#include <stdlib.h>
|
|
#include <internal.h>
|
|
#include <mtdll.h>
|
|
#include <windows.h>
|
|
#include <setlocal.h>
|
|
#include <string.h>
|
|
#include <dbgint.h>
|
|
|
|
|
|
/*
|
|
* Number of milliseconds in one day
|
|
*/
|
|
#define DAY_MILLISEC (24L * 60L * 60L * 1000L)
|
|
|
|
/*
|
|
* The macro below is valid for years between 1901 and 2099, which easily
|
|
* includes all years representable by the current implementation of time_t.
|
|
*/
|
|
#define IS_LEAP_YEAR(year) ( (year & 3) == 0 )
|
|
|
|
/*
|
|
* Pointer to a saved copy of the TZ value obtained in the previous call
|
|
* to tzset() set (if any).
|
|
*/
|
|
static char * lastTZ = NULL;
|
|
|
|
/*
|
|
* Flag indicating that time zone information came from GetTimeZoneInformation
|
|
* API call.
|
|
*/
|
|
static int tzapiused;
|
|
|
|
static TIME_ZONE_INFORMATION tzinfo;
|
|
|
|
/*
|
|
* Structure used to represent DST transition date/times.
|
|
*/
|
|
typedef struct {
|
|
int yr; /* year of interest */
|
|
int yd; /* day of year */
|
|
long ms; /* milli-seconds in the day */
|
|
} transitiondate;
|
|
|
|
/*
|
|
* DST start and end structs.
|
|
*/
|
|
static transitiondate dststart = { -1, 0, 0L };
|
|
static transitiondate dstend = { -1, 0, 0L };
|
|
|
|
static int __cdecl _isindst_lk(struct tm *);
|
|
|
|
|
|
|
|
/***
|
|
*void tzset() - sets timezone information and calc if in daylight time
|
|
*
|
|
*Purpose:
|
|
* Sets the timezone information from the TZ environment variable
|
|
* and then sets _timezone, _daylight, and _tzname. If we're in daylight
|
|
* time is automatically calculated.
|
|
*
|
|
*Entry:
|
|
* None, reads TZ environment variable.
|
|
*
|
|
*Exit:
|
|
* sets _daylight, _timezone, and _tzname global vars, no return value
|
|
*
|
|
*Exceptions:
|
|
*
|
|
*******************************************************************************/
|
|
|
|
|
|
#ifdef _MT
|
|
static void __cdecl _tzset_lk(void);
|
|
#else /* _MT */
|
|
#define _tzset_lk _tzset
|
|
#endif /* _MT */
|
|
|
|
void __cdecl __tzset(void)
|
|
{
|
|
static int first_time = 0;
|
|
|
|
if ( !first_time ) {
|
|
|
|
_mlock( _TIME_LOCK );
|
|
|
|
if ( !first_time ) {
|
|
_tzset_lk();
|
|
first_time++;
|
|
}
|
|
|
|
_munlock(_TIME_LOCK );
|
|
|
|
}
|
|
}
|
|
|
|
|
|
#ifdef _MT
|
|
void __cdecl _tzset (
|
|
void
|
|
)
|
|
{
|
|
_mlock( _TIME_LOCK );
|
|
|
|
_tzset_lk();
|
|
|
|
_munlock( _TIME_LOCK );
|
|
}
|
|
|
|
|
|
static void __cdecl _tzset_lk (
|
|
|
|
#else /* _MT */
|
|
|
|
void __cdecl _tzset (
|
|
|
|
#endif /* _MT */
|
|
|
|
void
|
|
)
|
|
{
|
|
char *TZ;
|
|
int defused;
|
|
int negdiff = 0;
|
|
|
|
_mlock(_ENV_LOCK);
|
|
|
|
/*
|
|
* Clear the flag indicated whether GetTimeZoneInformation was used.
|
|
*/
|
|
tzapiused = 0;
|
|
|
|
/*
|
|
* Set year fields of dststart and dstend structures to -1 to ensure
|
|
* they are recomputed as after this
|
|
*/
|
|
dststart.yr = dstend.yr = -1;
|
|
|
|
/*
|
|
* Fetch the value of the TZ environment variable.
|
|
*/
|
|
if ( (TZ = _getenv_lk("TZ")) == NULL ) {
|
|
|
|
/*
|
|
* There is no TZ environment variable, try to use the time zone
|
|
* information from the system.
|
|
*/
|
|
|
|
_munlock(_ENV_LOCK);
|
|
|
|
if ( GetTimeZoneInformation( &tzinfo ) != 0xFFFFFFFF ) {
|
|
/*
|
|
* Note that the API was used.
|
|
*/
|
|
tzapiused = 1;
|
|
|
|
/*
|
|
* Derive _timezone value from Bias and StandardBias fields.
|
|
*/
|
|
_timezone = tzinfo.Bias * 60L;
|
|
|
|
if ( tzinfo.StandardDate.wMonth != 0 )
|
|
_timezone += (tzinfo.StandardBias * 60L);
|
|
|
|
/*
|
|
* Check to see if there is a daylight time bias. Since the
|
|
* StandardBias has been added into _timezone, it must be
|
|
* compensated for in the value computed for _dstbias.
|
|
*/
|
|
if ( (tzinfo.DaylightDate.wMonth != 0) &&
|
|
(tzinfo.DaylightBias != 0) )
|
|
{
|
|
_daylight = 1;
|
|
_dstbias = (tzinfo.DaylightBias - tzinfo.StandardBias) *
|
|
60L;
|
|
}
|
|
else {
|
|
_daylight = 0;
|
|
|
|
/*
|
|
* Set daylight bias to 0 because GetTimeZoneInformation
|
|
* may return TIME_ZONE_ID_DAYLIGHT even though there is
|
|
* no DST (in NT 3.51, just turn off the automatic DST
|
|
* adjust in the control panel)!
|
|
*/
|
|
_dstbias = 0;
|
|
}
|
|
|
|
/*
|
|
* Try to grab the name strings for both the time zone and the
|
|
* daylight zone. Note the wide character strings in tzinfo
|
|
* must be converted to multibyte characters strings. The
|
|
* locale codepage, __lc_codepage, is used for this. Note that
|
|
* if setlocale() with LC_ALL or LC_CTYPE has not been called,
|
|
* then __lc_codepage will be 0 (_CLOCALECP), which is CP_ACP
|
|
* (which means use the host's default ANSI codepage).
|
|
*/
|
|
if ( (WideCharToMultiByte( __lc_codepage,
|
|
WC_COMPOSITECHECK |
|
|
WC_SEPCHARS,
|
|
tzinfo.StandardName,
|
|
-1,
|
|
_tzname[0],
|
|
63,
|
|
NULL,
|
|
&defused ) != 0) &&
|
|
(!defused) )
|
|
_tzname[0][63] = '\0';
|
|
else
|
|
_tzname[0][0] = '\0';
|
|
|
|
if ( (WideCharToMultiByte( __lc_codepage,
|
|
WC_COMPOSITECHECK |
|
|
WC_SEPCHARS,
|
|
tzinfo.DaylightName,
|
|
-1,
|
|
_tzname[1],
|
|
63,
|
|
NULL,
|
|
&defused ) != 0) &&
|
|
(!defused) )
|
|
_tzname[1][63] = '\0';
|
|
else
|
|
_tzname[1][0] = '\0';
|
|
|
|
}
|
|
|
|
/*
|
|
* Time zone information is unavailable, just return.
|
|
*/
|
|
return;
|
|
}
|
|
|
|
|
|
if ( (*TZ == '\0') || ((lastTZ != NULL) && (strcmp(TZ, lastTZ) == 0)) )
|
|
{
|
|
/*
|
|
* Either TZ is NULL, pointing to '\0', or is the unchanged
|
|
* from a earlier call (to this function). In any case, there
|
|
* is no work to do, so just return
|
|
*/
|
|
_munlock(_ENV_LOCK);
|
|
return;
|
|
}
|
|
|
|
/*
|
|
* Update lastTZ
|
|
*/
|
|
_free_crt(lastTZ);
|
|
|
|
if ((lastTZ = _malloc_crt(strlen(TZ)+1)) == NULL)
|
|
{
|
|
_munlock(_ENV_LOCK);
|
|
return;
|
|
}
|
|
strcpy(lastTZ, TZ);
|
|
|
|
_munlock(_ENV_LOCK);
|
|
|
|
/*
|
|
* Process TZ value and update _tzname, _timezone and _daylight.
|
|
*/
|
|
|
|
strncpy(_tzname[0], TZ, 3);
|
|
_tzname[0][3] = '\0';
|
|
|
|
/*
|
|
* time difference is of the form:
|
|
*
|
|
* [+|-]hh[:mm[:ss]]
|
|
*
|
|
* check minus sign first.
|
|
*/
|
|
if ( *(TZ += 3) == '-' ) {
|
|
negdiff++;
|
|
TZ++;
|
|
}
|
|
|
|
/*
|
|
* process, then skip over, the hours
|
|
*/
|
|
_timezone = atol(TZ) * 3600L;
|
|
|
|
while ( (*TZ == '+') || ((*TZ >= '0') && (*TZ <= '9')) ) TZ++;
|
|
|
|
/*
|
|
* check if minutes were specified
|
|
*/
|
|
if ( *TZ == ':' ) {
|
|
/*
|
|
* process, then skip over, the minutes
|
|
*/
|
|
_timezone += atol(++TZ) * 60L;
|
|
while ( (*TZ >= '0') && (*TZ <= '9') ) TZ++;
|
|
|
|
/*
|
|
* check if seconds were specified
|
|
*/
|
|
if ( *TZ == ':' ) {
|
|
/*
|
|
* process, then skip over, the seconds
|
|
*/
|
|
_timezone += atol(++TZ);
|
|
while ( (*TZ >= '0') && (*TZ <= '9') ) TZ++;
|
|
}
|
|
}
|
|
|
|
if ( negdiff )
|
|
_timezone = -_timezone;
|
|
|
|
/*
|
|
* finally, check for a DST zone suffix
|
|
*/
|
|
if ( _daylight = *TZ ) {
|
|
strncpy(_tzname[1], TZ, 3);
|
|
_tzname[1][3] = '\0';
|
|
}
|
|
else
|
|
*_tzname[1] = '\0';
|
|
|
|
}
|
|
|
|
/***
|
|
*static void cvtdate( trantype, datetype, year, month, week, dayofweek,
|
|
* date, hour, min, second, millisec ) - convert
|
|
* transition date format
|
|
*
|
|
*Purpose:
|
|
* Convert the format of a transition date specification to a value of
|
|
* a transitiondate structure.
|
|
*
|
|
*Entry:
|
|
* int trantype - 1, if it is the start of DST
|
|
* 0, if is the end of DST (in which case the date is
|
|
* is a DST date)
|
|
* int datetype - 1, if a day-in-month format is specified.
|
|
* 0, if an absolute date is specified.
|
|
* int year - year for which the date is being converted (70 ==
|
|
* 1970)
|
|
* int month - month (0 == January)
|
|
* int week - week of month, if datetype == 1 (note that 5== last
|
|
* week of month),
|
|
* 0, otherwise.
|
|
* int dayofweek - day of week (0 == Sunday), if datetype == 1.
|
|
* 0, otherwise.
|
|
* int date - date of month (1 - 31)
|
|
* int hour - hours (0 - 23)
|
|
* int min - minutes (0 - 59)
|
|
* int sec - seconds (0 - 59)
|
|
* int msec - milliseconds (0 - 999)
|
|
*
|
|
*Exit:
|
|
* dststart or dstend is filled in with the converted date.
|
|
*
|
|
*******************************************************************************/
|
|
|
|
static void __cdecl cvtdate (
|
|
int trantype,
|
|
int datetype,
|
|
int year,
|
|
int month,
|
|
int week,
|
|
int dayofweek,
|
|
int date,
|
|
int hour,
|
|
int min,
|
|
int sec,
|
|
int msec
|
|
)
|
|
{
|
|
int yearday;
|
|
int monthdow;
|
|
|
|
if ( datetype == 1 ) {
|
|
|
|
/*
|
|
* Transition day specified in day-in-month format.
|
|
*/
|
|
|
|
/*
|
|
* Figure the year-day of the start of the month.
|
|
*/
|
|
yearday = 1 + (IS_LEAP_YEAR(year) ? _lpdays[month - 1] :
|
|
_days[month - 1]);
|
|
|
|
/*
|
|
* Figure the day of the week of the start of the month.
|
|
*/
|
|
monthdow = (yearday + ((year - 70) * 365) + ((year - 1) >> 2) -
|
|
_LEAP_YEAR_ADJUST + _BASE_DOW) % 7;
|
|
|
|
/*
|
|
* Figure the year-day of the transition date
|
|
*/
|
|
if ( monthdow <= dayofweek )
|
|
yearday += (dayofweek - monthdow) + (week - 1) * 7;
|
|
else
|
|
yearday += (dayofweek - monthdow) + week * 7;
|
|
|
|
/*
|
|
* May have to adjust the calculation above if week == 5 (meaning
|
|
* the last instance of the day in the month). Check if year falls
|
|
* beyond after month and adjust accordingly.
|
|
*/
|
|
if ( (week == 5) &&
|
|
(yearday > (IS_LEAP_YEAR(year) ? _lpdays[month] :
|
|
_days[month])) )
|
|
{
|
|
yearday -= 7;
|
|
}
|
|
}
|
|
else {
|
|
/*
|
|
* Transition day specified as an absolute day
|
|
*/
|
|
yearday = IS_LEAP_YEAR(year) ? _lpdays[month - 1] :
|
|
_days[month - 1];
|
|
|
|
yearday += date;
|
|
}
|
|
|
|
if ( trantype == 1 ) {
|
|
/*
|
|
* Converted date was for the start of DST
|
|
*/
|
|
dststart.yd = yearday;
|
|
dststart.ms = (long)msec +
|
|
(1000L * (sec + 60L * (min + 60L * hour)));
|
|
/*
|
|
* Set year field of dststart so that unnecessary calls to
|
|
* cvtdate() may be avoided.
|
|
*/
|
|
dststart.yr = year;
|
|
}
|
|
else {
|
|
/*
|
|
* Converted date was for the end of DST
|
|
*/
|
|
dstend.yd = yearday;
|
|
dstend.ms = (long)msec +
|
|
(1000L * (sec + 60L * (min + 60L * hour)));
|
|
/*
|
|
* The converted date is still a DST date. Must convert to a
|
|
* standard (local) date while being careful the millisecond field
|
|
* does not overflow or underflow.
|
|
*/
|
|
if ( (dstend.ms += (_dstbias * 1000L)) < 0 ) {
|
|
dstend.ms += DAY_MILLISEC;
|
|
dstend.yd--;
|
|
}
|
|
else if ( dstend.ms >= DAY_MILLISEC ) {
|
|
dstend.ms -= DAY_MILLISEC;
|
|
dstend.yd++;
|
|
}
|
|
|
|
/*
|
|
* Set year field of dstend so that unnecessary calls to cvtdate()
|
|
* may be avoided.
|
|
*/
|
|
dstend.yr = year;
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
/***
|
|
*int _isindst(tb) - determine if broken-down time falls in DST
|
|
*
|
|
*Purpose:
|
|
* Determine if the given broken-down time falls within daylight saving
|
|
* time (DST). The DST rules are either obtained from Win32 (tzapiused !=
|
|
* TRUE) or assumed to be USA rules, post 1986.
|
|
*
|
|
* If the DST rules are obtained from Win32's GetTimeZoneInformation API,
|
|
* the transition dates to/from DST can be specified in either of two
|
|
* formats. First, a day-in-month format, similar to the way USA rules
|
|
* are specified, can be used. The transition date is given as the n-th
|
|
* occurence of a specified day of the week in a specified month. Second,
|
|
* an absolute date can be specified. The two cases are distinguished by
|
|
* the value of wYear field in the SYSTEMTIME structure (0 denotes a
|
|
* day-in-month format).
|
|
*
|
|
* USA rules for DST are that a time is in DST iff it is on or after
|
|
* 02:00 on the first Sunday in April, and before 01:00 on the last
|
|
* Sunday in October.
|
|
*
|
|
*Entry:
|
|
* struct tm *tb - structure holding broken-down time value
|
|
*
|
|
*Exit:
|
|
* 1, if time represented is in DST
|
|
* 0, otherwise
|
|
*
|
|
*******************************************************************************/
|
|
|
|
int __cdecl _isindst (
|
|
struct tm *tb
|
|
)
|
|
#ifdef _MT
|
|
{
|
|
int retval;
|
|
|
|
_mlock( _TIME_LOCK );
|
|
retval = _isindst_lk( tb );
|
|
_munlock( _TIME_LOCK );
|
|
|
|
return retval;
|
|
}
|
|
|
|
static int __cdecl _isindst_lk (
|
|
struct tm *tb
|
|
)
|
|
#endif /* _MT */
|
|
{
|
|
long ms;
|
|
|
|
if ( _daylight == 0 )
|
|
return 0;
|
|
|
|
/*
|
|
* Compute (recompute) the transition dates for daylight saving time
|
|
* if necessary.The yr (year) fields of dststart and dstend is
|
|
* compared to the year of interest to determine necessity.
|
|
*/
|
|
if ( (tb->tm_year != dststart.yr) || (tb->tm_year != dstend.yr) ) {
|
|
if ( tzapiused ) {
|
|
/*
|
|
* Convert the start of daylight saving time to dststart.
|
|
*/
|
|
if ( tzinfo.DaylightDate.wYear == 0 )
|
|
cvtdate( 1,
|
|
1, /* day-in-month format */
|
|
tb->tm_year,
|
|
tzinfo.DaylightDate.wMonth,
|
|
tzinfo.DaylightDate.wDay,
|
|
tzinfo.DaylightDate.wDayOfWeek,
|
|
0,
|
|
tzinfo.DaylightDate.wHour,
|
|
tzinfo.DaylightDate.wMinute,
|
|
tzinfo.DaylightDate.wSecond,
|
|
tzinfo.DaylightDate.wMilliseconds );
|
|
else
|
|
cvtdate( 1,
|
|
0, /* absolute date */
|
|
tb->tm_year,
|
|
tzinfo.DaylightDate.wMonth,
|
|
0,
|
|
0,
|
|
tzinfo.DaylightDate.wDay,
|
|
tzinfo.DaylightDate.wHour,
|
|
tzinfo.DaylightDate.wMinute,
|
|
tzinfo.DaylightDate.wSecond,
|
|
tzinfo.DaylightDate.wMilliseconds );
|
|
/*
|
|
* Convert start of standard time to dstend.
|
|
*/
|
|
if ( tzinfo.StandardDate.wYear == 0 )
|
|
cvtdate( 0,
|
|
1, /* day-in-month format */
|
|
tb->tm_year,
|
|
tzinfo.StandardDate.wMonth,
|
|
tzinfo.StandardDate.wDay,
|
|
tzinfo.StandardDate.wDayOfWeek,
|
|
0,
|
|
tzinfo.StandardDate.wHour,
|
|
tzinfo.StandardDate.wMinute,
|
|
tzinfo.StandardDate.wSecond,
|
|
tzinfo.StandardDate.wMilliseconds );
|
|
else
|
|
cvtdate( 0,
|
|
0, /* absolute date */
|
|
tb->tm_year,
|
|
tzinfo.StandardDate.wMonth,
|
|
0,
|
|
0,
|
|
tzinfo.StandardDate.wDay,
|
|
tzinfo.StandardDate.wHour,
|
|
tzinfo.StandardDate.wMinute,
|
|
tzinfo.StandardDate.wSecond,
|
|
tzinfo.StandardDate.wMilliseconds );
|
|
|
|
}
|
|
else {
|
|
/*
|
|
* GetTimeZoneInformation API was NOT used, or failed. USA
|
|
* daylight saving time rules are assumed.
|
|
*/
|
|
cvtdate( 1,
|
|
1,
|
|
tb->tm_year,
|
|
4, /* April */
|
|
1, /* first... */
|
|
0, /* ...Sunday */
|
|
0,
|
|
2, /* 02:00 (2 AM) */
|
|
0,
|
|
0,
|
|
0 );
|
|
|
|
cvtdate( 0,
|
|
1,
|
|
tb->tm_year,
|
|
10, /* October */
|
|
5, /* last... */
|
|
0, /* ...Sunday */
|
|
0,
|
|
2, /* 02:00 (2 AM) */
|
|
0,
|
|
0,
|
|
0 );
|
|
}
|
|
}
|
|
|
|
/*
|
|
* Handle simple cases first.
|
|
*/
|
|
if ( dststart.yd < dstend.yd ) {
|
|
/*
|
|
* Northern hemisphere ordering
|
|
*/
|
|
if ( (tb->tm_yday < dststart.yd) || (tb->tm_yday > dstend.yd) )
|
|
return 0;
|
|
if ( (tb->tm_yday > dststart.yd) && (tb->tm_yday < dstend.yd) )
|
|
return 1;
|
|
}
|
|
else {
|
|
/*
|
|
* Southern hemisphere ordering
|
|
*/
|
|
if ( (tb->tm_yday < dstend.yd) || (tb->tm_yday > dststart.yd) )
|
|
return 1;
|
|
if ( (tb->tm_yday > dstend.yd) && (tb->tm_yday < dststart.yd) )
|
|
return 0;
|
|
}
|
|
|
|
ms = 1000L * (tb->tm_sec + 60L * tb->tm_min + 3600L * tb->tm_hour);
|
|
|
|
if ( tb->tm_yday == dststart.yd ) {
|
|
if ( ms >= dststart.ms )
|
|
return 1;
|
|
else
|
|
return 0;
|
|
}
|
|
else {
|
|
/*
|
|
* tb->tm_yday == dstend.yd
|
|
*/
|
|
if ( ms < dstend.ms )
|
|
return 1;
|
|
else
|
|
return 0;
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#else /* _WIN32 */
|
|
|
|
#if defined (_M_MPPC) || defined (_M_M68K)
|
|
|
|
|
|
#include <cruntime.h>
|
|
#include <ctype.h>
|
|
#include <ctime.h>
|
|
#include <time.h>
|
|
#include <stdlib.h>
|
|
#include <internal.h>
|
|
#include <string.h>
|
|
#include <macos\script.h>
|
|
#include <macos\osutils.h>
|
|
|
|
/***
|
|
*void tzset() - sets timezone information and calc if in daylight time
|
|
*
|
|
*Purpose:
|
|
* Sets the timezone information from the TZ environment variable
|
|
* and then sets _timezone, _daylight, and _tzname. If we're in daylight
|
|
* time is automatically calculated.
|
|
*
|
|
*Entry:
|
|
* None, reads TZ environment variable.
|
|
*
|
|
*Exit:
|
|
* sets _daylight, _timezone, and _tzname global vars, no return value
|
|
*
|
|
*Exceptions:
|
|
*
|
|
*******************************************************************************/
|
|
|
|
void __cdecl _tzset (
|
|
void
|
|
)
|
|
{
|
|
REG1 char *TZ;
|
|
char *lastTZ=NULL;
|
|
MachineLocation ml;
|
|
long gmtDelta;
|
|
REG2 int negdiff = 0;
|
|
|
|
/*
|
|
* Fetch the value of the TZ environment variable. If there is no TZ
|
|
* environment variable, or if it is trivial, then the timezone
|
|
* information will be taken from the OS.
|
|
*/
|
|
|
|
if ( (TZ = getenv("TZ")) && (*TZ) ) {
|
|
/*
|
|
* TZ environment variable exists and is non-trivial. See if
|
|
* it is unchanged from a previous _tzset call.
|
|
*/
|
|
if ( (lastTZ == NULL) || (strcmp(TZ, lastTZ) != 0) ) {
|
|
/*
|
|
* TZ has changed, or there has been no prior _tzset call.
|
|
* Update lastTZ value.
|
|
*/
|
|
free(lastTZ);
|
|
lastTZ = _strdup(TZ);
|
|
}
|
|
else {
|
|
/*
|
|
* Timezone environment variable hasn't changed since the
|
|
* last _tzset call, just return.
|
|
*/
|
|
return;
|
|
|
|
}
|
|
}
|
|
else {
|
|
/*
|
|
* The TZ environment variable either does not exist, or is
|
|
* trivial. Therefore, timezone information will be obtained
|
|
* from the OS.
|
|
*/
|
|
if ( lastTZ != NULL ) {
|
|
free(lastTZ);
|
|
lastTZ = NULL;
|
|
}
|
|
ReadLocation(&ml);
|
|
//get gmtDelta from machinelocation in RAM
|
|
gmtDelta = ml.u.gmtDelta & 0x00ffffff;
|
|
|
|
if ((gmtDelta >> 23) & 1) //need to sign extend
|
|
gmtDelta = gmtDelta | 0xff000000;
|
|
|
|
//set timezone and daylight
|
|
_timezone = - gmtDelta;
|
|
_daylight = (ml.u.dlsDelta ? 1 : 0);
|
|
*_tzname[0] = '\0';
|
|
*_tzname[1] = '\0';
|
|
return;
|
|
}
|
|
|
|
strncpy(_tzname[0], TZ, 3);
|
|
|
|
/*
|
|
* time difference is of the form:
|
|
*
|
|
* [+|-]hh[:mm[:ss]]
|
|
*
|
|
* check minus sign first.
|
|
*/
|
|
if ( *(TZ += 3) == '-' ) {
|
|
negdiff++;
|
|
TZ++;
|
|
}
|
|
|
|
/*
|
|
* process, then skip over, the hours
|
|
*/
|
|
_timezone = atol(TZ) * 3600L;
|
|
|
|
while ( (*TZ == '+') || ((*TZ >= '0') && (*TZ <= '9')) ) TZ++;
|
|
|
|
/*
|
|
* check if minutes were specified
|
|
*/
|
|
if ( *TZ == ':' ) {
|
|
/*
|
|
* process, then skip over, the minutes
|
|
*/
|
|
_timezone += atol(++TZ) * 60L;
|
|
while ( (*TZ >= '0') && (*TZ <= '9') ) TZ++;
|
|
|
|
/*
|
|
* check if seconds were specified
|
|
*/
|
|
if ( *TZ == ':' ) {
|
|
/*
|
|
* process, then skip over, the seconds
|
|
*/
|
|
_timezone += atol(++TZ);
|
|
while ( (*TZ >= '0') && (*TZ <= '9') ) TZ++;
|
|
}
|
|
}
|
|
if ( negdiff )
|
|
_timezone = -_timezone;
|
|
|
|
/*
|
|
* finally, check for a DST zone suffix
|
|
*/
|
|
if (*TZ)
|
|
strncpy(_tzname[1], TZ, 3);
|
|
else
|
|
*_tzname[1] = '\0';
|
|
_daylight = *_tzname[1] != '\0';
|
|
}
|
|
|
|
/*
|
|
* _isindst - Tells whether Xenix-type time value falls under DST
|
|
*
|
|
* This is the rule for years before 1987:
|
|
* a time is in DST iff it is on or after 02:00:00 on the last Sunday
|
|
* in April and before 01:00:00 on the last Sunday in October.
|
|
* This is the rule for years starting with 1987:
|
|
* a time is in DST iff it is on or after 02:00:00 on the first Sunday
|
|
* in April and before 01:00:00 on the last Sunday in October.
|
|
*
|
|
* ENTRY tb - 'time' structure holding broken-down time value
|
|
*
|
|
* RETURN 1 if time represented is in DST, else 0
|
|
*/
|
|
|
|
int __cdecl _isindst (
|
|
REG1 struct tm *tb
|
|
)
|
|
{
|
|
int mdays;
|
|
REG2 int yr;
|
|
int lastsun;
|
|
|
|
/* If the month is before April or after October, then we know
|
|
* immediately it can't be DST. */
|
|
|
|
if (tb->tm_mon < 3 || tb->tm_mon > 9)
|
|
return(0);
|
|
|
|
/* If the month is after April and before October then we know
|
|
* immediately it must be DST. */
|
|
|
|
if (tb->tm_mon > 3 && tb->tm_mon < 9)
|
|
return(1);
|
|
/*
|
|
* Now for the hard part. Month is April or October; see if date
|
|
* falls between appropriate Sundays.
|
|
*/
|
|
|
|
/*
|
|
* The objective for years before 1987 (after 1986) is to determine
|
|
* if the day is on or after 2:00 am on the last (first) Sunday in
|
|
* April, or before 1:00 am on the last Sunday in October.
|
|
*
|
|
* We know the year-day (0..365) of the current time structure. We must
|
|
* determine the year-day of the last (first) Sunday in this month,
|
|
* April or October, and then do the comparison.
|
|
*
|
|
* To determine the year-day of the last Sunday, we do the following:
|
|
* 1. Get the year-day of the last day of the current month (Apr
|
|
* or Oct)
|
|
* 2. Determine the week-day number of #1,
|
|
* which is defined as 0 = Sun, 1 = Mon, ... 6 = Sat
|
|
* 3. Subtract #2 from #1
|
|
*
|
|
* To determine the year-day of the first Sunday, we do the following:
|
|
* 1. Get the year-day of the 7th day of the current month (April)
|
|
* 2. Determine the week-day number of #1,
|
|
* which is defined as 0 = Sun, 1 = Mon, ... 6 = Sat
|
|
* 3. Subtract #2 from #1
|
|
*/
|
|
|
|
yr = tb->tm_year + 1900; /* To see if this is a leap-year */
|
|
|
|
/* First we get #1. The year-days for each month are stored in _days[]
|
|
* they're all off by -1 */
|
|
|
|
if (yr > 1986 && tb->tm_mon == 3)
|
|
mdays = 7 + _days[tb->tm_mon];
|
|
else
|
|
mdays = _days[tb->tm_mon+1];
|
|
|
|
/* if this is a leap-year, add an extra day */
|
|
if (!(yr & 3))
|
|
mdays++;
|
|
|
|
/* mdays now has #1 */
|
|
|
|
yr = tb->tm_year - 70;
|
|
|
|
/* Now get #2. We know the week-day number of the beginning of the
|
|
* epoch, Jan. 1, 1970, which is defined as the constant _BASE_DOW. We
|
|
* then add the number of days that have passed from _BASE_DOW to the day
|
|
* of #2
|
|
* mdays + 365 * yr
|
|
* correct for the leap years which intervened
|
|
* + (yr + 1)/ 4
|
|
* and take the result mod 7, except that 0 must be mapped to 7.
|
|
* This is #2, which we then subtract from #1, mdays
|
|
*/
|
|
|
|
lastsun = mdays - ((mdays + 365*yr + ((yr+1)/4) + _BASE_DOW) % 7);
|
|
|
|
/* Now we know 1 and 3; we're golden: */
|
|
|
|
return (tb->tm_mon==3
|
|
? (tb->tm_yday > lastsun ||
|
|
(tb->tm_yday == lastsun && tb->tm_hour >= 2))
|
|
: (tb->tm_yday < lastsun ||
|
|
(tb->tm_yday == lastsun && tb->tm_hour < 1)));
|
|
}
|
|
|
|
|
|
|
|
|
|
#endif /* defined (_M_MPPC) || defined (_M_M68K) */
|
|
|
|
#endif /* _WIN32 */
|