📄 tzset.c
字号:
/***
*tzset.c - set timezone information and see if we're in daylight time
*
* Copyright (c) Microsoft Corporation. All rights reserved.
*
*Purpose:
* defines _tzset() - set timezone and daylight saving time vars
*
*******************************************************************************/
#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 (24 * 60 * 60 * 1000)
/*
* 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 */
int ms; /* milli-seconds in the day */
} transitiondate;
/*
* DST start and end structs.
*/
static transitiondate dststart = { -1, 0, 0 };
static transitiondate dstend = { -1, 0, 0 };
static int __cdecl _isindst_nolock(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:
*
*******************************************************************************/
static void __cdecl _tzset_nolock(void);
void __cdecl __tzset(void)
{
static int first_time = 0;
if ( !first_time ) {
_mlock( _TIME_LOCK );
__TRY
if ( !first_time ) {
_tzset_nolock();
first_time++;
}
__FINALLY
_munlock(_TIME_LOCK );
__END_TRY_FINALLY
}
}
void __cdecl _tzset (
void
)
{
_mlock( _TIME_LOCK );
__TRY
_tzset_nolock();
__FINALLY
_munlock( _TIME_LOCK );
__END_TRY_FINALLY
}
static void __cdecl _tzset_nolock (
void
)
{
const char *TZ;
int defused;
int negdiff = 0;
unsigned int lc_cp;
int nochange=FALSE;
long timezone = 0;
int daylight = 0;
long dstbias = 0;
char **tzname = NULL;
_mlock(_ENV_LOCK);
__TRY
_BEGIN_SECURE_CRT_DEPRECATION_DISABLE
tzname = _tzname;
_END_SECURE_CRT_DEPRECATION_DISABLE
_ERRCHECK(_get_timezone(&timezone));
_ERRCHECK(_get_daylight(&daylight));
_ERRCHECK(_get_dstbias(&dstbias));
/*
* Copy codepage to local (only really necessary for multithread case)
*/
lc_cp = ___lc_codepage_func();
/*
* 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_helper_nolock("TZ")) == NULL) || (*TZ =='\0') ) {
/*
* There is no TZ environment variable, try to use the time zone
* information from the system.
*/
/*
* If there is a lastTZ, discard it
*/
if ( lastTZ != NULL ) {
_free_crt(lastTZ);
lastTZ = NULL;
}
if ( GetTimeZoneInformation( &tzinfo ) != 0xFFFFFFFF ) {
/*
* Note that the API was used.
*/
tzapiused = 1;
/*
* Derive _timezone value from Bias and StandardBias fields.
*/
timezone = tzinfo.Bias * 60;
if ( tzinfo.StandardDate.wMonth != 0 )
timezone += (tzinfo.StandardBias * 60);
/*
* 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) *
60;
}
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_cp,
0,
tzinfo.StandardName,
-1,
tzname[0],
_TZ_STRINGS_SIZE - 1,
NULL,
&defused ) != 0) &&
(!defused) )
tzname[0][_TZ_STRINGS_SIZE - 1] = '\0';
else
tzname[0][0] = '\0';
if ( (WideCharToMultiByte( lc_cp,
0,
tzinfo.DaylightName,
-1,
tzname[1],
_TZ_STRINGS_SIZE - 1,
NULL,
&defused ) != 0) &&
(!defused) )
tzname[1][_TZ_STRINGS_SIZE - 1] = '\0';
else
tzname[1][0] = '\0';
}
/*
* Time zone information is unavailable, just return.
*/
nochange=TRUE;
}
else
{
if ( (lastTZ != NULL) && (strcmp(TZ, lastTZ) == 0) )
{
/*
* TZ is unchanged from a earlier call (to this function). Just
* return.
*/
nochange=TRUE;
}
else
{
/*
* Update lastTZ
*/
if ( lastTZ != NULL )
_free_crt(lastTZ);
if ((lastTZ = _malloc_crt(strlen(TZ)+1)) == NULL)
{
nochange=TRUE;
}
else
{
_ERRCHECK(strcpy_s(lastTZ, strlen(TZ) + 1, TZ));
}
}
}
_set_timezone(timezone);
_set_daylight(daylight);
_set_dstbias(dstbias);
__FINALLY
_munlock(_ENV_LOCK);
__END_TRY_FINALLY
if(!nochange)
{
/*
* Process TZ value and update _tzname, _timezone and _daylight.
*/
_ERRCHECK(strncpy_s(tzname[0], _TZ_STRINGS_SIZE, 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) * 3600;
while ( (*TZ == '+') || ((*TZ >= '0') && (*TZ <= '9')) ) TZ++;
/*
* check if minutes were specified
*/
if ( *TZ == ':' ) {
/*
* process, then skip over, the minutes
*/
timezone += atol(++TZ) * 60;
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
*/
daylight = *TZ;
if ( daylight ) {
_ERRCHECK(strncpy_s(tzname[1], _TZ_STRINGS_SIZE, TZ, 3));
}
else
*tzname[1] = '\0';
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -