Merge changes from emacs-23 branch
[bpt/emacs.git] / lisp / calendar / cal-dst.el
CommitLineData
e716fd62 1;;; cal-dst.el --- calendar functions for daylight saving rules
3e03d7c7 2
a20b3848 3;; Copyright (C) 1993, 1994, 1995, 1996, 2001, 2002, 2003, 2004, 2005,
114f9c96 4;; 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc.
3e03d7c7
JB
5
6;; Author: Paul Eggert <eggert@twinsun.com>
71ea27ee 7;; Edward M. Reingold <reingold@cs.uiuc.edu>
dbfca9c4 8;; Maintainer: Glenn Morris <rgm@gnu.org>
3e03d7c7 9;; Keywords: calendar
e716fd62 10;; Human-Keywords: daylight saving time, calendar, diary, holidays
bd78fa1d 11;; Package: calendar
3e03d7c7
JB
12
13;; This file is part of GNU Emacs.
14
2ed66575 15;; GNU Emacs is free software: you can redistribute it and/or modify
59243403 16;; it under the terms of the GNU General Public License as published by
2ed66575
GM
17;; the Free Software Foundation, either version 3 of the License, or
18;; (at your option) any later version.
59243403 19
3e03d7c7 20;; GNU Emacs is distributed in the hope that it will be useful,
59243403
RS
21;; but WITHOUT ANY WARRANTY; without even the implied warranty of
22;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23;; GNU General Public License for more details.
24
25;; You should have received a copy of the GNU General Public License
2ed66575 26;; along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>.
3e03d7c7
JB
27
28;;; Commentary:
29
b1c57079 30;; See calendar.el.
3e03d7c7 31
3e03d7c7
JB
32;;; Code:
33
34(require 'calendar)
35
ec1ee609
GM
36
37(defgroup calendar-dst nil
38 "Options related to Daylight Saving Time."
39 :prefix "calendar-"
40 :group 'calendar)
41
42
cd72c399
GM
43(defcustom calendar-dst-check-each-year-flag t
44 "Non-nil means to check each year for DST transitions as needed.
f3f4e600 45Otherwise assume the next two transitions found after the
cd72c399 46current date apply to all years. This is faster, but not always
e716fd62 47correct, since the dates of daylight saving transitions sometimes
cd72c399
GM
48change."
49 :type 'boolean
50 :version "22.1"
76db8823 51 :group 'calendar-dst)
cd72c399 52
ec1ee609
GM
53;;;###autoload
54(put 'calendar-daylight-savings-starts 'risky-local-variable t)
55(defcustom calendar-daylight-savings-starts '(calendar-dst-starts year)
56 "Sexp giving the date on which daylight saving time starts.
57This is an expression in the variable `year' whose value gives the Gregorian
58date in the form (month day year) on which daylight saving time starts. It is
59used to determine the starting date of daylight saving time for the holiday
60list and for correcting times of day in the solar and lunar calculations.
61
62For example, if daylight saving time is mandated to start on October 1,
63you would set `calendar-daylight-savings-starts' to
64
65 '(10 1 year)
66
67If it starts on the first Sunday in April, you would set it to
68
69 '(calendar-nth-named-day 1 0 4 year)
70
71If the locale never uses daylight saving time, set this to nil."
72 :type 'sexp
73 :group 'calendar-dst)
74
75;;;###autoload
76(put 'calendar-daylight-savings-ends 'risky-local-variable t)
77(defcustom calendar-daylight-savings-ends '(calendar-dst-ends year)
78 "Sexp giving the date on which daylight saving time ends.
79This is an expression in the variable `year' whose value gives the Gregorian
80date in the form (month day year) on which daylight saving time ends. It is
81used to determine the starting date of daylight saving time for the holiday
82list and for correcting times of day in the solar and lunar calculations.
83
84For example, if daylight saving time ends on the last Sunday in October:
85
86 '(calendar-nth-named-day -1 0 10 year)
87
88If the locale never uses daylight saving time, set this to nil."
89 :type 'sexp
90 :group 'calendar-dst)
91
92;;; More defcustoms below.
93
94
3e03d7c7 95(defvar calendar-current-time-zone-cache nil
ed589f9a 96 "Cache for result of `calendar-current-time-zone'.")
76db8823
GM
97;; It gets eval'd, eg by calendar-dst-starts.
98;;;###autoload
99(put 'calendar-current-time-zone-cache 'risky-local-variable t)
3e03d7c7
JB
100
101(defvar calendar-system-time-basis
102 (calendar-absolute-from-gregorian '(1 1 1970))
103 "Absolute date of starting date of system clock.")
104
3e03d7c7
JB
105(defun calendar-absolute-from-time (x utc-diff)
106 "Absolute local date of time X; local time is UTC-DIFF seconds from UTC.
107
108X is (HIGH . LOW) or (HIGH LOW . IGNORED) where HIGH and LOW are the
109high and low 16 bits, respectively, of the number of seconds since
1101970-01-01 00:00:00 UTC, ignoring leap seconds.
111
112Returns the pair (ABS-DATE . SECONDS) where SECONDS after local midnight on
113absolute date ABS-DATE is the equivalent moment to X."
114 (let* ((h (car x))
71ea27ee 115 (xtail (cdr x))
3e03d7c7 116 (l (+ utc-diff (if (numberp xtail) xtail (car xtail))))
4cc1b78a 117 (u (+ (* 512 (mod h 675)) (floor l 128))))
3e03d7c7
JB
118 ;; Overflow is a terrible thing!
119 (cons (+ calendar-system-time-basis
71ea27ee
GM
120 ;; floor((2^16 h +l) / (60*60*24))
121 (* 512 (floor h 675)) (floor u 675))
122 ;; (2^16 h +l) mod (60*60*24)
123 (+ (* (mod u 675) 128) (mod l 128)))))
3e03d7c7
JB
124
125(defun calendar-time-from-absolute (abs-date s)
126 "Time of absolute date ABS-DATE, S seconds after midnight.
127
ec9b5635 128Returns the list (HIGH LOW) where HIGH and LOW are the high and low
3e03d7c7
JB
12916 bits, respectively, of the number of seconds 1970-01-01 00:00:00 UTC,
130ignoring leap seconds, that is the equivalent moment to S seconds after
131midnight UTC on absolute date ABS-DATE."
132 (let* ((a (- abs-date calendar-system-time-basis))
4cc1b78a 133 (u (+ (* 163 (mod a 512)) (floor s 128))))
3e03d7c7 134 ;; Overflow is a terrible thing!
ec9b5635 135 (list
3ac14ca0 136 ;; floor((60*60*24*a + s) / 2^16)
4cc1b78a 137 (+ a (* 163 (floor a 512)) (floor u 512))
3ac14ca0 138 ;; (60*60*24*a + s) mod 2^16
4cc1b78a 139 (+ (* 128 (mod u 512)) (mod s 128)))))
3e03d7c7
JB
140
141(defun calendar-next-time-zone-transition (time)
142 "Return the time of the next time zone transition after TIME.
311cc551 143Both TIME and the result are acceptable arguments to `current-time-zone'.
3e03d7c7 144Return nil if no such transition can be found."
fd32e5b9
GM
145 (let* ((base 65536) ; 2^16 = base of current-time output
146 (quarter-multiple 120) ; approx = (seconds per quarter year) / base
71ea27ee
GM
147 (time-zone (current-time-zone time))
148 (time-utc-diff (car time-zone))
3e03d7c7 149 hi
71ea27ee 150 hi-zone
3e03d7c7
JB
151 (hi-utc-diff time-utc-diff)
152 (quarters '(2 1 3)))
153 ;; Heuristic: probe the time zone offset in the next three calendar
154 ;; quarters, looking for a time zone offset different from TIME.
155 (while (and quarters (eq time-utc-diff hi-utc-diff))
4b8683c7
GM
156 (setq hi (cons (+ (car time) (* (car quarters) quarter-multiple)) 0)
157 hi-zone (current-time-zone hi)
158 hi-utc-diff (car hi-zone)
159 quarters (cdr quarters)))
3e03d7c7
JB
160 (and
161 time-utc-diff
162 hi-utc-diff
163 (not (eq time-utc-diff hi-utc-diff))
164 ;; Now HI is after the next time zone transition.
165 ;; Set LO to TIME, and then binary search to increase LO and decrease HI
166 ;; until LO is just before and HI is just after the time zone transition.
167 (let* ((tail (cdr time))
71ea27ee
GM
168 (lo (cons (car time) (if (numberp tail) tail (car tail))))
169 probe)
3e03d7c7 170 (while
71ea27ee
GM
171 ;; Set PROBE to halfway between LO and HI, rounding down.
172 ;; If PROBE equals LO, we are done.
173 (let* ((lsum (+ (cdr lo) (cdr hi)))
174 (hsum (+ (car lo) (car hi) (/ lsum base)))
175 (hsumodd (logand 1 hsum)))
176 (setq probe (cons (/ (- hsum hsumodd) 2)
177 (/ (+ (* hsumodd base) (% lsum base)) 2)))
178 (not (equal lo probe)))
179 ;; Set either LO or HI to PROBE, depending on probe results.
180 (if (eq (car (current-time-zone probe)) hi-utc-diff)
181 (setq hi probe)
182 (setq lo probe)))
3e03d7c7
JB
183 hi))))
184
d80c2c18 185(autoload 'calendar-persian-to-absolute "cal-persia")
06e3b7ae 186
3e03d7c7
JB
187(defun calendar-time-zone-daylight-rules (abs-date utc-diff)
188 "Return daylight transition rule for ABS-DATE, UTC-DIFF sec offset from UTC.
e716fd62
CY
189ABS-DATE must specify a day that contains a daylight saving transition.
190The result has the proper form for `calendar-daylight-savings-starts'."
3e03d7c7 191 (let* ((date (calendar-gregorian-from-absolute abs-date))
71ea27ee 192 (weekday (% abs-date 7))
e803eab7
GM
193 (m (calendar-extract-month date))
194 (d (calendar-extract-day date))
195 (y (calendar-extract-year date))
3e03d7c7 196 (last (calendar-last-day-of-month m y))
ff35f3b8
GM
197 j rlist
198 (candidate-rules ; these return Gregorian dates
71ea27ee
GM
199 (append
200 ;; Day D of month M.
ff35f3b8 201 `((list ,m ,d year))
71ea27ee 202 ;; The first WEEKDAY of month M.
3e03d7c7 203 (if (< d 8)
ff35f3b8 204 `((calendar-nth-named-day 1 ,weekday ,m year)))
71ea27ee 205 ;; The last WEEKDAY of month M.
3e03d7c7 206 (if (> d (- last 7))
ff35f3b8
GM
207 `((calendar-nth-named-day -1 ,weekday ,m year)))
208 (progn
209 ;; The first WEEKDAY after day J of month M, for D-6 < J <= D.
210 (setq j (1- (max 2 (- d 6))))
211 (while (<= (setq j (1+ j)) (min d (- last 8)))
212 (push `(calendar-nth-named-day 1 ,weekday ,m year ,j) rlist))
213 rlist)
71ea27ee 214 ;; 01-01 and 07-01 for this year's Persian calendar.
ff35f3b8 215 ;; FIXME what does the Persian calendar have to do with this?
84cb770d
GM
216 (and (= m 3) (memq d '(20 21))
217 '((calendar-gregorian-from-absolute
218 (calendar-persian-to-absolute `(1 1 ,(- year 621))))))
219 (and (= m 9) (memq d '(22 23))
220 '((calendar-gregorian-from-absolute
221 (calendar-persian-to-absolute `(7 1 ,(- year 621))))))))
fd32e5b9 222 (prevday-sec (- -1 utc-diff)) ; last sec of previous local day
ff35f3b8
GM
223 (year (1+ y))
224 new-rules)
6bc457fe 225 ;; Scan through the next few years until only one rule remains.
ff35f3b8
GM
226 (while (cdr candidate-rules)
227 (dolist (rule candidate-rules)
228 ;; The rule we return should give a Gregorian date, but here
229 ;; we require an absolute date. The following is for efficiency.
230 (setq date (cond ((eq (car rule) 'calendar-nth-named-day)
231 (eval (cons 'calendar-nth-named-absday (cdr rule))))
232 ((eq (car rule) 'calendar-gregorian-from-absolute)
b27c3bc6 233 (eval (cadr rule)))
ff35f3b8
GM
234 (t (calendar-absolute-from-gregorian (eval rule)))))
235 (or (equal (current-time-zone
236 (calendar-time-from-absolute date prevday-sec))
237 (current-time-zone
238 (calendar-time-from-absolute (1+ date) prevday-sec)))
239 (setq new-rules (cons rule new-rules))))
240 ;; If no rules remain, just use the first candidate rule;
241 ;; it's wrong in general, but it's right for at least one year.
242 (setq candidate-rules (if new-rules (nreverse new-rules)
243 (list (car candidate-rules)))
4f1c166c
GM
244 new-rules nil
245 year (1+ year)))
6bc457fe 246 (car candidate-rules)))
3e03d7c7 247
cd72c399
GM
248;; TODO it might be better to extract this information directly from
249;; the system timezone database. But cross-platform...?
250;; See thread
251;; http://lists.gnu.org/archive/html/emacs-pretest-bug/2006-11/msg00060.html
252(defun calendar-dst-find-data (&optional time)
e716fd62 253 "Find data on the first daylight saving time transitions after TIME.
cd72c399
GM
254TIME defaults to `current-time'. Return value is as described
255for `calendar-current-time-zone'."
256 (let* ((t0 (or time (current-time)))
257 (t0-zone (current-time-zone t0))
258 (t0-utc-diff (car t0-zone))
4b8683c7 259 (t0-name (cadr t0-zone)))
cd72c399
GM
260 (if (not t0-utc-diff)
261 ;; Little or no time zone information is available.
262 (list nil nil t0-name t0-name nil nil nil nil)
263 (let* ((t1 (calendar-next-time-zone-transition t0))
264 (t2 (and t1 (calendar-next-time-zone-transition t1))))
265 (if (not t2)
e716fd62 266 ;; This locale does not have daylight saving time.
cd72c399 267 (list (/ t0-utc-diff 60) 0 t0-name t0-name nil nil 0 0)
e716fd62 268 ;; Use heuristics to find daylight saving parameters.
cd72c399
GM
269 (let* ((t1-zone (current-time-zone t1))
270 (t1-utc-diff (car t1-zone))
4b8683c7 271 (t1-name (cadr t1-zone))
cd72c399
GM
272 (t1-date-sec (calendar-absolute-from-time t1 t0-utc-diff))
273 (t2-date-sec (calendar-absolute-from-time t2 t1-utc-diff))
274 ;; TODO When calendar-dst-check-each-year-flag is non-nil,
275 ;; the rules can be simpler than they currently are.
276 (t1-rules (calendar-time-zone-daylight-rules
277 (car t1-date-sec) t0-utc-diff))
278 (t2-rules (calendar-time-zone-daylight-rules
279 (car t2-date-sec) t1-utc-diff))
280 (t1-time (/ (cdr t1-date-sec) 60))
281 (t2-time (/ (cdr t2-date-sec) 60)))
282 (cons
283 (/ (min t0-utc-diff t1-utc-diff) 60)
284 (cons
285 (/ (abs (- t0-utc-diff t1-utc-diff)) 60)
286 (if (< t0-utc-diff t1-utc-diff)
287 (list t0-name t1-name t1-rules t2-rules t1-time t2-time)
288 (list t1-name t0-name t2-rules t1-rules t2-time t1-time)
289 )))))))))
290
291(defvar calendar-dst-transition-cache nil
e716fd62 292 "Internal cal-dst variable storing date of daylight saving time transitions.
cd72c399
GM
293Value is a list with elements of the form (YEAR START END), where
294START and END are expressions that when evaluated return the
311cc551 295start and end dates (respectively) for DST in YEAR. Used by the
cd72c399
GM
296function `calendar-dst-find-startend'.")
297
298(defun calendar-dst-find-startend (year)
e716fd62 299 "Find the dates in YEAR on which daylight saving time starts and ends.
cd72c399
GM
300Returns a list (YEAR START END), where START and END are
301expressions that when evaluated return the start and end dates,
302respectively. This function first attempts to use pre-calculated
303data from `calendar-dst-transition-cache', otherwise it calls
325c2dd1
GM
304`calendar-dst-find-data' (and adds the results to the cache).
305If dates in YEAR cannot be handled by `encode-time' (e.g. if they
306are too large to be represented as a lisp integer), then rather
307than an error this function returns the result appropriate for
308the current year."
cd72c399
GM
309 (let ((e (assoc year calendar-dst-transition-cache))
310 f)
311 (or e
312 (progn
325c2dd1
GM
313 (setq e (calendar-dst-find-data
314 (condition-case nil
315 (encode-time 1 0 0 1 1 year)
316 (error
317 (encode-time 1 0 0 1 1 (nth 5 (decode-time))))))
cd72c399
GM
318 f (nth 4 e)
319 e (list year f (nth 5 e))
320 calendar-dst-transition-cache
321 (append calendar-dst-transition-cache (list e)))
322 e))))
323
3e03d7c7
JB
324(defun calendar-current-time-zone ()
325 "Return UTC difference, dst offset, names and rules for current time zone.
326
6bc457fe
PE
327Returns (UTC-DIFF DST-OFFSET STD-ZONE DST-ZONE DST-STARTS DST-ENDS
328DST-STARTS-TIME DST-ENDS-TIME), based on a heuristic probing of what the
329system knows:
3e03d7c7
JB
330
331UTC-DIFF is an integer specifying the number of minutes difference between
332 standard time in the current time zone and Coordinated Universal Time
333 (Greenwich Mean Time). A negative value means west of Greenwich.
e716fd62 334DST-OFFSET is an integer giving the daylight saving time offset in minutes.
3e03d7c7
JB
335STD-ZONE is a string giving the name of the time zone when no seasonal time
336 adjustment is in effect.
337DST-ZONE is a string giving the name of the time zone when there is a seasonal
338 time adjustment in effect.
339DST-STARTS and DST-ENDS are sexps in the variable `year' giving the daylight
e716fd62 340 saving time start and end rules, in the form expected by
3e03d7c7 341 `calendar-daylight-savings-starts'.
6bc457fe 342DST-STARTS-TIME and DST-ENDS-TIME are integers giving the number of minutes
e716fd62 343 after midnight that daylight saving time starts and ends.
3e03d7c7 344
6bc457fe
PE
345If the local area does not use a seasonal time adjustment, STD-ZONE and
346DST-ZONE are equal, and all the DST-* integer variables are 0.
3e03d7c7
JB
347
348Some operating systems cannot provide all this information to Emacs; in this
349case, `calendar-current-time-zone' returns a list containing nil for the data
350it can't find."
cd72c399
GM
351 (unless calendar-current-time-zone-cache
352 (setq calendar-current-time-zone-cache (calendar-dst-find-data))))
3e03d7c7 353
ec1ee609
GM
354
355;; Following options should be set based on conditions when the code
356;; is invoked, so are not suitable for dumping into loaddefs.el. They
357;; default to US Eastern time if time zone info is not available.
3e03d7c7
JB
358
359(calendar-current-time-zone)
360
ec1ee609 361(defcustom calendar-time-zone (or (car calendar-current-time-zone-cache) -300)
311cc551 362 "Number of minutes difference between local standard time and UTC.
ec1ee609
GM
363For example, -300 for New York City, -480 for Los Angeles."
364 :type 'integer
365 :group 'calendar-dst)
3e03d7c7 366
ec1ee609 367(defcustom calendar-daylight-time-offset
4b8683c7 368 (or (cadr calendar-current-time-zone-cache) 60)
ec1ee609
GM
369 "Number of minutes difference between daylight saving and standard time.
370If the locale never uses daylight saving time, set this to 0."
371 :type 'integer
372 :group 'calendar-dst)
3e03d7c7 373
ec1ee609 374(defcustom calendar-standard-time-zone-name
4b8683c7 375 (or (nth 2 calendar-current-time-zone-cache) "EST")
ec1ee609
GM
376 "Abbreviated name of standard time zone at `calendar-location-name'.
377For example, \"EST\" in New York City, \"PST\" for Los Angeles."
378 :type 'string
379 :group 'calendar-dst)
3e03d7c7 380
ec1ee609 381(defcustom calendar-daylight-time-zone-name
4b8683c7 382 (or (nth 3 calendar-current-time-zone-cache) "EDT")
ec1ee609
GM
383 "Abbreviated name of daylight saving time zone at `calendar-location-name'.
384For example, \"EDT\" in New York City, \"PDT\" for Los Angeles."
385 :type 'string
386 :group 'calendar-dst)
387
388(defcustom calendar-daylight-savings-starts-time
4b8683c7 389 (or (nth 6 calendar-current-time-zone-cache) 120)
ec1ee609
GM
390 "Number of minutes after midnight that daylight saving time starts."
391 :type 'integer
392 :group 'calendar-dst)
393
394(defcustom calendar-daylight-savings-ends-time
4b8683c7 395 (or (nth 7 calendar-current-time-zone-cache)
ec1ee609
GM
396 calendar-daylight-savings-starts-time)
397 "Number of minutes after midnight that daylight saving time ends."
398 :type 'integer
399 :group 'calendar-dst)
a1506d29 400
cd72c399
GM
401
402(defun calendar-dst-starts (year)
e716fd62 403 "Return the date of YEAR on which daylight saving time starts.
cd72c399
GM
404This function respects the value of `calendar-dst-check-each-year-flag'."
405 (or (let ((expr (if calendar-dst-check-each-year-flag
406 (cadr (calendar-dst-find-startend year))
407 (nth 4 calendar-current-time-zone-cache))))
408 (if expr (eval expr)))
71ea27ee 409 ;; New US rules commencing 2007. ftp://elsie.nci.nih.gov/pub/.
cd72c399 410 (and (not (zerop calendar-daylight-time-offset))
ed589f9a 411 (calendar-nth-named-day 2 0 3 year))))
cd72c399
GM
412
413(defun calendar-dst-ends (year)
e716fd62 414 "Return the date of YEAR on which daylight saving time ends.
cd72c399
GM
415This function respects the value of `calendar-dst-check-each-year-flag'."
416 (or (let ((expr (if calendar-dst-check-each-year-flag
417 (nth 2 (calendar-dst-find-startend year))
418 (nth 5 calendar-current-time-zone-cache))))
419 (if expr (eval expr)))
71ea27ee 420 ;; New US rules commencing 2007. ftp://elsie.nci.nih.gov/pub/.
cd72c399 421 (and (not (zerop calendar-daylight-time-offset))
ed589f9a 422 (calendar-nth-named-day 1 0 11 year))))
cd72c399 423
76db8823 424;; used by calc, solar.
ec230951 425(defun dst-in-effect (date)
e716fd62 426 "True if on absolute DATE daylight saving time is in effect.
021edd45 427Fractional part of DATE is local standard time of day."
e803eab7 428 (let* ((year (calendar-extract-year
ec230951 429 (calendar-gregorian-from-absolute (floor date))))
021edd45
ER
430 (dst-starts-gregorian (eval calendar-daylight-savings-starts))
431 (dst-ends-gregorian (eval calendar-daylight-savings-ends))
432 (dst-starts (and dst-starts-gregorian
ec230951 433 (+ (calendar-absolute-from-gregorian
021edd45 434 dst-starts-gregorian)
ec230951
ER
435 (/ calendar-daylight-savings-starts-time
436 60.0 24.0))))
021edd45 437 (dst-ends (and dst-ends-gregorian
ec230951 438 (+ (calendar-absolute-from-gregorian
021edd45 439 dst-ends-gregorian)
ec230951
ER
440 (/ (- calendar-daylight-savings-ends-time
441 calendar-daylight-time-offset)
442 60.0 24.0)))))
021edd45
ER
443 (and dst-starts dst-ends
444 (if (< dst-starts dst-ends)
445 (and (<= dst-starts date) (< date dst-ends))
446 (or (<= dst-starts date) (< date dst-ends))))))
ec230951 447
76db8823 448;; used by calc, lunar, solar.
ec230951
ER
449(defun dst-adjust-time (date time &optional style)
450 "Adjust, to account for dst on DATE, decimal fraction standard TIME.
451Returns a list (date adj-time zone) where `date' and `adj-time' are the values
452adjusted for `zone'; here `date' is a list (month day year), `adj-time' is a
453decimal fraction time, and `zone' is a string.
454
455Optional parameter STYLE forces the result time to be standard time when its
e716fd62 456value is 'standard and daylight saving time (if available) when its value is
ec230951
ER
457'daylight.
458
e716fd62 459Conversion to daylight saving time is done according to
ec230951
ER
460`calendar-daylight-savings-starts', `calendar-daylight-savings-ends',
461`calendar-daylight-savings-starts-time',
06e3b7ae 462`calendar-daylight-savings-ends-time', and `calendar-daylight-time-offset'."
ec230951 463 (let* ((rounded-abs-date (+ (calendar-absolute-from-gregorian date)
71ea27ee 464 (/ (round (* 60 time)) 60.0 24.0)))
ec230951 465 (dst (dst-in-effect rounded-abs-date))
71ea27ee
GM
466 (time-zone (if dst
467 calendar-daylight-time-zone-name
468 calendar-standard-time-zone-name))
469 (time (+ rounded-abs-date
ec230951
ER
470 (if dst (/ calendar-daylight-time-offset 24.0 60.0) 0))))
471 (list (calendar-gregorian-from-absolute (truncate time))
472 (* 24.0 (- time (truncate time)))
473 time-zone)))
474
3e03d7c7
JB
475(provide 'cal-dst)
476
c07e258b 477;; arch-tag: a141d204-213c-4ca5-bdc6-f9df3aa92aad
3e03d7c7 478;;; cal-dst.el ends here