Function: time-stamp-formatz-from-parsed-options

time-stamp-formatz-from-parsed-options is a byte-compiled function defined in time-stamp.el.gz.

Signature

(time-stamp-formatz-from-parsed-options FLAG-MINIMIZE FLAG-PAD-SPACES-ONLY FLAG-PAD-ZEROS-FIRST COLON-COUNT FIELD-WIDTH OFFSET-SECS)

Documentation

Format a time offset according to a %z variation.

With no flags, the output includes hours and minutes: +-HHMM unless there is a non-zero seconds part, in which case the seconds are included: +-HHMMSS

FLAG-MINIMIZE is whether "-" was specified. If non-nil, the output may be limited to hours if minutes and seconds are zero.

FLAG-PAD-SPACES-ONLY is whether "_" was specified. If non-nil, seconds must be output, so that any padding can be spaces only.

FLAG-PAD-ZEROS-FIRST is whether "0" was specified. If non-nil, padding to the requested FIELD-WIDTH (if any) is done by adding
00 seconds before padding with spaces.

COLON-COUNT is the number of colons preceding the "z" (0-3). One or two colons put that many colons in the output (+-HH:MM or +-HH:MM:SS). Three colons outputs only hours if minutes and seconds are zero and includes colon separators if minutes and seconds are output.

FIELD-WIDTH is a whole number giving the minimum number of characters in the output; 0 specifies no minimum. Additional characters will be added on the right if necessary. The added characters will be spaces unless FLAG-PAD-ZEROS-FIRST is non-nil.

OFFSET-SECS is the time zone offset (in seconds east of UTC) to be formatted according to the preceding parameters.

This is an internal function used by time-stamp.

Source Code

;; Defined in /usr/src/emacs/lisp/time-stamp.el.gz
;;; A principled, expressive implementation of time zone offset
;;; formatting ("%z" and variants).

;;; * Overarching principle for %z

;; The output should be clear and complete.
;;
;; That is,
;; a) it should be unambiguous what offset is represented, and
;; b) it should be possible to exactly recreate the offset.

;;; * Principles for %z

;; - The numeric fields are HHMMSS.
;; - The fixed point is at the left.  The first 2 digits are always
;;   hours, the next 2 (if they exist) minutes, and next 2 (if they
;;   exist) seconds.  "+11" is 11 hours (not 11 minutes, not 11 seconds).
;;   "+1015" is 10 hours 15 minutes (not 10 minutes 15 seconds).
;; - Each of the three numeric fields is two digits.
;;   "+1" and "+100" are illegal.  (Is that 1 hour? 10 hours? 100 hours?)
;; - The MMSS fields may be omitted only if both are 00.  Thus, the width
;;   of the field depends on the data.  (This is similar to how
;;   %B is always long enough to spell the entire month name.)
;; - The SS field may be omitted only if it is 00.
;; - Colons between the numeric fields are an option, unless the hours
;;   field is greater than 99, when colons are needed to prevent ambiguity.
;; - If padding with zeros, we must pad on the right, because the
;;   fixed point is at the left.  (This is similar to how %N,
;;   fractional seconds, must add its zeros on the right.)
;; - After zero-padding has filled out minutes and seconds with zeros,
;;   further padding can be blanks only.
;;   Any additional zeros would be confusing.

;;; * Padding for %z

;; Padding is under-specified, so we had to make choices.
;;
;; Principles guiding our choices:
;;
;; - The syntax should be easy to remember and the effect predictable.
;; - The syntax should enable as many useful effects as possible.
;;
;; Padding choices:
;;
;; - By default, pad with spaces, as other formats with non-digits do.
;;   The "0" flag pads first with zeros, until seconds are filled out.
;; - If padding with spaces, pad on the right.  This is consistent with
;;   how zero-padding works.  Padding on the right also keeps the fixed
;;   point in the same place, as other formats do for any given width.
;; - The %_z format always outputs seconds, allowing all added padding
;;   to be spaces.  Without this rule, there would be no way to
;;   request seconds that worked for both 2- and 3-digit hours.
;;   (We consider 3-digit hours not because such offsets are in use but
;;   instead to guide our design toward consistency and extensibility.)
;; - Conflicting options are rejected, lest users depend
;;   on incidental behavior.
;;
;; Padding combos that make no sense and are thus disallowed:
;;
;; %-:z   - minus minimizes to hours, : expands to minutes
;; %-::z  - minus minimizes to hours, :: expands to seconds
;; %_:z   - underscore requires seconds, : displays minutes
;; %_:::z - underscore requires seconds, ::: minimizes to hours
;;
;; Example padding effects (with offsets of 99 and 100 hours):
;;
;; %-7z   "+99    "   "+100:00"
;;  %7z   "+9900  "   "+100:00"
;; %07z   "+990000"   "+100:00"
;; %_7z   "+990000"   "+100:00:00"
;;
;; %7:::z "+99    "   "+100:00"
;; %7:z   "+99:00 "   "+100:00"
;; %07:z  "+99:00:00" "+100:00"
;; %7::z  "+99:00:00" "+100:00:00"

;;; * ABNF syntax of the offset string produced by %z

;; offset = sign ( hours [minutes [seconds]] /
;;                 hours [":" minutes [":" seconds]] /
;;                 bighours ":" minutes [":" seconds] ) padding
;; sign = "+" / "-"
;; hours = digitpair
;; minutes = digitpair
;; seconds = digitpair
;; digitpair = digit digit
;; digit = "0" / "1" / "2" / "3" / "4" / "5" / "6" / "7" / "8" / "9"
;; bighours = 1*digit digitpair
;; padding = *" "

(defun time-stamp-formatz-from-parsed-options (flag-minimize
                                               flag-pad-spaces-only
                                               flag-pad-zeros-first
                                               colon-count
                                               field-width
                                               offset-secs)
  "Format a time offset according to a %z variation.

With no flags, the output includes hours and minutes: +-HHMM
unless there is a non-zero seconds part, in which case the seconds
are included: +-HHMMSS

FLAG-MINIMIZE is whether \"-\" was specified.  If non-nil, the
output may be limited to hours if minutes and seconds are zero.

FLAG-PAD-SPACES-ONLY is whether \"_\" was specified.  If non-nil,
seconds must be output, so that any padding can be spaces only.

FLAG-PAD-ZEROS-FIRST is whether \"0\" was specified.  If non-nil,
padding to the requested FIELD-WIDTH (if any) is done by adding
00 seconds before padding with spaces.

COLON-COUNT is the number of colons preceding the \"z\" (0-3).  One or
two colons put that many colons in the output (+-HH:MM or +-HH:MM:SS).
Three colons outputs only hours if minutes and seconds are zero and
includes colon separators if minutes and seconds are output.

FIELD-WIDTH is a whole number giving the minimum number of characters
in the output; 0 specifies no minimum.  Additional characters will be
added on the right if necessary.  The added characters will be spaces
unless FLAG-PAD-ZEROS-FIRST is non-nil.

OFFSET-SECS is the time zone offset (in seconds east of UTC) to be
formatted according to the preceding parameters.

This is an internal function used by `time-stamp'."
  ;; Callers of this function need to have already parsed the %z
  ;; format string; this function accepts just the parts of the format.
  ;; `time-stamp-string-preprocess' is the full-fledged parser normally
  ;; used.  The unit test (in time-stamp-tests.el) defines the simpler
  ;; parser `format-time-offset'.
  (let ((hrs (/ (abs offset-secs) 3600))
        (mins (/ (% (abs offset-secs) 3600) 60))
        (secs (% (abs offset-secs) 60))
        (result ""))
    ;; valid option combo?
    (cond
     ((not (or (and flag-minimize (> colon-count 0))
               (and flag-pad-spaces-only (> colon-count 0))
               (and flag-pad-spaces-only flag-minimize)
               (and flag-pad-spaces-only flag-pad-zeros-first)
               (and flag-pad-zeros-first flag-minimize)))
      (setq result (concat result (if (>= offset-secs 0) "+" "-")))
      (setq result (concat result (format "%02d" hrs)))
      ;; Need minutes?
      (cond
       ((or (> hrs 99)
            (> mins 0)
            (> secs 0)
            (not (or flag-minimize (= colon-count 3)))
            (and (> field-width (length result))
                 flag-pad-zeros-first))
        ;; Need colon before minutes?
        (if (or (> colon-count 0)
                (> hrs 99))
            (setq result (concat result ":")))
        (setq result (concat result (format "%02d" mins)))
        ;; Need seconds, too?
        (cond
         ((or (> secs 0)
              (= colon-count 2)
              flag-pad-spaces-only
              (and (> field-width (length result))
                   flag-pad-zeros-first))
          ;; Need colon before seconds?
          (if (or (> colon-count 0)
                  (> hrs 99))
              (setq result (concat result ":")))
          (setq result (concat result (format "%02d" secs)))))))
      ;; Need padding?
      (let ((needed-padding (- field-width (length result))))
        (if (> needed-padding 0)
            (setq result (concat result (make-string needed-padding ?\s)))))))
    result))