branch: elpa/casual
commit 8a4e58895316db28a559e827cfab8162da9b4d55
Author: Charles Choi <[email protected]>
Commit: Charles Choi <[email protected]>

    Fix local time to remote time zone conversion
    
    - Fix for bug in dealing with AEST #231
    - Change to use more precise ISO 8601 date parsing.
---
 lisp/casual-timezone-utils.el       | 20 +++++++++++---
 tests/test-casual-timezone-utils.el | 55 ++++++++++++++++++++++++++++++++++++-
 2 files changed, 70 insertions(+), 5 deletions(-)

diff --git a/lisp/casual-timezone-utils.el b/lisp/casual-timezone-utils.el
index aeb68dd47a..801b765ac4 100644
--- a/lisp/casual-timezone-utils.el
+++ b/lisp/casual-timezone-utils.el
@@ -26,6 +26,7 @@
 (require 'org)
 (require 'vtable)
 (require 'casual-lib)
+(require 'iso8601)
 
 (defconst casual-timezone-unicode-db
   '((:previous . '("↑" "Previous"))
@@ -167,18 +168,28 @@ The format of the timestamp is defined in the variable
          (parse-ts (string-split datestr))
          (datestamp (nth 0 parse-ts))
          (timestamp (or (nth 1 parse-ts) "00:00"))
-         (local-tz (nth 1 (current-time-zone)))
+         (ctz (current-time-zone))
+         (local-tz (casual-timezone--zone-seconds-to-hours (nth 0 ctz)))
          (remote-time
           (format-time-string
            casual-timezone-convert-datestamp-format
-           (date-to-time
-            (concat datestamp " " timestamp ":00" " " local-tz))
+           (encode-time (iso8601-parse
+                         (concat datestamp "T" timestamp ":00" local-tz)))
            remote-tz))
          (remote-time-tz (concat remote-tz " " remote-time)))
     (kill-new remote-time-tz)
     (message remote-time-tz)
     remote-time-tz))
 
+(defun casual-timezone--zone-seconds-to-hours (tz)
+  "Convert TZ in seconds to ISO8601 timezone string."
+  (let* ((abs-tz (abs tz))
+         (hours (/ abs-tz 3600))
+         (remain (round (* (/ (mod abs-tz 3600) 3600.0) 60)))
+         (sign (if (< tz 0) "-" "+"))
+         (result (format "%s%02d%02d" sign hours remain)))
+    result))
+
 (defun casual-timezone-remote-time-to-local (&optional datestr remote-tz)
   "Convert date string DATESTR in remote timezone REMOTE-TZ to local.
 
@@ -209,7 +220,8 @@ The format of the timestamp is defined in the variable
          (index-time
           (format-time-string
            casual-timezone-convert-datestamp-format
-           (date-to-time (concat datestamp " " timestamp ":00" " " tzcode)))))
+           (encode-time
+            (iso8601-parse (concat datestamp "T" timestamp ":00" tzcode))))))
     (kill-new index-time)
     (message index-time)
     index-time))
diff --git a/tests/test-casual-timezone-utils.el 
b/tests/test-casual-timezone-utils.el
index 228ff76866..1fea140fd9 100644
--- a/tests/test-casual-timezone-utils.el
+++ b/tests/test-casual-timezone-utils.el
@@ -122,7 +122,6 @@
     (should (eq (keymap-lookup test-map "z") #'casual-timezone-planner))
     (should (eq (keymap-lookup test-map "c") #'calendar))))
 
-
 (ert-deftest test-casual-timezone-local-time-to-remote ()
   (let* ((read-date "2025-05-23 12:00")
          (remote-tz "Europe/Berlin")
@@ -131,6 +130,14 @@
 
     (should (string-equal control result))))
 
+(ert-deftest test-casual-timezone-local-time-to-remote-victoria ()
+  (let* ((read-date "2025-05-23 12:00")
+         (remote-tz "Australia/Victoria")
+         (control "Australia/Victoria 2025-05-24 05:00:00 AEST")
+         (result (casual-timezone-local-time-to-remote read-date remote-tz)))
+
+    (should (string-equal control result))))
+
 (ert-deftest test-casual-timezone-remote-time-to-local ()
   (let* ((read-date "2025-05-23 12:00")
          (remote-tz "Europe/Berlin")
@@ -139,6 +146,52 @@
 
     (should (string-equal control result))))
 
+(ert-deftest test-timezone-sanity-check ()
+  (let* ((ts "2025-06-04T17:00")
+         (control "2025-06-04 17:00:00 AEST")
+         (result
+          (format-time-string
+           casual-timezone-convert-datestamp-format
+           (encode-time (iso8601-parse (concat ts "+1000")))
+           "Australia/Victoria")))
+
+    (should (string-equal control result))))
+
+;; (format-time-string casual-timezone-convert-datestamp-format (encode-time 
(iso8601-parse "2025-06-04T17:00:00+0200")) "America/New_York")
+;; 2025-06-04 11:00:00 EDT
+
+(ert-deftest test-timezone-sanity-check2 ()
+  (let ((ts "2025-06-04T17:00")
+        (db (list
+             (list "+1000" "Australia/Victoria" "2025-06-04 17:00:00 AEST")
+             (list "+0200" "Europe/Berlin" "2025-06-04 17:00:00 CEST")
+             (list "+0500" "Asia/Karachi" "2025-06-04 17:00:00 PKT")
+             (list "+0530" "Asia/Kolkata" "2025-06-04 17:00:00 IST")
+             (list "+0900" "Asia/Seoul" "2025-06-04 17:00:00 KST")
+             (list "-0700" "America/Los_Angeles" "2025-06-04 17:00:00 PDT")
+             (list "-0400" "America/New_York" "2025-06-04 17:00:00 EDT"))))
+
+    (mapc (lambda (test-vector)
+            (let* ((offset (nth 0 test-vector))
+                   (tz (nth 1 test-vector))
+                   (control (nth 2 test-vector))
+                   (result
+                    (format-time-string
+                     casual-timezone-convert-datestamp-format
+                     (encode-time (iso8601-parse (concat ts offset)))
+                     tz)))
+              (print control)
+              (should (string-equal result control))))
+          db)))
+
+
+(ert-deftest test-casual-timezone--zone-seconds-to-hours ()
+  ;; (current-time-zone (current-time) "America/Chicago")
+  (should (string-equal (casual-timezone--zone-seconds-to-hours 32400) 
"+0900"))
+  (should (string-equal (casual-timezone--zone-seconds-to-hours 36000) 
"+1000"))
+  (should (string-equal (casual-timezone--zone-seconds-to-hours -18000) 
"-0500"))
+  (should (string-equal (casual-timezone--zone-seconds-to-hours +28800) 
"+0800"))
+  )
 
 (provide 'test-casual-timezone-utils)
 ;;; test-casual-timezone-utils.el ends here

Reply via email to