Improve handling of years with limitations on representable dates

* lisp/org.el (org-read-date-force-compatible-dates): New option.
(org-read-date, org-read-date-analyze): Check representable date range.
* doc/org.texi (The date/time prompt): Document date range protection.

New variable `org-read-date-force-compatible-dates' to control
handling of dates.
This commit is contained in:
Carsten Dominik 2011-03-13 08:06:22 +01:00
parent 0dc16a0fe9
commit f4387417c4
2 changed files with 63 additions and 5 deletions

View File

@ -5397,9 +5397,17 @@ The function understands English month and weekday abbreviations. If
you want to use unabbreviated names and/or other languages, configure you want to use unabbreviated names and/or other languages, configure
the variables @code{parse-time-months} and @code{parse-time-weekdays}. the variables @code{parse-time-months} and @code{parse-time-weekdays}.
@vindex org-read-date-force-compatible-dates
Not all dates can be represented in a given Emacs implementation. By default
Org mode forces dates into the compatibility range 1970--2037 which works on
all Emacs implementations. If you want to use dates outside of this range,
read the docstring of the variable
@code{org-read-date-force-compatible-dates}.
You can specify a time range by giving start and end times or by giving a You can specify a time range by giving start and end times or by giving a
start time and a duration (in HH:MM format). Use `-' or `-@{@}-' as the separator start time and a duration (in HH:MM format). Use `-' or `-@{@}-' as the
in the former case and use '+' as the separator in the latter case. E.g.@: separator in the former case and use '+' as the separator in the latter
case. E.g.@:
@example @example
11am-1:15pm @result{} 11:00-13:15 11am-1:15pm @result{} 11:00-13:15

View File

@ -2652,6 +2652,36 @@ This may t or nil, or the symbol `org-read-date-prefer-future'."
(const :tag "Never" nil) (const :tag "Never" nil)
(const :tag "Always" t))) (const :tag "Always" t)))
(defcustom org-read-date-force-compatible-dates t
"Should date/time prompt force dates that are guaranteed to work in Emacs?
Depending on the system Emacs is running on, certain dates cannot
be represented with the type used internally to represent time.
Dates between 1970-1-1 and 2038-1-1 can always be represented
correctly. Some systems allow for earlier dates, some for later,
some for both. One way to find out it to insert any date into an
Org buffer, putting the cursor on the year and hitting S-up and
S-down to test the range.
When this variable is set to t, the date/time prompt will not let
you specify dates outside the 1970-2037 range, so it is certain that
these dates will work in whatever version of Emacs you are
running, and also that you can move a file from one Emacs implementation
to another. WHenever Org is forcing the year for you, it will display
a message and beep.
When this variable is nil, Org will check if the date is
representable in the specific Emacs implementation you are using.
If not, it will force a year, usually the current year, and beep
to remind you. Currently this setting is not recommended because
the likelihood that you will open your Org files in an Emacs that
has limited date range is not negligible.
A workaround for this problem is to use diary sexp dates for time
stamps outside of this range."
:group 'org-time
:type 'boolean)
(defcustom org-read-date-display-live t (defcustom org-read-date-display-live t
"Non-nil means display current interpretation of date prompt live. "Non-nil means display current interpretation of date prompt live.
This display will be in an overlay, in the minibuffer." This display will be in an overlay, in the minibuffer."
@ -14332,6 +14362,8 @@ So these are more for recording a certain time/date."
(defvar org-dcst nil) ; dynamically scoped (defvar org-dcst nil) ; dynamically scoped
(defvar org-read-date-history nil) (defvar org-read-date-history nil)
(defvar org-read-date-final-answer nil) (defvar org-read-date-final-answer nil)
(defvar org-read-date-analyze-futurep nil)
(defvar org-read-date-analyze-forced-year nil)
(defun org-read-date (&optional with-time to-time from-string prompt (defun org-read-date (&optional with-time to-time from-string prompt
default-time default-input) default-time default-input)
@ -14504,6 +14536,13 @@ user."
(setq final (org-read-date-analyze ans def defdecode)) (setq final (org-read-date-analyze ans def defdecode))
(when org-read-date-analyze-forced-year
(message "Year was forced into %s"
(if org-read-date-force-compatible-dates
"compatible range (1970-2037)"
"range representable on this machine"))
(ding))
;; One round trip to get rid of 34th of August and stuff like that.... ;; One round trip to get rid of 34th of August and stuff like that....
(setq final (decode-time (apply 'encode-time final))) (setq final (decode-time (apply 'encode-time final)))
@ -14520,7 +14559,6 @@ user."
(defvar def) (defvar def)
(defvar defdecode) (defvar defdecode)
(defvar with-time) (defvar with-time)
(defvar org-read-date-analyze-futurep nil)
(defun org-read-date-display () (defun org-read-date-display ()
"Display the current date prompt interpretation in the minibuffer." "Display the current date prompt interpretation in the minibuffer."
(when org-read-date-display-live (when org-read-date-display-live
@ -14563,7 +14601,8 @@ user."
delta deltan deltaw deltadef year month day delta deltan deltaw deltadef year month day
hour minute second wday pm h2 m2 tl wday1 hour minute second wday pm h2 m2 tl wday1
iso-year iso-weekday iso-week iso-year iso-date futurep kill-year) iso-year iso-weekday iso-week iso-year iso-date futurep kill-year)
(setq org-read-date-analyze-futurep nil) (setq org-read-date-analyze-futurep nil
org-read-date-analyze-forced-year nil)
(when (string-match "\\`[ \t]*\\.[ \t]*\\'" ans) (when (string-match "\\`[ \t]*\\.[ \t]*\\'" ans)
(setq ans "+0")) (setq ans "+0"))
@ -14721,7 +14760,18 @@ user."
(nth 2 tl)) (nth 2 tl))
(setq org-time-was-given t)) (setq org-time-was-given t))
(if (< year 100) (setq year (+ 2000 year))) (if (< year 100) (setq year (+ 2000 year)))
(if (< year 1970) (setq year (nth 5 defdecode))) ; not representable ;; Check of the date is representable
(if org-read-date-force-compatible-dates
(progn
(if (< year 1970)
(setq year 1970 org-read-date-analyze-forced-year t))
(if (> year 2037)
(setq year 2037 org-read-date-analyze-forced-year t)))
(condition-case nil
(encode-time second minute hour day month year)
(error
(setq year (nth 5 defdecode))
(setq org-read-date-analyze-forced-year t))))
(setq org-read-date-analyze-futurep futurep) (setq org-read-date-analyze-futurep futurep)
(list second minute hour day month year))) (list second minute hour day month year)))