summaryrefslogtreecommitdiff
path: root/tcl/win/tclWinTime.c
diff options
context:
space:
mode:
Diffstat (limited to 'tcl/win/tclWinTime.c')
-rw-r--r--tcl/win/tclWinTime.c129
1 files changed, 100 insertions, 29 deletions
diff --git a/tcl/win/tclWinTime.c b/tcl/win/tclWinTime.c
index c29a9ab9913..746739c98b5 100644
--- a/tcl/win/tclWinTime.c
+++ b/tcl/win/tclWinTime.c
@@ -4,7 +4,7 @@
* Contains Windows specific versions of Tcl functions that
* obtain time values from the operating system.
*
- * Copyright 1995 by Sun Microsystems, Inc.
+ * Copyright 1995-1998 by Sun Microsystems, Inc.
*
* See the file "license.terms" for information on usage and redistribution
* of this file, and for a DISCLAIMER OF ALL WARRANTIES.
@@ -12,8 +12,7 @@
* RCS: @(#) $Id$
*/
-#include "tclInt.h"
-#include "tclPort.h"
+#include "tclWinInt.h"
#define SECSPERDAY (60L * 60L * 24L)
#define SECSPERYEAR (SECSPERDAY * 365L)
@@ -32,6 +31,12 @@ static int leapDays[] = {
-1, 30, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365
};
+typedef struct ThreadSpecificData {
+ char tzName[64]; /* Time zone name */
+ struct tm tm; /* time information */
+} ThreadSpecificData;
+static Tcl_ThreadDataKey dataKey;
+
/*
* Declarations for functions defined later in this file.
*/
@@ -162,14 +167,73 @@ TclpGetTime(timePtr)
*/
char *
-TclpGetTZName()
+TclpGetTZName(int dst)
{
- tzset();
- if (_daylight && _tzname[1] != NULL) {
- return _tzname[1];
- } else {
- return _tzname[0];
+ int len;
+ char *zone, *p;
+ TIME_ZONE_INFORMATION tz;
+ Tcl_Encoding encoding;
+ ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
+ char *name = tsdPtr->tzName;
+
+ /*
+ * tzset() under Borland doesn't seem to set up tzname[] at all.
+ * tzset() under MSVC has the following weird observed behavior:
+ * First time we call "clock format [clock seconds] -format %Z -gmt 1"
+ * we get "GMT", but on all subsequent calls we get the current time
+ * zone string, even though env(TZ) is GMT and the variable _timezone
+ * is 0.
+ */
+
+ name[0] = '\0';
+
+ zone = getenv("TZ");
+ if (zone != NULL) {
+ /*
+ * TZ is of form "NST-4:30NDT", where "NST" would be the
+ * name of the standard time zone for this area, "-4:30" is
+ * the offset from GMT in hours, and "NDT is the name of
+ * the daylight savings time zone in this area. The offset
+ * and DST strings are optional.
+ */
+
+ len = strlen(zone);
+ if (len > 3) {
+ len = 3;
+ }
+ if (dst != 0) {
+ /*
+ * Skip the offset string and get the DST string.
+ */
+
+ p = zone + len;
+ p += strspn(p, "+-:0123456789");
+ if (*p != '\0') {
+ zone = p;
+ len = strlen(zone);
+ if (len > 3) {
+ len = 3;
+ }
+ }
+ }
+ Tcl_ExternalToUtf(NULL, NULL, zone, len, 0, NULL, name,
+ sizeof(tsdPtr->tzName), NULL, NULL, NULL);
}
+ if (name[0] == '\0') {
+ if (GetTimeZoneInformation(&tz) == TIME_ZONE_ID_UNKNOWN) {
+ /*
+ * MSDN: On NT this is returned if DST is not used in
+ * the current TZ
+ */
+ dst = 0;
+ }
+ encoding = Tcl_GetEncoding(NULL, "unicode");
+ Tcl_ExternalToUtf(NULL, encoding,
+ (char *) ((dst) ? tz.DaylightName : tz.StandardName), -1,
+ 0, NULL, name, sizeof(tsdPtr->tzName), NULL, NULL, NULL);
+ Tcl_FreeEncoding(encoding);
+ }
+ return name;
}
/*
@@ -191,10 +255,11 @@ TclpGetTZName()
*/
struct tm *
-TclpGetDate(tp, useGMT)
- const time_t *tp;
+TclpGetDate(t, useGMT)
+ TclpTime_t t;
int useGMT;
{
+ const time_t *tp = (const time_t *) t;
struct tm *tmPtr;
long time;
@@ -207,10 +272,11 @@ TclpGetDate(tp, useGMT)
* algorithm ignores daylight savings time before the epoch.
*/
- time = *tp - _timezone;
- if (time >= 0) {
+ if (*tp >= 0) {
return localtime(tp);
}
+
+ time = *tp - _timezone;
/*
* If we aren't near to overflowing the long, just add the bias and
@@ -272,7 +338,7 @@ TclpGetDate(tp, useGMT)
* the epoch (midnight Jan 1 1970).
*
* Results:
- * Returns a statically allocated struct tm.
+ * Returns a (per thread) statically allocated struct tm.
*
* Side effects:
* Updates the values of the static struct tm.
@@ -284,10 +350,13 @@ static struct tm *
ComputeGMT(tp)
const time_t *tp;
{
- static struct tm tm; /* This should be allocated per thread.*/
+ struct tm *tmPtr;
long tmp, rem;
int isLeap;
int *days;
+ ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
+
+ tmPtr = &tsdPtr->tm;
/*
* Compute the 4 year span containing the specified time.
@@ -327,47 +396,49 @@ ComputeGMT(tp)
}
}
}
- tm.tm_year = tmp;
+ tmPtr->tm_year = tmp;
/*
* Compute the day of year and leave the seconds in the current day in
* the remainder.
*/
- tm.tm_yday = rem / SECSPERDAY;
+ tmPtr->tm_yday = rem / SECSPERDAY;
rem %= SECSPERDAY;
/*
* Compute the time of day.
*/
- tm.tm_hour = rem / 3600;
+ tmPtr->tm_hour = rem / 3600;
rem %= 3600;
- tm.tm_min = rem / 60;
- tm.tm_sec = rem % 60;
+ tmPtr->tm_min = rem / 60;
+ tmPtr->tm_sec = rem % 60;
/*
* Compute the month and day of month.
*/
days = (isLeap) ? leapDays : normalDays;
- for (tmp = 1; days[tmp] < tm.tm_yday; tmp++) {
+ for (tmp = 1; days[tmp] < tmPtr->tm_yday; tmp++) {
}
- tm.tm_mon = --tmp;
- tm.tm_mday = tm.tm_yday - days[tmp];
+ tmPtr->tm_mon = --tmp;
+ tmPtr->tm_mday = tmPtr->tm_yday - days[tmp];
/*
* Compute day of week. Epoch started on a Thursday.
*/
- tm.tm_wday = (*tp / SECSPERDAY) + 4;
+ tmPtr->tm_wday = (*tp / SECSPERDAY) + 4;
if ((*tp % SECSPERDAY) < 0) {
- tm.tm_wday--;
+ tmPtr->tm_wday--;
}
- tm.tm_wday %= 7;
- if (tm.tm_wday < 0) {
- tm.tm_wday += 7;
+ tmPtr->tm_wday %= 7;
+ if (tmPtr->tm_wday < 0) {
+ tmPtr->tm_wday += 7;
}
- return &tm;
+ return tmPtr;
}
+
+