*** The built-in ada-mode is now deleted. The GNU ELPA package is a
good replacement, even in very large source files.
-** Some conversions recommended for 'time-stamp-format' have changed.
+** time-stamp
+
+*** New '%5z' conversion for 'time-stamp-format' gives time zone offset.
+Specifying '%5z' in 'time-stamp-format' or 'time-stamp-pattern'
+expands to the time zone offset, e.g., '+0100'. The time zone used is
+specified by 'time-stamp-time-zone'.
+
+Because this feature is new in Emacs 27.1, do not use it in the local
+variables section of any file that might be edited by an older version
+of Emacs.
+
+*** Some conversions recommended for 'time-stamp-format' have changed.
The new documented/recommended %-conversions are closer to those
used by 'format-time-string' and are compatible at least as far back
as Emacs 22.1 (released in 2007).
%02S seconds
%w day number of week, Sunday is 0
%02y 2-digit year: `03' %Y 4-digit year: `2003'
-%#Z lowercase time zone name: `est' %Z gives uppercase: `EST'
+%Z time zone name: `EST' %#Z gives lowercase: `est'
+%5z time zone offset: `-0500' (since Emacs 27; see note below)
Non-date items:
%% a literal percent character: `%'
The default padding of some formats has changed to be more compatible
with format-time-string. To be compatible with older versions of Emacs,
specify a padding width (as shown) or use the : modifier to request the
-transitional behavior (again, as shown)."
+transitional behavior (again, as shown).
+
+The behavior of `%5z' is new in Emacs 27. If your files might be
+edited by older versions of Emacs also, do not use this format yet."
:type 'string
:group 'time-stamp
:version "27.1")
(cond
((eq cur-char ?%)
;; eat any additional args to allow for future expansion
- (setq alt-form nil change-case nil upcase nil field-width "")
+ (setq alt-form 0 change-case nil upcase nil field-width "")
(while (progn
(setq ind (1+ ind))
(setq cur-char (if (< ind fmt-len)
(setq prev-char cur-char)
;; some characters we actually use
(cond ((eq cur-char ?:)
- (setq alt-form t))
+ (setq alt-form (1+ alt-form)))
((eq cur-char ?#)
(setq change-case t))
((eq cur-char ?^)
((eq cur-char ?%)
"%")
((eq cur-char ?a) ;day of week
- (if alt-form
+ (if (> alt-form 0)
(if (string-equal field-width "")
(time-stamp--format "%A" time)
"") ;discourage "%:3a"
(time-stamp--format "%#A" time)
(time-stamp--format "%A" time)))
((eq cur-char ?b) ;month name
- (if alt-form
+ (if (> alt-form 0)
(if (string-equal field-width "")
(time-stamp--format "%B" time)
"") ;discourage "%:3b"
((eq cur-char ?w) ;weekday number, Sunday is 0
(time-stamp--format "%w" time))
((eq cur-char ?y) ;year
- (if alt-form
+ (if (> alt-form 0)
(string-to-number (time-stamp--format "%Y" time))
(if (or (string-equal field-width "")
(<= (string-to-number field-width) 2))
((eq cur-char ?z) ;time zone offset
(if change-case
"" ;discourage %z variations
- (if alt-form
- (time-stamp--format "%z" time)
- (time-stamp--format "%#Z" time)))) ;backward compat, will change
+ (cond ((= alt-form 0)
+ (if (string-equal field-width "")
+ (progn
+ (time-stamp-conv-warn "%z" "%#Z")
+ (time-stamp--format "%#Z" time))
+ (cond ((string-equal field-width "1")
+ (setq field-width "3")) ;%-z -> "+00"
+ ((string-equal field-width "2")
+ (setq field-width "5")) ;%_z -> "+0000"
+ ((string-equal field-width "4")
+ (setq field-width "0"))) ;discourage %4z
+ (time-stamp--format "%z" time)))
+ ((= alt-form 1)
+ (time-stamp--format "%:z" time))
+ ((= alt-form 2)
+ (time-stamp--format "%::z" time))
+ ((= alt-form 3)
+ (time-stamp--format "%:::z" time)))))
((eq cur-char ?Z) ;time zone name
(if change-case
(time-stamp--format "%#Z" time)
(system-name))
))
(and (numberp field-result)
- (not alt-form)
+ (= alt-form 0)
(string-equal field-width "")
;; no width provided; set width for default
(setq field-width "02"))
ALT-FORM is whether `#' specified. FIELD-WIDTH is the string
width specification or \"\". TIME is the time to convert."
(let ((format-string (concat "%" (char-to-string format-char))))
- (if (and alt-form (not (string-equal field-width "")))
+ (if (and (> alt-form 0) (not (string-equal field-width "")))
"" ;discourage "%:2d" and the like
(string-to-number (time-stamp--format format-string time)))))
(ert-deftest time-stamp-test-format-time-zone-offset ()
"Test time-stamp format %z."
(with-time-stamp-test-env
- ;; documented 1995-2019, will change
- (should (equal (time-stamp-string "%z" ref-time1)
- (format-time-string "%#Z" ref-time1 t)))
- ;; undocumented, changed in 2019
- (should (equal (time-stamp-string "%:z" ref-time1) "+0000"))
- (should (equal (time-stamp-string "%:7z" ref-time1) " +0000"))
- (should (equal (time-stamp-string "%:07z" ref-time1) " +0000"))
+ (let ((utc-abbr (format-time-string "%#Z" ref-time1 t)))
+ ;; documented 1995-2019, warned since 2019, will change
+ (time-stamp-should-warn
+ (equal (time-stamp-string "%z" ref-time1) utc-abbr)))
+ ;; implemented and documented (with compat caveat) since 2019
+ (should (equal (time-stamp-string "%5z" ref-time1) "+0000"))
(let ((time-stamp-time-zone "PST8"))
- (should (equal (time-stamp-string "%:z" ref-time1) "-0800")))
+ (should (equal (time-stamp-string "%5z" ref-time1) "-0800")))
(let ((time-stamp-time-zone "HST10"))
- (should (equal (time-stamp-string "%:z" ref-time1) "-1000")))
+ (should (equal (time-stamp-string "%5z" ref-time1) "-1000")))
(let ((time-stamp-time-zone "CET-1"))
- (should (equal (time-stamp-string "%:z" ref-time1) "+0100")))))
+ (should (equal (time-stamp-string "%5z" ref-time1) "+0100")))
+ ;; implemented since 2019, verify that these don't warn
+ (should (equal (time-stamp-string "%-z" ref-time1) "+00"))
+ (should (equal (time-stamp-string "%_z" ref-time1) "+0000"))
+ (should (equal (time-stamp-string "%:z" ref-time1) "+00:00"))
+ (should (equal (time-stamp-string "%::z" ref-time1) "+00:00:00"))
+ (should (equal (time-stamp-string "%:::z" ref-time1) "+00"))))
(ert-deftest time-stamp-test-format-non-date-conversions ()
"Test time-stamp formats for non-date items."