Originally posted by: Edward Davignon
Converting days into seconds while observing all of the leap-year days, known implementation bugs, and ever-changing conventions for leap seconds and daylight-savings-time is maddening!
Does anyone have a simple, pure-Perl library or function that correctly calculates differences of proleptic Gregorian calendar dates?
See: https://en.wikipedia.org/wiki/ISO_8601#Dates
Here are a few of the things I have run into.
Watch out for libraries that assume year 1970 (or 1900) have the same daylight saving time transition dates (and number of leap-year days) as the current year:
aixserver$ echo "===>$TZ<==="
===>America/New_York<===
aixserver$ zdump -V -c 1969,1971 "$TZ"
America/New_York Sun Apr 27 06:59:59 1969 UT = Sun Apr 27 01:59:59 1969 EST isdst=0 gmtoff=-18000
America/New_York Sun Apr 27 07:00:00 1969 UT = Sun Apr 27 03:00:00 1969 EDT isdst=1 gmtoff=-14400
America/New_York Sun Oct 26 05:59:59 1969 UT = Sun Oct 26 01:59:59 1969 EDT isdst=1 gmtoff=-14400
America/New_York Sun Oct 26 06:00:00 1969 UT = Sun Oct 26 01:00:00 1969 EST isdst=0 gmtoff=-18000
America/New_York Sun Apr 26 06:59:59 1970 UT = Sun Apr 26 01:59:59 1970 EST isdst=0 gmtoff=-18000
America/New_York Sun Apr 26 07:00:00 1970 UT = Sun Apr 26 03:00:00 1970 EDT isdst=1 gmtoff=-14400
America/New_York Sun Oct 25 05:59:59 1970 UT = Sun Oct 25 01:59:59 1970 EDT isdst=1 gmtoff=-14400
America/New_York Sun Oct 25 06:00:00 1970 UT = Sun Oct 25 01:00:00 1970 EST isdst=0 gmtoff=-18000
aixserver$ zdump -V -c 2018,2020 "$TZ"
America/New_York Sun Mar 11 06:59:59 2018 UT = Sun Mar 11 01:59:59 2018 EST isdst=0 gmtoff=-18000
America/New_York Sun Mar 11 07:00:00 2018 UT = Sun Mar 11 03:00:00 2018 EDT isdst=1 gmtoff=-14400
America/New_York Sun Nov 4 05:59:59 2018 UT = Sun Nov 4 01:59:59 2018 EDT isdst=1 gmtoff=-14400
America/New_York Sun Nov 4 06:00:00 2018 UT = Sun Nov 4 01:00:00 2018 EST isdst=0 gmtoff=-18000
America/New_York Sun Mar 10 06:59:59 2019 UT = Sun Mar 10 01:59:59 2019 EST isdst=0 gmtoff=-18000
America/New_York Sun Mar 10 07:00:00 2019 UT = Sun Mar 10 03:00:00 2019 EDT isdst=1 gmtoff=-14400
America/New_York Sun Nov 3 05:59:59 2019 UT = Sun Nov 3 01:59:59 2019 EDT isdst=1 gmtoff=-14400
America/New_York Sun Nov 3 06:00:00 2019 UT = Sun Nov 3 01:00:00 2019 EST isdst=0 gmtoff=-18000
aixserver$ zdump -v -c 1890,1919 "$TZ"
America/New_York Fri Dec 13 20:45:52 1901 UT = Fri Dec 13 15:45:52 1901 EST isdst=0 gmtoff=-18000
America/New_York Sat Dec 14 20:45:52 1901 UT = Sat Dec 14 15:45:52 1901 EST isdst=0 gmtoff=-18000
America/New_York Sun Mar 31 06:59:59 1918 UT = Sun Mar 31 01:59:59 1918 EST isdst=0 gmtoff=-18000
America/New_York Sun Mar 31 07:00:00 1918 UT = Sun Mar 31 03:00:00 1918 EDT isdst=1 gmtoff=-14400
America/New_York Sun Oct 27 05:59:59 1918 UT = Sun Oct 27 01:59:59 1918 EDT isdst=1 gmtoff=-14400
America/New_York Sun Oct 27 06:00:00 1918 UT = Sun Oct 27 01:00:00 1918 EST isdst=0 gmtoff=-18000
America/New_York Mon Jan 18 03:14:07 2038 UT = Sun Jan 17 22:14:07 2038 EST isdst=0 gmtoff=-18000
America/New_York Tue Jan 19 03:14:07 2038 UT = Mon Jan 18 22:14:07 2038 EST isdst=0 gmtoff=-18000
aixserver$
Watch out for the 1900-leap-year bug in Lotus 123 and inherited in MS Excel spreadsheet epochs calculations:
aixserver$ LANG=C TZ=UTC /opt/freeware/bin/date --date='12:00 Feb 28, 2000'
Mon Feb 28 12:00:00 UTC 2000
aixserver$ LANG=C TZ=UTC /opt/freeware/bin/date --date='12:00 Feb 29, 2000'
Tue Feb 29 12:00:00 UTC 2000
aixserver$ LANG=C TZ=UTC /opt/freeware/bin/date --date='12:00 Feb 28, 1900'
Wed Feb 28 12:00:00 UTC 1900
aixserver$ LANG=C TZ=UTC /opt/freeware/bin/date --date='12:00 Feb 29, 1900'
date_64: invalid date '12:00 Feb 29, 1900'
aixserver$
Note: 2000 is divisible by 400, so it is a leap year. While 1900 is divisible by 4, but not 400; so 1900 is not a leap year on the Gregorian calendar.
Watch out for date calculations that cross leap days:
aixserver$ LANG=C /opt/freeware/bin/date --date='TZ="America/New_York" 12:00 July 29, 1900 6 months ago'
Mon Jan 29 12:00:00 EST 1900
aixserver$ LANG=C /opt/freeware/bin/date --date='TZ="America/New_York" 12:00 July 29, 1900 5 months ago'
Thu Mar 1 12:00:00 EST 1900
aixserver$
aixserver$ LANG=C TZ=EST5EDT /opt/freeware/bin/date --date='TZ="EST5EDT" 12:00 July 29, 2000 6 months ago'
Sat Jan 29 12:00:00 EST 2000
aixserver$ LANG=C TZ=EST5EDT /opt/freeware/bin/date --date='TZ="EST5EDT" 12:00 July 29, 2000 5 months ago'
Tue Feb 29 12:00:00 EST 2000
aixserver$ LANG=C TZ=EST5EDT /opt/freeware/bin/date --date='TZ="EST5EDT" 12:00 July 29, 1900 6 months ago'
Mon Jan 29 12:00:00 EST 1900
aixserver$ LANG=C TZ=EST5EDT /opt/freeware/bin/date --date='TZ="EST5EDT" 12:00 July 29, 1900 5 months ago'
Thu Mar 1 12:00:00 EST 1900
aixserver$ rpm -qf /opt/freeware/bin/date
coreutils-8.29-3.ppc
aixserver$ yum list | grep coreutils
coreutils.ppc 8.29-3 @AIX_Toolbox
aixserver$
Watch out for the Y2K and 2038 problems.
aixserver$ echo "===>$TZ<==="
===>America/New_York<===
aixserver$ zdump -v -c 1999,2001 "$TZ"
America/New_York Fri Dec 13 20:45:52 1901 UT = Fri Dec 13 15:45:52 1901 EST isdst=0 gmtoff=-18000
America/New_York Sat Dec 14 20:45:52 1901 UT = Sat Dec 14 15:45:52 1901 EST isdst=0 gmtoff=-18000
America/New_York Sun Apr 4 06:59:59 1999 UT = Sun Apr 4 01:59:59 1999 EST isdst=0 gmtoff=-18000
America/New_York Sun Apr 4 07:00:00 1999 UT = Sun Apr 4 03:00:00 1999 EDT isdst=1 gmtoff=-14400
America/New_York Sun Oct 31 05:59:59 1999 UT = Sun Oct 31 01:59:59 1999 EDT isdst=1 gmtoff=-14400
America/New_York Sun Oct 31 06:00:00 1999 UT = Sun Oct 31 01:00:00 1999 EST isdst=0 gmtoff=-18000
America/New_York Sun Apr 2 06:59:59 2000 UT = Sun Apr 2 01:59:59 2000 EST isdst=0 gmtoff=-18000
America/New_York Sun Apr 2 07:00:00 2000 UT = Sun Apr 2 03:00:00 2000 EDT isdst=1 gmtoff=-14400
America/New_York Sun Oct 29 05:59:59 2000 UT = Sun Oct 29 01:59:59 2000 EDT isdst=1 gmtoff=-14400
America/New_York Sun Oct 29 06:00:00 2000 UT = Sun Oct 29 01:00:00 2000 EST isdst=0 gmtoff=-18000
America/New_York Mon Jan 18 03:14:07 2038 UT = Sun Jan 17 22:14:07 2038 EST isdst=0 gmtoff=-18000
America/New_York Tue Jan 19 03:14:07 2038 UT = Mon Jan 18 22:14:07 2038 EST isdst=0 gmtoff=-18000
aixserver$ lslpp -l bos.rte.date
Fileset Level State Description
----------------------------------------------------------------------------
Path: /usr/lib/objrepos
bos.rte.date 7.2.3.16 COMMITTED Date Control Commands
Path: /etc/objrepos
bos.rte.date 7.2.3.16 COMMITTED Date Control Commands
aixserver$ oslevel -s
7200-03-03-1914
aixserver$ LANG=C TZ=UTC /opt/freeware/bin/date --date='12:00 July 29, 2019 20 years'
Fri Jul 29 12:00:00 UTC 2039
aixserver$
There are less than 20 years until 2038. Does AIX 7.2 TL3 SP3 have Year-2038 problems?