aboutsummaryrefslogtreecommitdiffstats
path: root/lisp
diff options
context:
space:
mode:
authorJay Belanger2012-12-02 18:54:11 -0600
committerJay Belanger2012-12-02 18:54:11 -0600
commit682ceaf895f61e14c3545aa26d7290507dac0a31 (patch)
treead8b38b60064e7bad161ccf4f856d3f49ea5d503 /lisp
parent2dd2e62273983693076360e1bc4e59a0f9184c68 (diff)
downloademacs-682ceaf895f61e14c3545aa26d7290507dac0a31.tar.gz
emacs-682ceaf895f61e14c3545aa26d7290507dac0a31.zip
* lisp/calc/calc-forms.el (math-absolute-from-iso-dt)
(math-date-to-iso-dt, math-parse-iso-date-validate) (math-iso-dt-to-date): New functions. (math-fd-iso-dt, math-fd-isoyear, math-fd-isoweek) (math-fd-isoweekday): New variables. (calc-date-notation, math-parse-standard-date, math-format-date) (math-format-date-part): Add support for more formatting codes.
Diffstat (limited to 'lisp')
-rw-r--r--lisp/ChangeLog10
-rw-r--r--lisp/calc/calc-forms.el147
2 files changed, 138 insertions, 19 deletions
diff --git a/lisp/ChangeLog b/lisp/ChangeLog
index 59622c72678..1fd8fffa8a8 100644
--- a/lisp/ChangeLog
+++ b/lisp/ChangeLog
@@ -1,3 +1,13 @@
12012-12-03 Jay Belanger <jay.p.belanger@gmail.com>
2
3 * calc/calc-forms.el (math-absolute-from-iso-dt)
4 (math-date-to-iso-dt, math-parse-iso-date-validate)
5 (math-iso-dt-to-date): New functions.
6 (math-fd-iso-dt, math-fd-isoyear, math-fd-isoweek)
7 (math-fd-isoweekday): New variables.
8 (calc-date-notation, math-parse-standard-date, math-format-date)
9 (math-format-date-part): Add support for more formatting codes.
10
12012-12-02 Dmitry Gutov <dgutov@yandex.ru> 112012-12-02 Dmitry Gutov <dgutov@yandex.ru>
2 12
3 * vc/vc.el (vc-delete-file, vc-rename-file): Default to the 13 * vc/vc.el (vc-delete-file, vc-rename-file): Default to the
diff --git a/lisp/calc/calc-forms.el b/lisp/calc/calc-forms.el
index 15a153059a8..9915799002f 100644
--- a/lisp/calc/calc-forms.el
+++ b/lisp/calc/calc-forms.el
@@ -95,7 +95,7 @@
95 (let ((case-fold-search nil)) 95 (let ((case-fold-search nil))
96 (and (not (string-match "<.*>" fmt)) 96 (and (not (string-match "<.*>" fmt))
97 ;; Find time part to put in <...> 97 ;; Find time part to put in <...>
98 (string-match "\\`[^hHspP]*\\([^ac-gi-lnoqrt-zAC-GI-OQRT-Z]*\\(bs\\|bm\\|bh\\|BS\\|BH\\|[hHmpPsS]\\)+[^ac-gi-lnoqrt-zAC-GI-OQRT-Z]*\\)[^hHspP]*\\'" fmt) 98 (string-match "\\`[^hHspPT]*\\([^ac-gi-lnoqrt-zAC-GI-OQRU-Z]*\\(bs\\|bm\\|bh\\|BS\\|BH\\|[hHmpPsST]\\)+[^ac-gi-lnoqrt-zAC-GI-OQRU-Z]*\\)[^hHspPT]*\\'" fmt)
99 (string-match (concat "[^ac-gi-lnoqrt-zAC-GI-OQRT-Z]*" 99 (string-match (concat "[^ac-gi-lnoqrt-zAC-GI-OQRT-Z]*"
100 (regexp-quote (math-match-substring fmt 1)) 100 (regexp-quote (math-match-substring fmt 1))
101 "[^ac-gi-lnoqrt-zAC-GI-OQRT-Z]*") fmt) 101 "[^ac-gi-lnoqrt-zAC-GI-OQRT-Z]*") fmt)
@@ -126,7 +126,7 @@
126 lfmt nil)) 126 lfmt nil))
127 (setq time nil)) 127 (setq time nil))
128 (t 128 (t
129 (if (string-match "\\`[^a-zA-Z]*[bB][a-zA-Z]" fmt) 129 (if (string-match "\\`[^a-zA-Z]*[bBZI][a-zA-Z]" fmt)
130 (setq pos2 (1+ pos2))) 130 (setq pos2 (1+ pos2)))
131 (while (and (< pos2 (length fmt)) 131 (while (and (< pos2 (length fmt))
132 (= (upcase (aref fmt pos2)) 132 (= (upcase (aref fmt pos2))
@@ -134,6 +134,7 @@
134 (setq pos2 (1+ pos2))) 134 (setq pos2 (1+ pos2)))
135 (setq sym (intern (substring fmt pos pos2))) 135 (setq sym (intern (substring fmt pos pos2)))
136 (or (memq sym '(Y YY BY YYY YYYY 136 (or (memq sym '(Y YY BY YYY YYYY
137 ZYYY IYYY Iww w
137 aa AA aaa AAA aaaa AAAA 138 aa AA aaa AAA aaaa AAAA
138 bb BB bbb BBB bbbb BBBB 139 bb BB bbb BBB bbbb BBBB
139 M MM BM mmm Mmm Mmmm MMM MMMM 140 M MM BM mmm Mmm Mmmm MMM MMMM
@@ -142,7 +143,7 @@
142 h hh bh H HH BH 143 h hh bh H HH BH
143 p P pp PP pppp PPPP 144 p P pp PP pppp PPPP
144 m mm bm s ss bs SS BS C 145 m mm bm s ss bs SS BS C
145 N n J j U b)) 146 N n J j U b T))
146 (and (eq sym 'X) (not lfmt) (not fullfmt)) 147 (and (eq sym 'X) (not lfmt) (not fullfmt))
147 (error "Bad format code: %s" sym)) 148 (error "Bad format code: %s" sym))
148 (and (memq sym '(bb BB bbb BBB bbbb BBBB)) 149 (and (memq sym '(bb BB bbb BBB bbbb BBBB))
@@ -455,6 +456,26 @@ in the Gregorian calendar and the remaining part determines the time."
455 (% (/ time 60) 60) 456 (% (/ time 60) 60)
456 (math-add (% time 60) (nth 2 parts))))))) 457 (math-add (% time 60) (nth 2 parts)))))))
457 458
459(defun math-date-to-iso-dt (date)
460 "Return the ISO8601 date (year week day) of DATE."
461 (unless (Math-integerp date)
462 (setq date (math-floor date)))
463 (let* ((approx (nth 0 (math-date-to-gregorian-dt (math-sub date 3))))
464 (year (math-add approx
465 (let ((y approx)
466 (sum 0))
467 (while (>= (math-compare date
468 (math-iso-dt-to-absolute (setq y (math-add y 1)) 1 1)) 0)
469 (setq sum (+ sum 1)))
470 sum))))
471 (list
472 year
473 (math-add (car (math-idivmod
474 (math-sub date (math-iso-dt-to-absolute year 1 1))
475 7))
476 1)
477 (cdr (math-idivmod date 7)))))
478
458(defun math-dt-to-date (dt) 479(defun math-dt-to-date (dt)
459 (or (integerp (nth 1 dt)) 480 (or (integerp (nth 1 dt))
460 (math-reject-arg (nth 1 dt) 'fixnump)) 481 (math-reject-arg (nth 1 dt) 'fixnump))
@@ -473,6 +494,16 @@ in the Gregorian calendar and the remaining part determines the time."
473 '(float 864 2))) 494 '(float 864 2)))
474 date))) 495 date)))
475 496
497(defun math-iso-dt-to-date (dt)
498 (let ((date (math-absolute-from-iso-dt (car dt) (nth 1 dt) (nth 2 dt))))
499 (if (nth 3 dt)
500 (math-add (math-float date)
501 (math-div (math-add (+ (* (nth 3 dt) 3600)
502 (* (nth 4 dt) 60))
503 (nth 5 dt))
504 '(float 864 2)))
505 date)))
506
476(defun math-date-parts (value &optional offset) 507(defun math-date-parts (value &optional offset)
477 (let* ((date (math-floor value)) 508 (let* ((date (math-floor value))
478 (time (math-round (math-mul (math-sub value (or offset date)) 86400) 509 (time (math-round (math-mul (math-sub value (or offset date)) 86400)
@@ -594,6 +625,14 @@ in the Gregorian calendar."
594;; calc-gregorian-switch is a customizable variable defined in calc.el 625;; calc-gregorian-switch is a customizable variable defined in calc.el
595(defvar calc-gregorian-switch) 626(defvar calc-gregorian-switch)
596 627
628(defun math-absolute-from-iso-dt (year week day)
629 "Return the DATE of the day given by the iso8601 day YEAR WEEK DAY."
630 (let* ((janfour (math-absolute-from-gregorian-dt year 1 4))
631 (prevmon (math-sub janfour
632 (cdr (math-idivmod (math-sub janfour 1) 7)))))
633 (math-add
634 (math-add prevmon (* (1- week) 7))
635 (if (zerop day) 6 (1- day)))))
597 636
598(defun math-absolute-from-dt (year month day) 637(defun math-absolute-from-dt (year month day)
599 "Return the DATE of the day given by the day YEAR MONTH DAY. 638 "Return the DATE of the day given by the day YEAR MONTH DAY.
@@ -638,6 +677,10 @@ in the Gregorian calendar."
638(defvar math-fd-minute) 677(defvar math-fd-minute)
639(defvar math-fd-second) 678(defvar math-fd-second)
640(defvar math-fd-bc-flag) 679(defvar math-fd-bc-flag)
680(defvar math-fd-iso-dt)
681(defvar math-fd-isoyear)
682(defvar math-fd-isoweek)
683(defvar math-fd-isoweekday)
641 684
642(defun math-format-date (math-fd-date) 685(defun math-format-date (math-fd-date)
643 (if (eq (car-safe math-fd-date) 'date) 686 (if (eq (car-safe math-fd-date) 'date)
@@ -645,12 +688,14 @@ in the Gregorian calendar."
645 (let ((entry (list math-fd-date calc-internal-prec calc-date-format))) 688 (let ((entry (list math-fd-date calc-internal-prec calc-date-format)))
646 (or (cdr (assoc entry math-format-date-cache)) 689 (or (cdr (assoc entry math-format-date-cache))
647 (let* ((math-fd-dt nil) 690 (let* ((math-fd-dt nil)
691 (math-fd-iso-dt nil)
648 (calc-group-digits nil) 692 (calc-group-digits nil)
649 (calc-leading-zeros nil) 693 (calc-leading-zeros nil)
650 (calc-number-radix 10) 694 (calc-number-radix 10)
651 (calc-twos-complement-mode nil) 695 (calc-twos-complement-mode nil)
652 math-fd-year math-fd-month math-fd-day math-fd-weekday 696 math-fd-year math-fd-month math-fd-day math-fd-weekday
653 math-fd-hour math-fd-minute math-fd-second 697 math-fd-hour math-fd-minute math-fd-second
698 math-fd-isoyear math-fd-isoweek math-fd-isoweekday
654 (math-fd-bc-flag nil) 699 (math-fd-bc-flag nil)
655 (fmt (apply 'concat (mapcar 'math-format-date-part 700 (fmt (apply 'concat (mapcar 'math-format-date-part
656 calc-date-format)))) 701 calc-date-format))))
@@ -690,6 +735,25 @@ as measured in the integer number of days before December 31, 1 BC (Gregorian)."
690 math-julian-date-beginning-int))) 735 math-julian-date-beginning-int)))
691 ((eq x 'U) 736 ((eq x 'U)
692 (math-format-number (nth 1 (math-date-parts math-fd-date 719164)))) 737 (math-format-number (nth 1 (math-date-parts math-fd-date 719164))))
738 ((memq x '(IYYY Iww w))
739 (progn
740 (or math-fd-iso-dt
741 (setq math-fd-iso-dt (math-date-to-iso-dt math-fd-date)
742 jpb math-fd-date
743 jpbb math-fd-iso-dt
744 math-fd-isoyear (car math-fd-iso-dt)
745 math-fd-isoweek (nth 1 math-fd-iso-dt)
746 math-fd-isoweekday (nth 2 math-fd-iso-dt)))
747 (cond ((eq x 'IYYY)
748 (let* ((neg (Math-negp math-fd-isoyear))
749 (pyear (calcFunc-abs math-fd-isoyear)))
750 (if (and (natnump pyear) (< pyear 10000))
751 (concat (if neg "-" "") (format "%04d" pyear))
752 (concat (if neg "-" "+") (math-format-number pyear)))))
753 ((eq x 'Iww)
754 (concat "W" (format "%02d" math-fd-isoweek)))
755 ((eq x 'w)
756 (format "%d" math-fd-isoweekday)))))
693 ((progn 757 ((progn
694 (or math-fd-dt 758 (or math-fd-dt
695 (progn 759 (progn
@@ -720,6 +784,15 @@ as measured in the integer number of days before December 31, 1 BC (Gregorian)."
720 (if (and (natnump math-fd-year) (< math-fd-year 100)) 784 (if (and (natnump math-fd-year) (< math-fd-year 100))
721 (format "+%d" math-fd-year) 785 (format "+%d" math-fd-year)
722 (math-format-number math-fd-year))) 786 (math-format-number math-fd-year)))
787 ((eq x 'ZYYY)
788 (let* ((year (if (Math-negp math-fd-year)
789 (math-add math-fd-year 1)
790 math-fd-year))
791 (neg (Math-negp year))
792 (pyear (calcFunc-abs year)))
793 (if (and (natnump pyear) (< pyear 10000))
794 (concat (if neg "-" "") (format "%04d" pyear))
795 (concat (if neg "-" "+") (math-format-number pyear)))))
723 ((eq x 'b) "") 796 ((eq x 'b) "")
724 ((eq x 'aa) 797 ((eq x 'aa)
725 (and (not math-fd-bc-flag) "ad")) 798 (and (not math-fd-bc-flag) "ad"))
@@ -745,6 +818,7 @@ as measured in the integer number of days before December 31, 1 BC (Gregorian)."
745 (and math-fd-bc-flag "b.c.")) 818 (and math-fd-bc-flag "b.c."))
746 ((eq x 'BBBB) 819 ((eq x 'BBBB)
747 (and math-fd-bc-flag "B.C.")) 820 (and math-fd-bc-flag "B.C."))
821 ((eq x 'T) "T")
748 ((eq x 'M) 822 ((eq x 'M)
749 (format "%d" math-fd-month)) 823 (format "%d" math-fd-month))
750 ((eq x 'MM) 824 ((eq x 'MM)
@@ -1009,6 +1083,20 @@ as measured in the integer number of days before December 31, 1 BC (Gregorian)."
1009 (list 'date (math-dt-to-date (append (list year month day) 1083 (list 'date (math-dt-to-date (append (list year month day)
1010 (and hour (list hour minute second)))))) 1084 (and hour (list hour minute second))))))
1011 1085
1086(defun math-parse-iso-date-validate (isoyear isoweek isoweekday hour minute second)
1087 (if (or (< isoweek 1) (> isoweek 53))
1088 (throw 'syntax "Week value is out of range"))
1089 (and hour
1090 (progn
1091 (if (or (< hour 0) (> hour 23))
1092 (throw 'syntax "Hour value is out of range"))
1093 (if (or (< minute 0) (> minute 59))
1094 (throw 'syntax "Minute value is out of range"))
1095 (if (or (math-negp second) (not (Math-lessp second 60)))
1096 (throw 'syntax "Seconds value is out of range"))))
1097 (list 'date (math-iso-dt-to-date (append (list isoyear isoweek isoweekday)
1098 (and hour (list hour minute second))))))
1099
1012(defun math-parse-date-word (names &optional front) 1100(defun math-parse-date-word (names &optional front)
1013 (let ((n 1)) 1101 (let ((n 1))
1014 (while (and names (not (string-match (if (equal (car names) "Sep") 1102 (while (and names (not (string-match (if (equal (car names) "Sep")
@@ -1029,6 +1117,7 @@ as measured in the integer number of days before December 31, 1 BC (Gregorian)."
1029 (let ((case-fold-search t) 1117 (let ((case-fold-search t)
1030 (okay t) num 1118 (okay t) num
1031 (fmt calc-date-format) this next (gnext nil) 1119 (fmt calc-date-format) this next (gnext nil)
1120 (isoyear nil) (isoweek nil) (isoweekday nil)
1032 (year nil) (month nil) (day nil) (bigyear nil) (yearday nil) 1121 (year nil) (month nil) (day nil) (bigyear nil) (yearday nil)
1033 (hour nil) (minute nil) (second nil) (bc-flag nil)) 1122 (hour nil) (minute nil) (second nil) (bc-flag nil))
1034 (while (and fmt okay) 1123 (while (and fmt okay)
@@ -1105,19 +1194,35 @@ as measured in the integer number of days before December 31, 1 BC (Gregorian)."
1105 (if (string-match "\\`pm\\|p\\.m\\." math-pd-str) 1194 (if (string-match "\\`pm\\|p\\.m\\." math-pd-str)
1106 (setq hour (if (= hour 12) 12 (% (+ hour 12) 24)) 1195 (setq hour (if (= hour 12) 12 (% (+ hour 12) 24))
1107 math-pd-str (substring math-pd-str (match-end 0)))))) 1196 math-pd-str (substring math-pd-str (match-end 0))))))
1108 ((memq this '(Y YY BY YYY YYYY)) 1197 ((memq this '(Y YY BY YYY YYYY ZYYY))
1109 (and (if (memq next '(MM DD ddd hh HH mm ss SS)) 1198 (and (if (memq next '(MM DD ddd hh HH mm ss SS))
1110 (if (memq this '(Y YY BYY)) 1199 (if (memq this '(Y YY BYY))
1111 (string-match "\\` *[0-9][0-9]" math-pd-str) 1200 (string-match "\\` *[0-9][0-9]" math-pd-str)
1112 (string-match "\\`[0-9][0-9][0-9][0-9]" math-pd-str)) 1201 (string-match "\\`[0-9][0-9][0-9][0-9]" math-pd-str))
1113 (string-match "\\`[-+]?[0-9]+" math-pd-str)) 1202 (string-match "\\`[-+]?[0-9]+" math-pd-str))
1114 (setq year (math-match-substring math-pd-str 0) 1203 (setq year (math-match-substring math-pd-str 0)
1115 bigyear (or (eq this 'YYY) 1204 bigyear (or (eq this 'YYY)
1116 (memq (aref math-pd-str 0) '(?\+ ?\-))) 1205 (memq (aref math-pd-str 0) '(?\+ ?\-)))
1117 math-pd-str (substring math-pd-str (match-end 0)) 1206 math-pd-str (substring math-pd-str (match-end 0))
1118 year (math-read-number year)))) 1207 year (math-read-number year))
1208 (if (and (eq this 'ZYYY) (eq year 0))
1209 (setq year (math-sub year 1)
1210 bigyear t)
1211 t)))
1212 ((eq this 'IYYY)
1213 (if (string-match "\\`[-+]?[0-9]+" math-pd-str)
1214 (setq isoyear (string-to-number (math-match-substring math-pd-str 0))
1215 math-pd-str (substring math-pd-str (match-end 0)))))
1216 ((eq this 'Iww)
1217 (if (string-match "W\\([0-9][0-9]\\)" math-pd-str)
1218 (setq isoweek (string-to-number (math-match-substring math-pd-str 1))
1219 math-pd-str (substring math-pd-str 3))))
1119 ((eq this 'b) 1220 ((eq this 'b)
1120 t) 1221 t)
1222 ((eq this 'T)
1223 (if (eq (aref math-pd-str 0) ?T)
1224 (setq math-pd-str (substring math-pd-str 1))
1225 t))
1121 ((memq this '(aa AA aaaa AAAA)) 1226 ((memq this '(aa AA aaaa AAAA))
1122 (if (string-match "\\` *\\(ad\\|a\\.d\\.\\)" math-pd-str) 1227 (if (string-match "\\` *\\(ad\\|a\\.d\\.\\)" math-pd-str)
1123 (setq math-pd-str (substring math-pd-str (match-end 0))))) 1228 (setq math-pd-str (substring math-pd-str (match-end 0)))))
@@ -1152,7 +1257,9 @@ as measured in the integer number of days before December 31, 1 BC (Gregorian)."
1152 nil)) 1257 nil))
1153 nil) 1258 nil)
1154 ((eq this 'W) 1259 ((eq this 'W)
1155 (and (>= num 0) (< num 7))) 1260 (and (>= num 0) (< num 7)))
1261 ((eq this 'w)
1262 (setq isoweekday num))
1156 ((memq this '(d ddd bdd)) 1263 ((memq this '(d ddd bdd))
1157 (setq yearday num)) 1264 (setq yearday num))
1158 ((memq this '(M MM BM)) 1265 ((memq this '(M MM BM))
@@ -1169,18 +1276,20 @@ as measured in the integer number of days before December 31, 1 BC (Gregorian)."
1169 (setq yearday nil) 1276 (setq yearday nil)
1170 (setq month 1 day 1))) 1277 (setq month 1 day 1)))
1171 (if (and okay (equal math-pd-str "")) 1278 (if (and okay (equal math-pd-str ""))
1172 (and month day (or (not (or hour minute second)) 1279 (if isoyear
1173 (and hour minute)) 1280 (math-parse-iso-date-validate isoyear isoweek isoweekday hour minute second)
1174 (progn 1281 (and month day (or (not (or hour minute second))
1175 (or year (setq year (math-this-year))) 1282 (and hour minute))
1176 (or second (setq second 0)) 1283 (progn
1177 (if bc-flag 1284 (or year (setq year (math-this-year)))
1178 (setq year (math-neg (math-abs year)))) 1285 (or second (setq second 0))
1179 (setq day (math-parse-date-validate year bigyear month day 1286 (if bc-flag
1180 hour minute second)) 1287 (setq year (math-neg (math-abs year))))
1181 (if yearday 1288 (setq day (math-parse-date-validate year bigyear month day
1182 (setq day (math-add day (1- yearday)))) 1289 hour minute second))
1183 day))))) 1290 (if yearday
1291 (setq day (math-add day (1- yearday))))
1292 day))))))
1184 1293
1185 1294
1186(defun calcFunc-now (&optional zone) 1295(defun calcFunc-now (&optional zone)