Subject: Re: bug#7337: 23.2; (require 'time) changes timezone

From: Kevin Ryde <[email-masked]>
Date: Fri, 15 Jul 2011 10:40:50 +1000

Lars Magne Ingebrigtsen <[email-masked]> writes:
>
> Hm.  Would that be returning the tzname variable (as described in the
> tzet manual page)?

Probably not, perhaps the TZ entry the C-level environ[], if that's
essentially what set-time-zone-rule writes to.

I later changed the macro I posted to the bit below, doing a `setenv' on
restoring as well as `set-time-zone-rule'.  I suspect set-time-zone-rule
might update the lisp process-environment as well as the C environ[]
... but I'm not certain if that's right, or enough, for combinations of
save/restore and to influence the current process and/or spawned
subprocesses, etc etc.

(defmacro xtide-with-TZ (tz &rest body)
  ;; checkdoc-params: (tz body)
  "Run BODY with `set-time-zone-rule' temporarily to TZ.
The current timezone (per `getenv' \"TZ\") is restored by an
`unwind-protect'.

This doesn't work properly if a `set-time-zone-rule' has been
applied but (setenv \"TZ\") not updated accordingly.  A `setenv'
is done here so that `xtide-with-TZ' will nest successfully at
least."

  ;; This getenv and restore is similar to what add-log.el
  ;; `add-change-log-entry' and time-stamp.el `time-stamp-string' do.  In
  ;; Emacs 23.2 the initializer in `display-time-world-list' always sets
  ;; back to nil, but a restore seems a much better idea.
  ;;
  ;; (setenv "TZ") makes the new TZ visible to a nested `xtide-with-TZ' or
  ;; to `add-change-log-entry'.  As of Emacs 23.2 `set-time-zone-rule'
  ;; changes TZ in the C-level environ[], but not in the lisp level
  ;; `process-environment'.
  ;;
  ;; setenv in emacs22 up returns the value set, but in emacs21 and xemacs21
  ;; it's the whole new `process-environment', or some such, so don't depend
  ;; on the value.
  ;;
  ;; setenv in emacs22 up also calls `set-time-zone-rule' itself, but for
  ;; emacs21 and xemacs21 must do so explicitly
  ;;
  (declare (indent 1)) ;; from 'cl
  `(let ((xtide-with-TZ--old (getenv "TZ"))
         (xtide-with-TZ--new ,tz)) ;; evaluate `tz' expression only once
     (setenv "TZ" xtide-with-TZ--new)
     (set-time-zone-rule xtide-with-TZ--new)
     (unwind-protect
         (progn ,@body)
       (setenv "TZ" xtide-with-TZ--old)
       (set-time-zone-rule xtide-with-TZ--old))))