Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Bug in Time::localtime? #6183

Closed
p5pRT opened this issue Dec 24, 2002 · 14 comments
Closed

Bug in Time::localtime? #6183

p5pRT opened this issue Dec 24, 2002 · 14 comments

Comments

@p5pRT
Copy link

p5pRT commented Dec 24, 2002

Migrated from rt.perl.org#19393 (status was 'resolved')

Searchable as RT19393$

@p5pRT
Copy link
Author

p5pRT commented Dec 24, 2002

From j.pritchard@eso.org

This is a bug report for perl from j.pritchard@​eso.org,
generated with the help of perlbug 1.34 running under perl v5.8.0.


The following script​:

<--Start-->
#! /usr/bin/perl

use Time​::Local;
use Time​::gmtime;
use Time​::localtime;

my $dateda=timelocal(0,0,0,12,9,2002);
printf("timelocal(0,0,0,12,9,2002) ==> %04d-%02d-%02d\n",(localtime($dateda)->year()+1900),(localtime($dateda)->mon()),localtime($dateda)->mday() );
$dateda=timelocal(0,0,0,13,9,2002);
printf("timelocal(0,0,0,13,9,2002) ==> %04d-%02d-%02d\n",(localtime($dateda)->year()+1900),(localtime($dateda)->mon()),localtime($dateda)->mday() );
$dateda=timelocal(0,0,0,14,9,2002);
printf("timelocal(0,0,0,14,9,2002) ==> %04d-%02d-%02d\n",(localtime($dateda)->year()+1900),(localtime($dateda)->mon()),localtime($dateda)->mday() );

<--End-->

produces the following output...

timelocal(0,0,0,12,9,2002) ==> 2002-09-12
timelocal(0,0,0,13,9,2002) ==> 2002-09-12
timelocal(0,0,0,14,9,2002) ==> 2002-09-14

Am I doing something wrong or is there a problem here?

Thanks in advance...
John Pritchard



Flags​:
  category=core
  severity=low


Site configuration information for perl v5.8.0​:

Configured by bhcompile at Sun Sep 1 23​:55​:07 EDT 2002.

Summary of my perl5 (revision 5.0 version 8 subversion 0) configuration​:
  Platform​:
  osname=linux, osvers=2.4.18-11smp, archname=i386-linux-thread-multi
  uname='linux daffy.perf.redhat.com 2.4.18-11smp #1 smp thu aug 15 06​:41​:59 edt 2002 i686 i686 i386 gnulinux '
  config_args='-des -Doptimize=-O2 -march=i386 -mcpu=i686 -Dmyhostname=localhost -Dperladmin=root@​localhost -Dcc=gcc -Dcf_by=Red Hat, Inc. -Dinstallprefix=/usr -Dprefix=/usr -Darchname=i386-linux -Dvendorprefix=/usr -Dsiteprefix=/usr -Duseshrplib -Dusethreads -Duseithreads -Duselargefiles -Dd_dosuid -Dd_semctl_semun -Di_db -Ui_ndbm -Di_gdbm -Di_shadow -Di_syslog -Dman3ext=3pm -Duseperlio -Dinstallusrbinperl -Ubincompat5005 -Uversiononly -Dpager=/usr/bin/less -isr'
  hint=recommended, useposix=true, d_sigaction=define
  usethreads=define use5005threads=undef useithreads=define usemultiplicity=define
  useperlio=define d_sfio=undef uselargefiles=define usesocks=undef
  use64bitint=undef use64bitall=undef uselongdouble=undef
  usemymalloc=n, bincompat5005=undef
  Compiler​:
  cc='gcc', ccflags ='-D_REENTRANT -D_GNU_SOURCE -fno-strict-aliasing -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64 -I/usr/include/gdbm',
  optimize='-O2 -march=i386 -mcpu=i686',
  cppflags='-D_REENTRANT -D_GNU_SOURCE -fno-strict-aliasing -I/usr/include/gdbm'
  ccversion='', gccversion='3.2 20020822 (Red Hat Linux Rawhide 3.2-5)', gccosandvers=''
  intsize=4, longsize=4, ptrsize=4, doublesize=8, byteorder=1234
  d_longlong=define, longlongsize=8, d_longdbl=define, longdblsize=12
  ivtype='long', ivsize=4, nvtype='double', nvsize=8, Off_t='off_t', lseeksize=8
  alignbytes=4, prototype=define
  Linker and Libraries​:
  ld='gcc', ldflags =' -L/usr/local/lib'
  libpth=/usr/local/lib /lib /usr/lib
  libs=-lnsl -lgdbm -ldb -ldl -lm -lpthread -lc -lcrypt -lutil
  perllibs=-lnsl -ldl -lm -lpthread -lc -lcrypt -lutil
  libc=/lib/libc-2.2.92.so, so=so, useshrplib=true, libperl=libperl.so
  gnulibc_version='2.2.92'
  Dynamic Linking​:
  dlsrc=dl_dlopen.xs, dlext=so, d_dlsymun=undef, ccdlflags='-rdynamic -Wl,-rpath,/usr/lib/perl5/5.8.0/i386-linux-thread-multi/CORE'
  cccdlflags='-fpic', lddlflags='-shared -L/usr/local/lib'

Locally applied patches​:
 


@​INC for perl v5.8.0​:
  /usr/lib/perl5/5.8.0/i386-linux-thread-multi
  /usr/lib/perl5/5.8.0
  /usr/lib/perl5/site_perl/5.8.0/i386-linux-thread-multi
  /usr/lib/perl5/site_perl/5.8.0
  /usr/lib/perl5/site_perl/5.6.1
  /usr/lib/perl5/site_perl
  /usr/lib/perl5/vendor_perl/5.8.0/i386-linux-thread-multi
  /usr/lib/perl5/vendor_perl/5.8.0
  /usr/lib/perl5/vendor_perl/5.6.1
  /usr/lib/perl5/vendor_perl
  .


Environment for perl v5.8.0​:
  HOME=/home/jpritcha
  LANG=en_NZ
  LANGUAGE (unset)
  LD_LIBRARY_PATH=/midas/02FEB/lib​:/midas/98NOV/lib​:/usr/local/astro/Linux-ix86/star/share​:/usr/local/astro/Linux-ix86/star/share​:/usr/local/astro/Linux-ix86/star/share​:/usr/local/astro/Linux-ix86/star/share​:/usr/local/astro/Linux-ix86/star/share
  LOGDIR (unset)
  PATH=/astro/jdp/bin​:/home/jpritcha/bin/Linux-ix86​:/home/jpritcha/bin​:/usr/local/bin​:/usr/local/astro/Linux-ix86/bin​:/usr/local/astro/common/scripts​:/usr/local/astro/eb/bin/Linux-ix86​:/usr/local/astro/eb/bin​:/midas/02FEB/contrib/exec​:/midas/02FEB/gui/exec​:/sbin​:/usr/sbin​:/usr/local/astro/Linux-ix86/p2pp/bin​:/usr/bin​:/bin​:/usr/X11R6/bin​:.​:/usr/local/astro/Linux-ix86/star/bin​:/usr/local/astro/Linux-ix86/autoCd/autoCd
  PERL_BADLANG (unset)
  SHELL=/bin/tcsh

@p5pRT
Copy link
Author

p5pRT commented Dec 26, 2002

From @andk

On 24 Dec 2002 03​:13​:40 -0000, "j.pritchard@​eso.org (via RT)" <perlbug-followup@​perl.org> said​:

  > # New Ticket Created by j.pritchard@​eso.org
  > # Please include the string​: [perl #19393]
  > # in the subject line of all future correspondence about this issue.
  > # <URL​: http​://rt.perl.org/rt2/Ticket/Display.html?id=19393 >

  > This is a bug report for perl from j.pritchard@​eso.org,
  > generated with the help of perlbug 1.34 running under perl v5.8.0.

  > -----------------------------------------------------------------
  > The following script​:

  > <--Start-->
  > #! /usr/bin/perl

  > use Time​::Local;
  > use Time​::gmtime;
  > use Time​::localtime;

  > my $dateda=timelocal(0,0,0,12,9,2002);
  > printf("timelocal(0,0,0,12,9,2002) ==> %04d-%02d-%02d\n",(localtime($dateda)->year()+1900),(localtime($dateda)->mon()),localtime($dateda)->mday() );
  > $dateda=timelocal(0,0,0,13,9,2002);
  > printf("timelocal(0,0,0,13,9,2002) ==> %04d-%02d-%02d\n",(localtime($dateda)->year()+1900),(localtime($dateda)->mon()),localtime($dateda)->mday() );
  > $dateda=timelocal(0,0,0,14,9,2002);
  > printf("timelocal(0,0,0,14,9,2002) ==> %04d-%02d-%02d\n",(localtime($dateda)->year()+1900),(localtime($dateda)->mon()),localtime($dateda)->mday() );

  > <--End-->

  > produces the following output...

  > timelocal(0,0,0,12,9,2002) ==> 2002-09-12
  > timelocal(0,0,0,13,9,2002) ==> 2002-09-12
  > timelocal(0,0,0,14,9,2002) ==> 2002-09-14

FWIW, I cannot reproduce this here, I get

timelocal(0,0,0,12,9,2002) ==> 2002-09-12
timelocal(0,0,0,13,9,2002) ==> 2002-09-13
timelocal(0,0,0,14,9,2002) ==> 2002-09-14

Maybe it's time-zone or daylight-saving-time dependent?

--
andreas

@p5pRT
Copy link
Author

p5pRT commented Dec 27, 2002

From j.pritchard@eso.org

"Andreas Koenig (via RT)" wrote​:

Maybe it's time-zone or daylight-saving-time dependent?

Seems you are right...

encue​: ~/tmp> setenv TZ Chile/Continental
encue​: ~/tmp> date
Thu Dec 26 17​:18​:53 CLST 2002
encue​: ~/tmp> dtest2.pl
timelocal(0,0,0,12,9,2002) ==> 2002-09-12
timelocal(0,0,0,13,9,2002) ==> 2002-09-12
timelocal(0,0,0,14,9,2002) ==> 2002-09-14
encue​: ~/tmp> setenv TZ UTC
encue​: ~/tmp> date
Thu Dec 26 20​:20​:14 UTC 2002
encue​: ~/tmp> dtest2.pl
timelocal(0,0,0,12,9,2002) ==> 2002-09-12
timelocal(0,0,0,13,9,2002) ==> 2002-09-13
timelocal(0,0,0,14,9,2002) ==> 2002-09-14

So does this make it a bug or a feature???

John

-- + -- John Pritchard (2p2 Team, La Silla Observatory)
  +E S+ European Southern Observatory
  O Alonso de Cordova 3107, Vitacura, Santiago 19-Chile
  Off​: +56 2 463 3093 fx​: +56 2 463 3001
  mailto​:j.pritchard@​eso.org
-- + -- http​://www.sc.eso.org/~jpritcha

@p5pRT
Copy link
Author

p5pRT commented Dec 27, 2002

From @iabyn

On Thu, Dec 26, 2002 at 05​:21​:14PM -0300, John Pritchard wrote​:

"Andreas Koenig (via RT)" wrote​:

Maybe it's time-zone or daylight-saving-time dependent?

Seems you are right...

encue​: ~/tmp> setenv TZ Chile/Continental
encue​: ~/tmp> date
Thu Dec 26 17​:18​:53 CLST 2002
encue​: ~/tmp> dtest2.pl
timelocal(0,0,0,12,9,2002) ==> 2002-09-12
timelocal(0,0,0,13,9,2002) ==> 2002-09-12
timelocal(0,0,0,14,9,2002) ==> 2002-09-14
encue​: ~/tmp> setenv TZ UTC
encue​: ~/tmp> date
Thu Dec 26 20​:20​:14 UTC 2002
encue​: ~/tmp> dtest2.pl
timelocal(0,0,0,12,9,2002) ==> 2002-09-12
timelocal(0,0,0,13,9,2002) ==> 2002-09-13
timelocal(0,0,0,14,9,2002) ==> 2002-09-14

So does this make it a bug or a feature???

It's just the transition to DST - there are two hours that map to the same
internal time, so Not-A-Bug.
ie at 00​:00, the clocks go back to 23​:00.

The following script​:

  use Time​::Local;
  use Time​::gmtime;
  use Time​::localtime;

  for my $day (12..13) {
  for my $hour ('00'..'23') {
  my $dateda=timelocal(0,0,$hour,$day,9,2002);
  printf("timelocal(0,0,$hour,$day,9,2002) ==> "
  . " %10d %04d-%02d-%02d %02d​:%02d​:%02d dst=%d\n",
  $dateda,
  localtime($dateda)->year()+1900,
  localtime($dateda)->mon(),
  localtime($dateda)->mday(),
  localtime($dateda)->hour(),
  localtime($dateda)->min(),
  localtime($dateda)->sec(),
  localtime($dateda)->isdst(),
  );
  }
  }

outputs​:

[davem@​percy davem]$ TZ=Chile/Continental perl5.8.0 /tmp/p
[snip]
timelocal(0,0,22,12,9,2002) ==> 1034474400 2002-09-12 22​:00​:00 dst=0
timelocal(0,0,23,12,9,2002) ==> 1034478000 2002-09-12 23​:00​:00 dst=0
timelocal(0,0,00,13,9,2002) ==> 1034478000 2002-09-12 23​:00​:00 dst=0
timelocal(0,0,01,13,9,2002) ==> 1034481600 2002-09-13 01​:00​:00 dst=1
timelocal(0,0,02,13,9,2002) ==> 1034485200 2002-09-13 02​:00​:00 dst=1
timelocal(0,0,03,13,9,2002) ==> 1034488800 2002-09-13 03​:00​:00 dst=1
...

--
"Emacs isn't a bad OS once you get used to it.
It just lacks a decent editor."

@p5pRT
Copy link
Author

p5pRT commented Dec 29, 2002

From j.pritchard@eso.org

"Dave Mitchell (via RT)" wrote​:

It's just the transition to DST - there are two hours that map to the same
internal time, so Not-A-Bug.
ie at 00​:00, the clocks go back to 23​:00.

Ahhhh, many thanks for the clarification and solution.

Best regards
John

-- + -- John Pritchard (Science Operations, La Silla Observatory)
  +E S+ European Southern Observatory
  O Alonso de Cordova 3107, Vitacura, Santiago 19-Chile
  Off​: +56 2 463 3093 fx​: +56 2 463 3001
  mailto​:j.pritchard@​eso.org
-- + -- http​://www.sc.eso.org/~jpritcha

@p5pRT
Copy link
Author

p5pRT commented Dec 29, 2002

From @jhi

I'm marking the problem ticket as resolved.

@p5pRT
Copy link
Author

p5pRT commented Dec 29, 2002

@jhi - Status changed from 'new' to 'resolved'

@p5pRT
Copy link
Author

p5pRT commented Dec 30, 2002

From perl5-porters@ton.iguana.be

In article <20021227215004.A28503@​_dgroup.com>,
  Dave Mitchell <davem@​fdgroup.com> writes​:

timelocal(0,0,0,12,9,2002) ==> 2002-09-12
timelocal(0,0,0,13,9,2002) ==> 2002-09-13
timelocal(0,0,0,14,9,2002) ==> 2002-09-14

So does this make it a bug or a feature???

It's just the transition to DST - there are two hours that map to the same
internal time, so Not-A-Bug.
ie at 00​:00, the clocks go back to 23​:00.

Well, not exactly​:

TZ=Chile/Continental perl -wle 'print join" ",localtime(1034477999)'
59 59 22 12 9 102 6 284 0
TZ=Chile/Continental perl -wle 'print join" ",localtime(1034477999+2)'
1 0 23 12 9 102 6 284 0
TZ=Chile/Continental perl -wle 'print join" ",localtime(1034477999+3600)'
59 59 23 12 9 102 6 284 0
TZ=Chile/Continental perl -wle 'print join" ",localtime(1034477999+3601)'
0 0 1 13 9 102 0 285 1
TZ=Chile/Continental perl -wle 'print join" ",localtime(1034477999+3602)'
1 0 1 13 9 102 0 285 1

So time actually skips 0​:00 to 1​:00, and there is no 0​:00 really.
Still, if you want to put it anywhere, it corresponds to
1034478000+3600=1034481600

So I'd call this a bug​:
TZ=Chile/Continental perl -MTime​::Local -wle 'print timelocal(0,0,0,13,9,2002)'
1034478000
TZ=Chile/Continental perl -MTime​::Local -wle 'print timelocal(0,0,0,13,9,102)'
1034478000

It should be either an error or 1034481600

PS for the original poster​:
Nobody puts the daylight saving jumps during the day, so if you want to
use timelocal/localtime for date manipulation, set the hour to 12, and use
things like​:
timelocal(0,0,12,13,9,102)

@p5pRT
Copy link
Author

p5pRT commented Jan 1, 2003

From @iabyn

On Mon, Dec 30, 2002 at 09​:58​:51PM +0000, Ton Hospel wrote​:

In article <20021227215004.A28503@​_dgroup.com>,
Dave Mitchell <davem@​fdgroup.com> writes​:

It's just the transition to DST - there are two hours that map to the same
internal time, so Not-A-Bug.
ie at 00​:00, the clocks go back to 23​:00.

Well, not exactly​:

[ snip]

So time actually skips 0​:00 to 1​:00, and there is no 0​:00 really.
Still, if you want to put it anywhere, it corresponds to
1034478000+3600=1034481600

So I'd call this a bug​:
TZ=Chile/Continental perl -MTime​::Local -wle 'print timelocal(0,0,0,13,9,2002)'
1034478000
TZ=Chile/Continental perl -MTime​::Local -wle 'print timelocal(0,0,0,13,9,102)'
1034478000

It should be either an error or 1034481600

D'oh - I got confused by Chile's clocks going fowards in the autumn,
whereas they go backwards in the UK and other places at that time :-(

So yes, its a bug.
Attached patch adjusts 'inbetween' dates to the DST-shifted equivalent.

--
"You're so sadly neglected, and often ignored.
A poor second to Belgium, When going abroad."
Monty Python - "Finland"

Inline Patch
--- lib/Time/Local.pm-	Wed Jan  1 21:24:34 2003
+++ lib/Time/Local.pm	Wed Jan  1 22:29:54 2003
@@ -132,7 +132,18 @@
 	or return $loc_t;
 
     # Adjust for DST change
-    $loc_t + $dst_off;
+    $loc_t += $dst_off;
+
+    # for a negative offset from GMT, and if the original date
+    # was a non-extent gap in a forward DST jump, we should
+    # now have the wrong answer - undo the DST adjust;
+
+    return $loc_t if $zone_off <= 0;
+
+    my ($s,$m,$h) = localtime($loc_t);
+    $loc_t -= $dst_off if $s != $_[0] || $m != $_[1] || $h != $_[2];
+
+    $loc_t;
 }
 
 
--- lib/Time/Local.t-	Wed Jan  1 21:24:45 2003
+++ lib/Time/Local.t	Wed Jan  1 22:47:17 2003
@@ -28,7 +28,7 @@
 # use vmsish 'time' makes for oddness around the Unix epoch
 if ($^O eq 'VMS') { $time[0][2]++ }
 
-print "1..", @time * 2 + 5, "\n";
+print "1..", @time * 2 + 6, "\n";
 
 $count = 1;
 for (@time) {
@@ -93,6 +93,20 @@
   or print "not ";
 print "ok ", $count++, "\n";
 
+# bugid #19393
+# At a DST transition, the clock skips forward, eg from 01:59:59 to
+# 03:00:00. In this case, 02:00:00 is an invalid time, and should be
+# treated like 03:00:00 rather than 01:00:00 - negative zone offsets used
+# to do the latter
+
+{
+    my $hour = (localtime(timelocal(0, 0, 2, 7, 3, 102)))[2];
+    # testers in US/Pacific should get 3,
+    # other testers should get 2
+    print "not " unless $hour == 2 || $hour == 3;
+    print "ok ", $main::count++, "\n";
+}
+
 
 #print "Testing timelocal.pl module too...\n";
 package test;

@p5pRT
Copy link
Author

p5pRT commented Jan 3, 2003

From @jhi

I think bug found, and patched, so I'm marking the problem ticket
as resolved.

@p5pRT
Copy link
Author

p5pRT commented Jan 3, 2003

@jhi - Status changed from 'open' to 'resolved'

@p5pRT
Copy link
Author

p5pRT commented Jan 16, 2003

From @rgs

Dave Mitchell wrote​:

Attached patch adjusts 'inbetween' dates to the DST-shifted equivalent.

Thanks, applied as #18497.

@p5pRT
Copy link
Author

p5pRT commented Mar 17, 2003

From @iabyn

closing (for 3rd time), since bug is fixed

@p5pRT
Copy link
Author

p5pRT commented Mar 17, 2003

@iabyn - Status changed from 'open' to 'resolved'

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant