branch: elpa/datetime
commit 2f8037f0ba47f6da29afae074b1c5ce507839f6c
Author: Paul Pogonyshev <pogonys...@gmail.com>
Commit: Paul Pogonyshev <pogonys...@gmail.com>

    Implement timezone offset formatting (currently, only 'Z' in a Java 
pattern).
---
 datetime.el    | 42 +++++++++++++++++++++++++++---------------
 test/format.el |  5 +++++
 2 files changed, 32 insertions(+), 15 deletions(-)

diff --git a/datetime.el b/datetime.el
index 6596a4d6e1..fb9eebe8ae 100644
--- a/datetime.el
+++ b/datetime.el
@@ -177,7 +177,8 @@
 (defvar datetime--pattern-formatters '((parsed . (lambda (parts options) 
parts))
                                        (java   . 
datetime--format-java-pattern)))
 
-(defvar datetime--last-conversion-was-in-dst nil)
+;; Floating-point offset is our internal mark of a transition to DST.
+(defvar datetime--last-conversion-offset nil)
 
 (defvar datetime--locale-timezone-name-lookup-cache nil)
 (defvar datetime--locale-timezone-name-lookup-cache-version 0)
@@ -676,7 +677,21 @@ to this function.
                   (if (string= name dst-name)
                       (push (datetime--format-escape-string name) format-parts)
                     (push "%s" format-parts)
-                    (push `(if datetime--last-conversion-was-in-dst ,dst-name 
,name) format-arguments))))
+                    ;; See comments for the variable for explanation of 
`floatp'.
+                    (push `(if (floatp datetime--last-conversion-offset) 
,dst-name ,name) format-arguments))))
+               (`rfc-822
+                (pcase timezone-data
+                  (`(,constant-offset)
+                   (push (format "%c%02d%02d"
+                                 (if (>= constant-offset 0) ?+ ?-)
+                                 (/ (abs constant-offset) (* 60 60))
+                                 (/ (mod (abs constant-offset) (* 60 60)) 60))
+                         format-parts))
+                  (_
+                   (push "%c%02d%02d" format-parts)
+                   (push `(if (>= datetime--last-conversion-offset 0) ?+ ?-) 
format-arguments)
+                   (push `(/ (abs (round datetime--last-conversion-offset)) (* 
60 60)) format-arguments)
+                   (push `(/ (mod (abs (round 
datetime--last-conversion-offset)) (* 60 60)) 60) format-arguments))))
                (_
                 (signal 'datetime-unsupported-timezone details))))
             (_ (error "Unexpected value %s" type))))))
@@ -747,24 +762,21 @@ to this function.
 
 (defun datetime--convert-to-utc-float (date-time timezone-data)
   (let ((year-offset          (floor (/ (- date-time (car timezone-data)) 
datetime--average-seconds-in-year)))
-        (all-year-transitions (nth 1 timezone-data)))
+        (all-year-transitions (nth 1 timezone-data))
+        offset)
     (if (>= year-offset 0)
-        (let* ((year-transitions (or (when (< year-offset (length 
all-year-transitions))
-                                       (aref all-year-transitions year-offset))
-                                     (datetime--calculate-year-transitions 
timezone-data year-offset)))
-               (offset           (pop year-transitions)))
+        (let ((year-transitions (or (when (< year-offset (length 
all-year-transitions))
+                                      (aref all-year-transitions year-offset))
+                                    (datetime--calculate-year-transitions 
timezone-data year-offset))))
+          (setf offset (pop year-transitions))
           (when year-transitions
             (let ((offset-in-year (floor (- date-time (car timezone-data) (* 
year-offset datetime--average-seconds-in-year)))))
               (while (and (>= offset-in-year (car year-transitions))
-                          (setq offset           (cadr year-transitions)
-                                year-transitions (cddr year-transitions))))))
-          ;; Floating-point offset is our internal mark of a transition to 
DST.  Its value
-          ;; is really an integer anyway.
-          (setf datetime--last-conversion-was-in-dst (floatp offset))
-          (+ date-time offset))
+                          (setf offset           (cadr year-transitions)
+                                year-transitions (cddr year-transitions)))))))
       ;; Offset before the very first transition.
-      (setf datetime--last-conversion-was-in-dst nil)
-      (+ date-time (car (aref all-year-transitions 0))))))
+      (setf offset (car (aref all-year-transitions 0))))
+    (+ date-time (setf datetime--last-conversion-offset offset))))
 
 ;; 146097 is the value of `datetime--gregorian-days-in-400-years'.
 ;; `eval-when-compile' doesn't allow referring to the mnemonic name.
diff --git a/test/format.el b/test/format.el
index b8af6663d4..b7141f42c6 100644
--- a/test/format.el
+++ b/test/format.el
@@ -142,6 +142,11 @@
       ;; Exact numbers don't matter much, we just need to skip a few months 
each time.
       (datetime--test-formatter (mapcar (lambda (k) (* k 7000000)) 
(number-sequence -300 400))))))
 
+(ert-deftest datetime-formatting-with-timezone-name-3 ()
+  (dolist (timezone (datetime-list-timezones))
+    (datetime--test-set-up-formatter timezone 'en "yyyy-MM-dd HH:mm:ssZ"
+      (datetime--test-formatter-around-transition 1414285200))))
+
 (ert-deftest datetime-formatting-day-periods ()
   (let (times)
     (dotimes (minute (* 24 60))

Reply via email to