Attachment "gmttz.patch" to
ticket [559376ffff]
added by
hobbs
2002-05-25 02:32:56.
Index: compat/strftime.c
===================================================================
RCS file: /cvsroot/tcl/tcl/compat/strftime.c,v
retrieving revision 1.7.2.1
diff -b -u -r1.7.2.1 strftime.c
--- compat/strftime.c 17 Oct 2001 19:29:24 -0000 1.7.2.1
+++ compat/strftime.c 24 May 2002 19:20:56 -0000
@@ -8,6 +8,8 @@
* source. See the copyright notice below for details on redistribution
* restrictions. The "license.terms" file does not apply to this file.
*
+ * Changes 2002 Copyright (c) 2002 ActiveState Corporation.
+ *
* RCS: @(#) $Id: strftime.c,v 1.7.2.1 2001/10/17 19:29:24 das Exp $
*/
@@ -69,6 +71,12 @@
const char *t_fmt_ampm;
} _TimeLocale;
+/*
+ * This is the C locale default. On Windows, if we wanted to make this
+ * localized, we would use GetLocaleInfo to get the correct values.
+ * It may be acceptable to do localization of month/day names, as the
+ * numerical values would be considered the locale-independent versions.
+ */
static const _TimeLocale _DefaultTimeLocale =
{
{
@@ -97,6 +105,7 @@
static const _TimeLocale *_CurrentTimeLocale = &_DefaultTimeLocale;
+static int isGMT;
static size_t gsize;
static char *pt;
static int _add _ANSI_ARGS_((const char* str));
@@ -106,11 +115,12 @@
const struct tm *t));
size_t
-TclpStrftime(s, maxsize, format, t)
+TclpStrftime(s, maxsize, format, t, useGMT)
char *s;
size_t maxsize;
const char *format;
const struct tm *t;
+ int useGMT;
{
if (format[0] == '%' && format[1] == 'Q') {
/* Format as a stardate */
@@ -122,6 +132,11 @@
return(strlen(s));
}
+ isGMT = useGMT;
+ /*
+ * We may be able to skip this for useGMT, but it should be harmless.
+ * -- hobbs
+ */
tzset();
pt = s;
@@ -144,6 +159,20 @@
const char *format;
const struct tm *t;
{
+#ifdef WIN32
+#define BUF_SIZ 256
+ TCHAR buf[BUF_SIZ];
+ SYSTEMTIME syst = {
+ t->tm_year + 1900,
+ t->tm_mon + 1,
+ t->tm_wday,
+ t->tm_mday,
+ t->tm_hour,
+ t->tm_min,
+ t->tm_sec,
+ 0,
+ };
+#endif
for (; *format; ++format) {
if (*format == '%') {
++format;
@@ -188,10 +217,6 @@
2, '0'))
return(0);
continue;
- case 'c':
- if (!_fmt(_CurrentTimeLocale->d_t_fmt, t))
- return(0);
- continue;
case 'D':
if (!_fmt("%m/%d/%y", t))
return(0);
@@ -307,6 +332,38 @@
if (!_conv(t->tm_wday, 1, '0'))
return(0);
continue;
+#ifdef WIN32
+ /*
+ * To properly handle the localized time routines on Windows,
+ * we must make use of the special localized calls.
+ */
+ case 'c':
+ if (!GetDateFormat(LOCALE_USER_DEFAULT, DATE_LONGDATE,
+ &syst, NULL, buf, BUF_SIZ) || !_add(buf)
+ || !_add(" ")) {
+ return(0);
+ }
+ /*
+ * %c is created with LONGDATE + " " + TIME on Windows,
+ * so continue to %X case here.
+ */
+ case 'X':
+ if (!GetTimeFormat(LOCALE_USER_DEFAULT, 0,
+ &syst, NULL, buf, BUF_SIZ) || !_add(buf)) {
+ return(0);
+ }
+ continue;
+ case 'x':
+ if (!GetDateFormat(LOCALE_USER_DEFAULT, DATE_SHORTDATE,
+ &syst, NULL, buf, BUF_SIZ) || !_add(buf)) {
+ return(0);
+ }
+ continue;
+#else
+ case 'c':
+ if (!_fmt(_CurrentTimeLocale->d_t_fmt, t))
+ return(0);
+ continue;
case 'x':
if (!_fmt(_CurrentTimeLocale->d_fmt, t))
return(0);
@@ -315,6 +372,7 @@
if (!_fmt(_CurrentTimeLocale->t_fmt, t))
return(0);
continue;
+#endif
case 'y':
if (!_conv((t->tm_year + TM_YEAR_BASE) % 100,
2, '0'))
@@ -325,7 +383,7 @@
return(0);
continue;
case 'Z': {
- char *name = TclpGetTZName(t->tm_isdst);
+ char *name = (isGMT ? "GMT" : TclpGetTZName(t->tm_isdst));
if (name && !_add(name)) {
return 0;
}
Index: generic/tclClock.c
===================================================================
RCS file: /cvsroot/tcl/tcl/generic/tclClock.c,v
retrieving revision 1.9.2.1
diff -b -u -r1.9.2.1 tclClock.c
--- generic/tclClock.c 7 Aug 2000 21:30:56 -0000 1.9.2.1
+++ generic/tclClock.c 24 May 2002 19:20:56 -0000
@@ -289,11 +289,12 @@
return TCL_OK;
}
-#ifndef HAVE_TM_ZONE
+#if !defined(HAVE_TM_ZONE) && !defined(WIN32)
/*
* This is a kludge for systems not having the timezone string in
* struct tm. No matter what was specified, they use the local
- * timezone string.
+ * timezone string. We don't do this on Windows because setting
+ * env vars there is a known mem leak in msvcrt.dll.
*/
if (useGMT) {
@@ -332,10 +333,10 @@
Tcl_MutexLock(&clockMutex);
result = TclpStrftime(buffer.string, (unsigned int) bufSize, format,
- timeDataPtr);
+ timeDataPtr, useGMT);
Tcl_MutexUnlock(&clockMutex);
-#ifndef HAVE_TM_ZONE
+#if !defined(HAVE_TM_ZONE) && !defined(WIN32)
if (useGMT) {
if (savedTZEnv != NULL) {
Tcl_SetVar2(interp, "env", "TZ", savedTZEnv, TCL_GLOBAL_ONLY);
Index: generic/tclInt.decls
===================================================================
RCS file: /cvsroot/tcl/tcl/generic/tclInt.decls,v
retrieving revision 1.20.2.6
diff -b -u -r1.20.2.6 tclInt.decls
--- generic/tclInt.decls 17 Oct 2001 19:29:25 -0000 1.20.2.6
+++ generic/tclInt.decls 24 May 2002 19:20:56 -0000
@@ -503,7 +503,7 @@
}
declare 134 generic {
size_t TclpStrftime(char *s, size_t maxsize, CONST char *format, \
- CONST struct tm *t)
+ CONST struct tm *t, int useGMT)
}
declare 135 generic {
int TclpCheckStackSpace(void)
Index: generic/tclIntDecls.h
===================================================================
RCS file: /cvsroot/tcl/tcl/generic/tclIntDecls.h,v
retrieving revision 1.19.2.2
diff -b -u -r1.19.2.2 tclIntDecls.h
--- generic/tclIntDecls.h 15 Oct 2001 20:27:23 -0000 1.19.2.2
+++ generic/tclIntDecls.h 24 May 2002 19:20:56 -0000
@@ -453,7 +453,8 @@
EXTERN struct tm * TclpGetDate _ANSI_ARGS_((TclpTime_t time, int useGMT));
/* 134 */
EXTERN size_t TclpStrftime _ANSI_ARGS_((char * s, size_t maxsize,
- CONST char * format, CONST struct tm * t));
+ CONST char * format, CONST struct tm * t,
+ int useGMT));
/* 135 */
EXTERN int TclpCheckStackSpace _ANSI_ARGS_((void));
/* Slot 136 is reserved */
@@ -705,7 +706,7 @@
void (*tcl_SetNamespaceResolvers) _ANSI_ARGS_((Tcl_Namespace * namespacePtr, Tcl_ResolveCmdProc * cmdProc, Tcl_ResolveVarProc * varProc, Tcl_ResolveCompiledVarProc * compiledVarProc)); /* 131 */
int (*tclpHasSockets) _ANSI_ARGS_((Tcl_Interp * interp)); /* 132 */
struct tm * (*tclpGetDate) _ANSI_ARGS_((TclpTime_t time, int useGMT)); /* 133 */
- size_t (*tclpStrftime) _ANSI_ARGS_((char * s, size_t maxsize, CONST char * format, CONST struct tm * t)); /* 134 */
+ size_t (*tclpStrftime) _ANSI_ARGS_((char * s, size_t maxsize, CONST char * format, CONST struct tm * t, int useGMT)); /* 134 */
int (*tclpCheckStackSpace) _ANSI_ARGS_((void)); /* 135 */
void *reserved136;
int (*tclpChdir) _ANSI_ARGS_((CONST char * dirName)); /* 137 */
Index: tests/clock.test
===================================================================
RCS file: /cvsroot/tcl/tcl/tests/clock.test,v
retrieving revision 1.13.2.3
diff -b -u -r1.13.2.3 clock.test
--- tests/clock.test 18 Oct 2001 20:17:17 -0000 1.13.2.3
+++ tests/clock.test 24 May 2002 19:20:56 -0000
@@ -427,6 +427,19 @@
[clock format [clock scan year -base $5amPST -gmt 1] -format $fmt]
} {12/31 12/31}
+set ::tcltest::testConstraints(needPST) \
+ [regexp {^(Pacific.*|P[DS]T)$} [clock format 1 -format %Z]]
+test clock-9.1 {%s gmt testing} {needPST} {
+ # We need PST to guarantee the difference value below.
+ set s 100000
+ set a [clock format $s -format %s -gmt 0]
+ set b [clock format $s -format %s -gmt 1]
+ # This should be the offset in seconds between current locale and GMT.
+ # This didn't seem to be correctly on Windows until the fix for
+ # Bug #559376, which fiddled with env(TZ) when -gmt 1 was used.
+ # It's hard-coded to check P[SD]T now. (8 hours)
+ set c [expr {$b-$a}]
+} {28800}
# cleanup
::tcltest::cleanupTests
Index: unix/tclUnixTime.c
===================================================================
RCS file: /cvsroot/tcl/tcl/unix/tclUnixTime.c,v
retrieving revision 1.7
diff -b -u -r1.7 tclUnixTime.c
--- unix/tclUnixTime.c 14 Jan 2000 22:15:52 -0000 1.7
+++ unix/tclUnixTime.c 24 May 2002 19:20:56 -0000
@@ -279,7 +279,8 @@
*
* TclpStrftime --
*
- * On Unix, we can safely call the native strftime implementation.
+ * On Unix, we can safely call the native strftime implementation,
+ * and also ignore the useGMT parameter.
*
* Results:
* The normal strftime result.
@@ -291,11 +292,12 @@
*/
size_t
-TclpStrftime(s, maxsize, format, t)
+TclpStrftime(s, maxsize, format, t, useGMT)
char *s;
size_t maxsize;
CONST char *format;
CONST struct tm *t;
+ int useGMT;
{
if (format[0] == '%' && format[1] == 'Q') {
/* Format as a stardate */