[tz] How to compute the moment of the next DST change
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
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-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)))
> (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))))
> ;; 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)))
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
More information about the tz