Subject: 26.1; calc-time-zone result 2h too low for TZ east of GMT during DST

From: David O'Shea <[email-masked]>
Date: Mon, 14 Jan 2019 11:46:06 +0000

calc-time-zone returns time zone offset 2 hours less than expected for
a time zone ahead of UTC (east of Greenwich) when daylight savings is
active and the time zone is not specified within Emacs and instead is
fetched from the system.

Procedure to reproduce on a CentOS Linux system where /etc/localtime is
a symlink to /usr/share/zoneinfo/Australia/Sydney and daylight savings
time is active (e.g. on 14/Jan/2019):

1. Start calculator:         M-x calc RET
2. Get the time zone offset: t Z
3. Convert it to hours:      3600 /

For this location and time of year (daylight savings active), the offset
should be 11 hours, but the result of the above is 9.

I get the same behaviour with Emacs 24.2 (also built by myself) and
Emacs 24.3.1 as shipped by CentOS (RPM version 24.3-20.el7_4).

The offset is correct when daylight savings time is not active.

The info node "(calc) Time Zones" shows these default time zone
definitions are available in the calculator:

>      YST  PST  MST  CST  EST  AST    NST    GMT   WET     MET    MEZ
>       9    8    7    6    5    4     3.5     0     -1      -2     -2

These are negated compared to the usual convention of positive offsets
being used for time zones ahead of UTC (east of Greenwich) as is
followed by the function current-time-zone.  It would seem to me then
that for consistency with calculator's convention I should actually be
getting a negative result from calc-time-zone, but I don't, and I
think that's related to the absolute value of the offset being wrong.

It seems that when I invoke calc-time-zone, math-get-calendar-tzinfo
is called to get the timezone offset, and it does this:

      (setq math-calendar-tzinfo
            (list (* 60 (abs (nth 0 tzinfo)))
                  (* 60 (nth 1 tzinfo)))))))

I think the call to abs probably successfully converts the operating
system's view of the timezone offset from negative to positive for
timezones west of Greenwich, but fails to account for timezones east
of Greenwich.

When I change that code to just invert the sign on the timezone:

      (setq math-calendar-tzinfo
            (list (* -60 (nth 0 tzinfo))
   (* 60 (nth 1 tzinfo)))))))

I get a result of -11 from the sequence of steps shown at the top of
this bug report.  I didn't check closely to make sure that inverting
the sign is actually the correct behaviour but it's at least somewhat
consistent with the other code in making the offset negative for a
timezone east of Greenwich, and seems to work for this specific case.

I'm not considering this bug to be about the fact that the timezone
offset sign is inverted compared to usual conventions - and not filing
a separate bug about that - because (a) that might just be personal
preference and (b) changing it would presumably break any local
changes users may have made to math-tzone-names, so I imagine it'd be
pretty tricky.

In GNU Emacs 26.1 (build 1, x86_64-pc-linux-gnu)
 of 2019-01-14 built on <my machine, name redacted>
System Description: CentOS release 6.3 (Final)

Recent messages:
For information about GNU Emacs and the GNU system, type C-h C-a.
Welcome to the GNU Emacs Calculator!  Press ‘?’ or ‘h’ for help, ‘q’ to quit
t-

Configured using:
 'configure --prefix=/opt/emacs-26.1'

Configured features:
SOUND NOTIFY LIBSELINUX GNUTLS LIBXML2 ZLIB THREADS

Important settings:
  value of $LANG: en_US.utf8
  value of $XMODIFIERS: @im=none
  locale-coding-system: utf-8-unix

Major mode: Calculator

Minor modes in effect:
  tooltip-mode: t
  global-eldoc-mode: t
  electric-indent-mode: t
  menu-bar-mode: t
  file-name-shadow-mode: t
  global-font-lock-mode: t
  font-lock-mode: t
  auto-composition-mode: t
  auto-encryption-mode: t
  auto-compression-mode: t
  buffer-read-only: t
  line-number-mode: t
  transient-mark-mode: t

Load-path shadows:
None found.

Features:
(shadow sort mail-extr emacsbug message rmc puny seq byte-opt gv
bytecomp byte-compile cconv cl-loaddefs cl-lib dired dired-loaddefs
format-spec rfc822 mml mml-sec password-cache epa derived epg epg-config
gnus-util rmail tool-bar rmail-loaddefs mm-decode mm-bodies mm-encode
mail-parse rfc2231 mailabbrev gmm-utils mailheader sendmail regexp-opt
rfc2047 rfc2045 ietf-drums mm-util mail-prsvr mail-utils calc-arith
cal-dst cal-menu calendar cal-loaddefs calc-alg calc-forms calc-ext
calc-misc calc-menu easymenu calc calc-loaddefs calc-macs time-date
elec-pair mule-util tooltip eldoc electric uniquify ediff-hook vc-hooks
lisp-float-type tabulated-list replace newcomment text-mode elisp-mode
lisp-mode prog-mode register page menu-bar rfn-eshadow isearch timer
select mouse jit-lock font-lock syntax facemenu font-core
term/tty-colors frame cl-generic cham georgian utf-8-lang misc-lang
vietnamese tibetan thai tai-viet lao korean japanese eucjp-ms cp51932
hebrew greek romanian slovak czech european ethiopic indian cyrillic
chinese composite charscript charprop case-table epa-hook jka-cmpr-hook
help simple abbrev obarray minibuffer cl-preloaded nadvice loaddefs
button faces cus-face macroexp files text-properties overlay sha1 md5
base64 format env code-pages mule custom widget hashtable-print-readable
backquote inotify multi-tty make-network-process emacs)

Memory information:
((conses 16 129204 8727)
 (symbols 48 22926 1)
 (miscs 40 39 132)
 (strings 32 34692 1702)
 (string-bytes 1 946707)
 (vectors 16 15734)
 (vector-slots 8 477414 6086)
 (floats 8 57 256)
 (intervals 56 207 0)
 (buffers 992 13)
 (heap 1024 21719 738))