Re: [perl #18238] timezone and gmt offset as output by POSIX::strftime() are sometim...
Slaven Rezic [Sat, 9 Nov 2002 23:21:16 +0000 (00:21 +0100)]
Message-ID: <874raqz8o3.fsf@vran.herceg.de>

p4raw-id: //depot/perl@18267

config_h.SH
ext/POSIX/t/posix.t
util.c

index 05d8ec2..6bd2039 100644 (file)
@@ -2994,10 +2994,15 @@ sed <<!GROK!THIS! >$CONFIG_H -e 's!^#undef\(.*/\)\*!/\*#define\1 \*!' -e 's!^#un
  *     This symbol, if defined, indicates to the C program that
  *     the struct tm has a tm_zone field.
  */
+/* HAS_TM_TM_GMTOFF:
+ *     This symbol, if defined, indicates to the C program that
+ *     the struct tm has a tm_gmtoff field.
+ */
 #$i_time I_TIME                /**/
 #$i_systime I_SYS_TIME         /**/
 #$i_systimek I_SYS_TIME_KERNEL         /**/
 #$d_tm_tm_zone HAS_TM_TM_ZONE          /**/
+#$d_tm_tm_gmtoff HAS_TM_TM_GMTOFF      /**/
 
 /* I_USTAT:
  *     This symbol, if defined, indicates that <ustat.h> exists and
index 01dba7f..9b0a751 100644 (file)
@@ -11,7 +11,7 @@ BEGIN {
 }
 
 require "./test.pl";
-plan(tests => 61);
+plan(tests => 66);
 
 
 use POSIX qw(fcntl_h signal_h limits_h _exit getcwd open read strftime write
@@ -183,6 +183,26 @@ try_strftime("Wed Mar 01 00:00:00 2000 061", 0,0,0, 1,2,100);
 try_strftime("Fri Mar 31 00:00:00 2000 091", 0,0,0, 31,2,100);
 &POSIX::setlocale(&POSIX::LC_TIME, $lc) if $Config{d_setlocale};
 
+SKIP: {
+    # XXX wait for smokers to see which OSs else to skip
+    skip("No mktime and/or tm_gmtoff", 5)
+       if !$Config{d_mktime} || !$Config{d_tm_tm_gmtoff} || !$Config{d_tm_tm_zone};
+    local $ENV{TZ} = "Europe/Berlin";
+
+    # May fail for ancient FreeBSD versions.
+    # %z is not included in POSIX, but valid on Linux and FreeBSD.
+    foreach $def ([1000,'Sun Sep  9 03:46:40 2001 +0200 CEST'],
+                 [900, 'Thu Jul  9 18:00:00 1998 +0200 CEST'],
+                 [800, 'Tue May  9 08:13:20 1995 +0200 CEST'],
+                 [700, 'Sat Mar  7 21:26:40 1992 +0100 CET'],
+                 [600, 'Thu Jan  5 11:40:00 1989 +0100 CET'],
+                ) {
+       my($t, $expected) = @$def;
+        my @tm = localtime($t*1000000);
+       is(strftime("%c %z %Z",@tm), $expected, "validating zone setting: $expected");
+    }
+}
+
 {
     for my $test (0, 1) {
        $! = 0;
diff --git a/util.c b/util.c
index 9a97a6b..b58a1b4 100644 (file)
--- a/util.c
+++ b/util.c
@@ -3388,6 +3388,20 @@ Perl_my_strftime(pTHX_ char *fmt, int sec, int min, int hour, int mday, int mon,
   mytm.tm_yday = yday;
   mytm.tm_isdst = isdst;
   mini_mktime(&mytm);
+  /* use libc to get the values for tm_gmtoff and tm_zone [perl #18238] */
+#if defined(HAS_MKTIME) && (defined(HAS_TM_TM_GMTOFF) || defined(HAS_TM_TM_ZONE))
+  STMT_START {
+    struct tm mytm2;
+    mytm2 = mytm;
+    mktime(&mytm2);
+#ifdef HAS_TM_TM_GMTOFF
+    mytm.tm_gmtoff = mytm2.tm_gmtoff;
+#endif
+#ifdef HAS_TM_TM_ZONE
+    mytm.tm_zone = mytm2.tm_zone;
+#endif
+  } STMT_END;
+#endif
   buflen = 64;
   New(0, buf, buflen, char);
   len = strftime(buf, buflen, fmt, &mytm);