[Zope] Fix for DateTime.py regarding daylight saving time (was: Z2.log and Date stamps 2nd Call for answers????)

Gregor Hoffleit gregor@hoffleit.de
Fri, 28 Apr 2000 12:01:12 +0200


--V0207lvV8h4k8FAm
Content-Type: multipart/mixed; boundary="fUYQa+Pmc3FrFX/N"


--fUYQa+Pmc3FrFX/N
Content-Type: text/plain; charset=us-ascii
Content-Transfer-Encoding: quoted-printable

I hacked together a fix to DateTime.py for the problems wrt. daylight saving
time.

I still have the impression that DateTime.py is to some degree 'broken by
design' and don't know how to fix this completely without big changes to the
class. Still, the attached patch should fix the problems as described in the
"Z2.log and Date stamps" thread and as described in two Collector bug
reports (search for "daylight" and DateTime) in a backward compatible
manner.


To begin with, _localzone or tz is no immutable property during the life of
a Zope process (the switch to daylight saving time may happen while the Zope
process is running), still DateTime uses _localzone as an immutable class
attribute that's calculated only once during when the class is initialized.

Furthermore, the calculation of _localzone was broken: _localzone was always
set to the non-daylight saving timezone, even if we were currently in
daylight saving time. Problems arose when this was mixed with the variables
like hour, which were relative to the daylight saving time zone. I stick
with _localzone as the non-dst zone and introduce a new, immutable class
attribute _localdszone for the dst zone. Now the idea is to decide on
runtime if a localtime value is non-dst or dst. I think I found and
corrected the most obvious places in the class where this problem arises.


I'm quite confident that with the fix, DateTime now will always return a
correct date representation.

Potential problems remaining to be evaluated are that DateTime *perhaps*
still sometimes returns a non-dst localtime even for dates when dst was
valid in your local time zone, i.e. a correct but inappropriate result.

Still, that's much better than the current incorrect results.

    Gregor
   =20

--fUYQa+Pmc3FrFX/N
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment; filename="DateTime.py.diff"
Content-Transfer-Encoding: quoted-printable

--- DateTime.py.ORIG	Fri Apr 28 10:13:18 2000
+++ DateTime.py	Fri Apr 28 11:25:12 2000
@@ -179,7 +179,7 @@
            'GMT-0300','GMT-0400','GMT-0500','GMT-0600','GMT-0700',
            'GMT-0800','GMT-0900','GMT-1000','GMT-1100','GMT-1200',
            'GMT+1',
-           'UT','BST','CDT','MEST','SST','FST','WADT','EADT','NZDT',
+           'UT','BST','CDT','CEST','MEST','SST','FST','WADT','EADT','NZDT',
            'WET','WAT','AT','AST','NT','IDLW','CET','MET',
            'MEWT','SWT','FWT','EET','BT','ZP4','ZP5','ZP6',
            'WAST','CCT','JST','EAST','GST','NZT','NZST','IDLE']
@@ -254,7 +254,7 @@
            'us/samoa':'US/Samoa',
=20
            'ut':'Universal',     =20
-           'bst':'GMT+1', 'cdt':'GMT+2', 'mest':'GMT+2', 'sst':'GMT+2',
+           'bst':'GMT+1', 'cdt':'GMT+2', 'cest':'GMT+2', 'mest':'GMT+2', '=
sst':'GMT+2',
            'fst':'GMT+2', 'wadt':'GMT+8', 'eadt':'GMT+11', 'nzdt':'GMT+13',
            'wet':'GMT', 'wat':'GMT-1', 'at':'GMT-2', 'ast':'GMT-4',
            'nt':'GMT-11', 'idlw':'GMT-12', 'cet':'GMT+1', 'met':'GMT+1',
@@ -484,12 +484,16 @@
=20
         elif not args:
             # Current time, exp in local timezone
-            t,tz=3Dtime(),self._localzone
+            t=3Dtime()
             ms=3D(t-int(t))
             yr,mo,dy,hr,mn,sc=3Dgmtime(int(t))[:6]
             s=3D(hr/24.0+mn/1440.0+(sc+ms)/86400.0)
             d=3D(self._julianday(yr,mo,dy)-jd1901)+s
-            yr,mo,dy,hr,mn,sc=3Dlocaltime(t)[:6]
+            yr,mo,dy,hr,mn,sc,wd,jd,ds=3Dlocaltime(t)
+            if not ds:
+                tz=3Dself._localzone
+            else:
+                tz=3Dself._localdszone
             sc=3Dsc+ms
            =20
         elif ac=3D=3D1:
@@ -539,12 +543,16 @@
=20
             else:
                 # Seconds from epoch, gmt
-                t,tz=3Darg,self._localzone
+                t=3Darg
                 ms=3D(t-int(t))
                 yr,mo,dy,hr,mn,sc=3Dgmtime(int(t))[:6]
                 s=3D(hr/24.0+mn/1440.0+(sc+ms)/86400.0)
                 d=3D(self._julianday(yr,mo,dy)-jd1901)+s
-                yr,mo,dy,hr,mn,sc=3Dlocaltime(t)[:6]
+                yr,mo,dy,hr,mn,sc,wd,jd,ds=3Dlocaltime(t)
+                if not ds:
+                    tz=3Dself._localzone
+                else:
+                    tz=3Dself._localdszone
                 sc=3Dsc+ms
=20
         elif ac=3D=3D2:
@@ -691,7 +699,8 @@
     except:
         try:
             t=3Dtime()
-            localzone=3Dfloat(int(mktime(gmtime(t))) - int(t))
+            t0=3Dmktime(list(gmtime(t))[:-1]+[0])
+            localzone=3Dfloat(int(t0) - int(t))
             offset=3D(-localzone/(60*60))
             majorOffset=3Dint(offset)
             if majorOffset !=3D 0 :
@@ -701,6 +710,22 @@
             lz=3D'%s%0.02d%0.02d' % (m, majorOffset, minorOffset)
             _localzone=3D_cache._zmap[lower('GMT%s' % lz)]
         except: _localzone=3D''
+       =20
+    try: _localdszone=3D_cache._zmap[lower(tzname[1])]
+    except:
+        try:
+            t=3Dtime()
+            t0=3Dmktime(list(gmtime(t))[:-1]+[1])
+            localzone=3Dfloat(int(t0) - int(t))
+            offset=3D(-localzone/(60*60))
+            majorOffset=3Dint(offset)
+            if majorOffset !=3D 0 :
+                minorOffset=3Dabs(int((offset % majorOffset) * 60.0))
+            else: minorOffset =3D 0
+            m=3DmajorOffset >=3D 0 and '+' or ''
+            lz=3D'%s%0.02d%0.02d' % (m, majorOffset, minorOffset)
+            _localdszone=3D_cache._zmap[lower('GMT%s' % lz)]
+        except: _localdszone=3D''
=20
     _tzinfo     =3D_cache()
=20

--fUYQa+Pmc3FrFX/N--

--V0207lvV8h4k8FAm
Content-Type: application/pgp-signature

-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.0.1 (GNU/Linux)
Comment: For info see http://www.gnupg.org

iD8DBQE5CWFn3eVfDf25G40RAWuWAJ9TPh7R5nMK96I5d0DV4DxrfdrHWACdFNxW
S7OgQpVIMC2vzjzMBwu8big=
=j+Y4
-----END PGP SIGNATURE-----

--V0207lvV8h4k8FAm--