From 85c55d453b77a874c8584ba8ae3cdfc1f8c933df Mon Sep 17 00:00:00 2001 From: Nicolas Goaziou Date: Tue, 6 Jan 2015 23:19:42 +0100 Subject: [PATCH] Fix `org-read-date-prefer-future' when rescheduling * lisp/org.el (org-read-date-analyze): When `org-read-date-prefer-future', offer a date in the future even if default date is different from now. * testing/lisp/test-org.el (test-org/org-read-date): Add tests. Reported-by: Rasmus --- lisp/org.el | 39 ++++++++++++++----- testing/lisp/test-org.el | 82 +++++++++++++++++++++++++++++++++++++++- 2 files changed, 110 insertions(+), 11 deletions(-) diff --git a/lisp/org.el b/lisp/org.el index c5cef0d61..e8e335684 100755 --- a/lisp/org.el +++ b/lisp/org.el @@ -16936,16 +16936,35 @@ user." (setq tl (parse-time-string ans) day (or (nth 3 tl) (nth 3 org-defdecode)) - month (or (nth 4 tl) - (if (and org-read-date-prefer-future - (nth 3 tl) (< (nth 3 tl) (nth 3 nowdecode))) - (prog1 (1+ (nth 4 nowdecode)) (setq futurep t)) - (nth 4 org-defdecode))) - year (or (and (not kill-year) (nth 5 tl)) - (if (and org-read-date-prefer-future - (nth 4 tl) (< (nth 4 tl) (nth 4 nowdecode))) - (prog1 (1+ (nth 5 nowdecode)) (setq futurep t)) - (nth 5 org-defdecode))) + month + (cond ((nth 4 tl)) + ((not org-read-date-prefer-future) (nth 4 org-defdecode)) + ;; Day was specified. Make sure DAY+MONTH + ;; combination happens in the future. + ((nth 3 tl) + (setq futurep t) + (if (< day (nth 3 nowdecode)) (1+ (nth 4 nowdecode)) + (nth 4 nowdecode))) + (t (nth 4 org-defdecode))) + year + (cond ((and (not kill-year) (nth 5 tl))) + ((not org-read-date-prefer-future) (nth 5 org-defdecode)) + ;; Month was guessed in the future and is at least + ;; equal to NOWDECODE's. Fix year accordingly. + (futurep + (if (or (> month (nth 4 nowdecode)) + (>= day (nth 3 nowdecode))) + (nth 5 nowdecode) + (1+ (nth 5 nowdecode)))) + ;; Month was specified. Make sure MONTH+YEAR + ;; combination happens in the future. + ((nth 4 tl) + (setq futurep t) + (cond ((> month (nth 4 nowdecode)) (nth 5 nowdecode)) + ((< month (nth 5 nowdecode)) (1+ (nth 5 nowdecode))) + ((< day (nth 3 nowdecode)) (1+ (nth 5 nowdecode))) + (t (nth 5 nowdecode)))) + (t (nth 5 org-defdecode))) hour (or (nth 2 tl) (nth 2 org-defdecode)) minute (or (nth 1 tl) (nth 1 org-defdecode)) second (or (nth 0 tl) 0) diff --git a/testing/lisp/test-org.el b/testing/lisp/test-org.el index 6134b827e..f206ac263 100644 --- a/testing/lisp/test-org.el +++ b/testing/lisp/test-org.el @@ -191,7 +191,87 @@ ;; Parse Europeans dates without year. (should (string-match "2[0-9]\\{3\\}-03-29 16:40" (let ((org-time-was-given t)) - (org-read-date t nil "29.03. 16:40"))))) + (org-read-date t nil "29.03. 16:40")))) + ;; Relative date applied to current time if there is single + ;; plus/minus, or to default date when there are two of them. + (should + (equal + "2015-03-04" + (flet ((current-time () (apply #'encode-time + (org-parse-time-string "2014-03-04")))) + (org-read-date + t nil "+1y" nil + (apply #'encode-time (org-parse-time-string "2012-03-29")))))) + (should + (equal + "2013-03-29" + (flet ((current-time () (apply #'encode-time + (org-parse-time-string "2014-03-04")))) + (org-read-date + t nil "++1y" nil + (apply #'encode-time (org-parse-time-string "2012-03-29")))))) + ;; When `org-read-date-prefer-future' is non-nil, prefer future + ;; dates (relatively to now) when incomplete. Otherwise, use + ;; default date. + (should + (equal + "2014-04-01" + (flet ((current-time () (apply #'encode-time + (org-parse-time-string "2014-03-04")))) + (let ((org-read-date-prefer-future t)) + (org-read-date t nil "1"))))) + (should + (equal + "2013-03-04" + (flet ((current-time () (apply #'encode-time + (org-parse-time-string "2012-03-29")))) + (let ((org-read-date-prefer-future t)) + (org-read-date t nil "3-4"))))) + (should + (equal + "2012-03-04" + (flet ((current-time () (apply #'encode-time + (org-parse-time-string "2012-03-29")))) + (let ((org-read-date-prefer-future nil)) + (org-read-date t nil "3-4"))))) + ;; When set to `org-read-date-prefer-future' is set to `time', read + ;; day is moved to tomorrow if specified hour is before current + ;; time. However, it only happens in no other part of the date is + ;; specified. + (should + (equal + "2012-03-30" + (flet ((current-time () (apply #'encode-time + (org-parse-time-string "2012-03-29 16:40")))) + (let ((org-read-date-prefer-future 'time)) + (org-read-date t nil "00:40" nil))))) + (should-not + (equal + "2012-03-30" + (flet ((current-time () (apply #'encode-time + (org-parse-time-string "2012-03-29 16:40")))) + (let ((org-read-date-prefer-future 'time)) + (org-read-date t nil "29 00:40" nil))))) + ;; Caveat: `org-read-date-prefer-future' always refers to current + ;; time, not default time, when they differ. + (should + (equal + "2014-04-01" + (flet ((current-time + () (apply #'encode-time (org-parse-time-string "2014-03-04")))) + (let ((org-read-date-prefer-future t)) + (org-read-date + t nil "1" nil + (apply #'encode-time (org-parse-time-string "2012-03-29"))))))) + (should + (equal + "2014-03-25" + (flet ((current-time + () (apply #'encode-time (org-parse-time-string "2014-03-04")))) + (let ((org-read-date-prefer-future t)) + (org-read-date + t nil "25" nil + (apply #'encode-time (org-parse-time-string "2012-03-29")))))))) (ert-deftest test-org/org-parse-time-string () "Test `org-parse-time-string'."