Tcl Source Code

Artifact [c68025184e]
Login

Artifact c68025184e820f780af43b73fbd5c5a80abcd927:

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 */