# [tz] How to compute the moment of the next DST change

Simon Perreault simon.perreault at viagenie.ca
Tue Apr 2 19:21:05 UTC 2013

```First I want to say thanks to everyone for your help! In the end I think
I will parse the output of zdump. Easy, correct, simple. Just the way I
like it.

Now this original suggestion warrants a reply:

Le 2013-04-02 17:59, Paul Eggert a écrit :
> This shell command should do the trick:
>
> emacs -batch -l cal-dst -eval '(message "%s" (format-time-string "%Y-%m-%d %H:%M:%S %z" (calendar-next-time-zone-transition (current-time))))'

Interesting... Looking at the source code of
"calendar-next-time-zone-transition", it looks very error prone to me.
Am I reading the comments right? It initializes a binary search with the
results of a heuristic? I know you know what you're doing, it's just a
bit unexpected to this time newbie.

> (defun calendar-next-time-zone-transition (time)
>   "Return the time of the next time zone transition after TIME.
> Both TIME and the result are acceptable arguments to `current-time-zone'.
> Return nil if no such transition can be found."
>   (let* ((base 65536)           ; 2^16 = base of current-time output
>          (quarter-multiple 120) ; approx = (seconds per quarter year) / base
>          (time-zone (current-time-zone time))
>          (time-utc-diff (car time-zone))
>          hi
>          hi-zone
>          (hi-utc-diff time-utc-diff)
>          (quarters '(2 1 3)))
>     ;; Heuristic: probe the time zone offset in the next three calendar
>     ;; quarters, looking for a time zone offset different from TIME.
>     (while (and quarters (eq time-utc-diff hi-utc-diff))
>       (setq hi (cons (+ (car time) (* (car quarters) quarter-multiple)) 0)
>             hi-zone (current-time-zone hi)
>             hi-utc-diff (car hi-zone)
>             quarters (cdr quarters)))
>     (and
>      time-utc-diff
>      hi-utc-diff
>      (not (eq time-utc-diff hi-utc-diff))
>      ;; Now HI is after the next time zone transition.
>      ;; Set LO to TIME, and then binary search to increase LO and decrease HI
>      ;; until LO is just before and HI is just after the time zone transition.
>      (let* ((tail (cdr time))
>             (lo (cons (car time) (if (numberp tail) tail (car tail))))
>             probe)
>        (while
>            ;; Set PROBE to halfway between LO and HI, rounding down.
>            ;; If PROBE equals LO, we are done.
>            (let* ((lsum (+ (cdr lo) (cdr hi)))
>                   (hsum (+ (car lo) (car hi) (/ lsum base)))
>                   (hsumodd (logand 1 hsum)))
>              (setq probe (cons (/ (- hsum hsumodd) 2)
>                                (/ (+ (* hsumodd base) (% lsum base)) 2)))
>              (not (equal lo probe)))
>          ;; Set either LO or HI to PROBE, depending on probe results.
>          (if (eq (car (current-time-zone probe)) hi-utc-diff)
>              (setq hi probe)
>            (setq lo probe)))
>        hi))))

Simon
--
DTN made easy, lean, and smart --> http://postellation.viagenie.ca
NAT64/DNS64 open-source        --> http://ecdysis.viagenie.ca
STUN/TURN server               --> http://numb.viagenie.ca
```