]> code.delx.au - gnu-emacs/blobdiff - lisp/calendar/cal-dst.el
(calendar-time-zone-daylight-rules): Add support
[gnu-emacs] / lisp / calendar / cal-dst.el
index a4c666eac5ef1308ff57b3c21ceed3f9f371e690..3e33f6cb9f355ab84c67efa33eca8957420eec3d 100644 (file)
@@ -1,6 +1,6 @@
 ;;; cal-dst.el --- calendar functions for daylight savings rules.
 
 ;;; cal-dst.el --- calendar functions for daylight savings rules.
 
-;; Copyright (C) 1993 Free Software Foundation, Inc.
+;; Copyright (C) 1993, 1994, 1995, 1996 Free Software Foundation, Inc.
 
 ;; Author: Paul Eggert <eggert@twinsun.com>
 ;;     Edward M. Reingold <reingold@cs.uiuc.edu>
 
 ;; Author: Paul Eggert <eggert@twinsun.com>
 ;;     Edward M. Reingold <reingold@cs.uiuc.edu>
@@ -9,20 +9,20 @@
 
 ;; This file is part of GNU Emacs.
 
 
 ;; This file is part of GNU Emacs.
 
+;; GNU Emacs is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 2, or (at your option)
+;; any later version.
+
 ;; GNU Emacs is distributed in the hope that it will be useful,
 ;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY.  No author or distributor
-;; accepts responsibility to anyone for the consequences of using it
-;; or for whether it serves any particular purpose or works at all,
-;; unless he says so in writing.  Refer to the GNU Emacs General Public
-;; License for full details.
-
-;; Everyone is granted permission to copy, modify and redistribute
-;; GNU Emacs, but only under the conditions described in the
-;; GNU Emacs General Public License.   A copy of this license is
-;; supposed to have been given to you along with GNU Emacs so you
-;; can know your rights and responsibilities.  It should be in a
-;; file named COPYING.  Among other things, the copyright notice
-;; and this notice must be preserved on all copies.
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs; see the file COPYING.  If not, write to the
+;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+;; Boston, MA 02111-1307, USA.
 
 ;;; Commentary:
 
 
 ;;; Commentary:
 
@@ -38,6 +38,7 @@
 ;;; Code:
 
 (require 'calendar)
 ;;; Code:
 
 (require 'calendar)
+(require 'cal-persia)
 
 (defvar calendar-current-time-zone-cache nil
   "Cache for result of calendar-current-time-zone.")
 
 (defvar calendar-current-time-zone-cache nil
   "Cache for result of calendar-current-time-zone.")
@@ -128,7 +129,7 @@ Return nil if no such transition can be found."
 
 (defun calendar-time-zone-daylight-rules (abs-date utc-diff)
   "Return daylight transition rule for ABS-DATE, UTC-DIFF sec offset from UTC.
 
 (defun calendar-time-zone-daylight-rules (abs-date utc-diff)
   "Return daylight transition rule for ABS-DATE, UTC-DIFF sec offset from UTC.
-ABS-DIFF must specify a day that contains a daylight savings transition.
+ABS-DATE must specify a day that contains a daylight savings transition.
 The result has the proper form for calendar-daylight-savings-starts'."
   (let* ((date (calendar-gregorian-from-absolute abs-date))
         (weekday (% abs-date 7))
 The result has the proper form for calendar-daylight-savings-starts'."
   (let* ((date (calendar-gregorian-from-absolute abs-date))
         (weekday (% abs-date 7))
@@ -153,7 +154,16 @@ The result has the proper form for calendar-daylight-savings-starts'."
                      (cons
                       (list 'calendar-nth-named-day 1 weekday m 'year j)
                       l)))
                      (cons
                       (list 'calendar-nth-named-day 1 weekday m 'year j)
                       l)))
-            l)))
+            l)
+          ;; 01-01 and 07-01 for this year's Persian calendar.
+          (if (and (= m 3) (<= 20 d) (<= d 21))
+              '((calendar-gregorian-from-absolute
+                 (calendar-absolute-from-persian
+                  (list 1 1 (- year 621))))))
+          (if (and (= m 9) (<= 22 d) (<= d 23))
+              '((calendar-gregorian-from-absolute
+                 (calendar-absolute-from-persian
+                  (list 7 1 (- year 621))))))))
         (prevday-sec (- -1 utc-diff)) ;; last sec of previous local day
         (year (1+ y)))
     ;; Scan through the next few years until only one rule remains.
         (prevday-sec (- -1 utc-diff)) ;; last sec of previous local day
         (year (1+ y)))
     ;; Scan through the next few years until only one rule remains.
@@ -247,11 +257,11 @@ it can't find."
               (cons
                (/ (abs (- t0-utc-diff t1-utc-diff)) 60)
                (if (< t0-utc-diff t1-utc-diff)
               (cons
                (/ (abs (- t0-utc-diff t1-utc-diff)) 60)
                (if (< t0-utc-diff t1-utc-diff)
-                   (list t0-name t1-name t1-rules t2-rules t2-time t1-time)
-                   (list t1-name t0-name t2-rules t1-rules t1-time t2-time)
+                   (list t0-name t1-name t1-rules t2-rules t1-time t2-time)
+                   (list t1-name t0-name t2-rules t1-rules t2-time t1-time)
                    )))))))))))
 
                    )))))))))))
 
-;;; The following six defvars relating to daylight savings time should NOT be
+;;; The following eight defvars relating to daylight savings time should NOT be
 ;;; marked to go into loaddefs.el where they would be evaluated when Emacs is
 ;;; dumped.  These variables' appropriate values depend on the conditions under
 ;;; which the code is INVOKED; so it's inappropriate to initialize them when
 ;;; marked to go into loaddefs.el where they would be evaluated when Emacs is
 ;;; dumped.  These variables' appropriate values depend on the conditions under
 ;;; which the code is INVOKED; so it's inappropriate to initialize them when
@@ -281,6 +291,8 @@ For example, \"EST\" in New York City, \"PST\" for Los Angeles.")
   "*Abbreviated name of daylight-savings time zone at `calendar-location-name'.
 For example, \"EDT\" in New York City, \"PDT\" for Los Angeles.")
   
   "*Abbreviated name of daylight-savings time zone at `calendar-location-name'.
 For example, \"EDT\" in New York City, \"PDT\" for Los Angeles.")
   
+;;;###autoload
+(put 'calendar-daylight-savings-starts 'risky-local-variable t)
 (defvar calendar-daylight-savings-starts
   (or (car (nthcdr 4 calendar-current-time-zone-cache))
       (and (not (zerop calendar-daylight-time-offset))
 (defvar calendar-daylight-savings-starts
   (or (car (nthcdr 4 calendar-current-time-zone-cache))
       (and (not (zerop calendar-daylight-time-offset))
@@ -302,6 +314,8 @@ If it starts on the first Sunday in April, you would set it to
 
 If the locale never uses daylight savings time, set this to nil.")
 
 
 If the locale never uses daylight savings time, set this to nil.")
 
+;;;###autoload
+(put 'calendar-daylight-savings-ends 'risky-local-variable t)
 (defvar calendar-daylight-savings-ends
   (or (car (nthcdr 5 calendar-current-time-zone-cache))
       (and (not (zerop calendar-daylight-time-offset))
 (defvar calendar-daylight-savings-ends
   (or (car (nthcdr 5 calendar-current-time-zone-cache))
       (and (not (zerop calendar-daylight-time-offset))
@@ -327,6 +341,57 @@ If the locale never uses daylight savings time, set this to nil.")
       calendar-daylight-savings-starts-time)
   "*Number of minutes after midnight that daylight savings time ends.")
 
       calendar-daylight-savings-starts-time)
   "*Number of minutes after midnight that daylight savings time ends.")
 
+(defun dst-in-effect (date)
+  "True if on absolute DATE daylight savings time is in effect.
+Fractional part of DATE is local standard time of day."
+  (let* ((year (extract-calendar-year
+                (calendar-gregorian-from-absolute (floor date))))
+         (dst-starts-gregorian (eval calendar-daylight-savings-starts))
+         (dst-ends-gregorian (eval calendar-daylight-savings-ends))
+         (dst-starts (and dst-starts-gregorian
+                          (+ (calendar-absolute-from-gregorian
+                              dst-starts-gregorian)
+                             (/ calendar-daylight-savings-starts-time
+                                60.0 24.0))))
+         (dst-ends (and dst-ends-gregorian
+                        (+ (calendar-absolute-from-gregorian
+                            dst-ends-gregorian)
+                           (/ (- calendar-daylight-savings-ends-time
+                                 calendar-daylight-time-offset)
+                              60.0 24.0)))))
+    (and dst-starts dst-ends
+         (if (< dst-starts dst-ends)
+             (and (<= dst-starts date) (< date dst-ends))
+           (or (<= dst-starts date) (< date dst-ends))))))
+
+(defun dst-adjust-time (date time &optional style)
+  "Adjust, to account for dst on DATE, decimal fraction standard TIME.
+Returns a list (date adj-time zone) where `date' and `adj-time' are the values
+adjusted for `zone'; here `date' is a list (month day year), `adj-time' is a
+decimal fraction time, and `zone' is a string.
+
+Optional parameter STYLE forces the result time to be standard time when its
+value is 'standard and daylight savings time (if available) when its value is
+'daylight.
+
+Conversion to daylight savings time is done according to
+`calendar-daylight-savings-starts', `calendar-daylight-savings-ends',
+`calendar-daylight-savings-starts-time',
+`calendar-daylight-savings-ends-time', and
+`calendar-daylight-savings-offset'."
+
+  (let* ((rounded-abs-date (+ (calendar-absolute-from-gregorian date)
+                             (/ (round (* 60 time)) 60.0 24.0)))
+         (dst (dst-in-effect rounded-abs-date))
+        (time-zone (if dst
+                       calendar-daylight-time-zone-name
+                       calendar-standard-time-zone-name))
+        (time (+ rounded-abs-date
+                  (if dst (/ calendar-daylight-time-offset 24.0 60.0) 0))))
+    (list (calendar-gregorian-from-absolute (truncate time))
+          (* 24.0 (- time (truncate time)))
+          time-zone)))
+
 (provide 'cal-dst)
 
 ;;; cal-dst.el ends here
 (provide 'cal-dst)
 
 ;;; cal-dst.el ends here