Function: format-seconds

format-seconds is an autoloaded and byte-compiled function defined in time-date.el.gz.

Signature

(format-seconds STRING SECONDS)

Documentation

Use format control STRING to format the number SECONDS.

The valid format specifiers are:
%y is the number of (365-day) years.
%d is the number of days.
%h is the number of hours.
%m is the number of minutes.
%s is the number of seconds.
%z is a non-printing control flag (see below).
%% is a literal "%".

Upper-case specifiers are followed by the unit-name (e.g. "years"). Lower-case specifiers return only the unit.

"%" may be followed by a number specifying a width, with an
optional leading "." for zero-padding. For example, "%.3Y" will return something of the form "001 year".

The "%s" spec takes an additional optional parameter, introduced by the "," character, to say how many decimals to use. "%,1s" means "use one decimal".

The "%z" specifier does not print anything. When it is used, specifiers must be given in order of decreasing size. To the left of "%z", nothing is output until the first non-zero unit is encountered.

Probably introduced at or before Emacs version 23.1.

Aliases

org-format-seconds (obsolete since 9.0)

Source Code

;; Defined in /usr/src/emacs/lisp/calendar/time-date.el.gz
;;;###autoload
(defun format-seconds (string seconds)
  "Use format control STRING to format the number SECONDS.
The valid format specifiers are:
%y is the number of (365-day) years.
%d is the number of days.
%h is the number of hours.
%m is the number of minutes.
%s is the number of seconds.
%z is a non-printing control flag (see below).
%% is a literal \"%\".

Upper-case specifiers are followed by the unit-name (e.g. \"years\").
Lower-case specifiers return only the unit.

\"%\" may be followed by a number specifying a width, with an
optional leading \".\" for zero-padding.  For example, \"%.3Y\" will
return something of the form \"001 year\".

The \"%s\" spec takes an additional optional parameter,
introduced by the \",\" character, to say how many decimals to
use.  \"%,1s\" means \"use one decimal\".

The \"%z\" specifier does not print anything.  When it is used, specifiers
must be given in order of decreasing size.  To the left of \"%z\", nothing
is output until the first non-zero unit is encountered."
  (let ((start 0)
        (units '(("y" "year"   31536000)
                 ("d" "day"       86400)
                 ("h" "hour"       3600)
                 ("m" "minute"       60)
                 ("s" "second"        1)
                 ("z")))
        (case-fold-search t)
        spec match usedunits zeroflag larger prev name unit num zeropos
        fraction)
    (while (string-match "%\\.?[0-9]*\\(,[0-9]\\)?\\(.\\)" string start)
      (setq start (match-end 0)
            spec (match-string 2 string))
      (unless (string-equal spec "%")
        (or (setq match (assoc (downcase spec) units))
            (error "Bad format specifier: `%s'" spec))
        (if (assoc (downcase spec) usedunits)
            (error "Multiple instances of specifier: `%s'" spec))
        (if (string-equal (car match) "z")
            (setq zeroflag t)
          (unless larger
            (setq unit (nth 2 match)
                  larger (and prev (> unit prev))
                  prev unit)))
        (push match usedunits)))
    (and zeroflag larger
         (error "Units are not in decreasing order of size"))
    (unless (numberp seconds)
      (setq seconds (float-time seconds)))
    (setq fraction (mod seconds 1)
          seconds (round seconds))
    (dolist (u units)
      (setq spec (car u)
            name (cadr u)
            unit (nth 2 u))
      (when (string-match
             (format "%%\\(\\.?[0-9]+\\)?\\(,[0-9]+\\)?\\(%s\\)" spec)
             string)
        (if (string-equal spec "z")     ; must be last in units
            (setq string
                  (replace-regexp-in-string
                   "%z" ""
                   (substring string (min (or zeropos (match-end 0))
                                          (match-beginning 0)))))
          ;; Cf article-make-date-line in gnus-art.
          (setq num (floor seconds unit)
                seconds (- seconds (* num unit)))
          ;; Start position of the first non-zero unit.
          (or zeropos
              (setq zeropos (unless (zerop num) (match-beginning 0))))
          (setq string
                (replace-match
                 (format (if (match-string 2 string)
                             (concat
                              "%"
                              (and (match-string 1 string)
                                   (if (= (elt (match-string 1 string) 0) ?.)
                                       (concat "0" (substring
                                                    (match-string 1 string) 1))
                                     (match-string 1 string)))
                              (concat "." (substring
                                           (match-string 2 string) 1))
                              "f%s")
                           (concat "%" (match-string 1 string) "d%s"))
                         (if (= unit 1)
                             (+ num fraction)
                           num)
                         (if (string-equal (match-string 3 string) spec)
                             ""         ; lower-case, no unit-name
                           (format " %s%s" name
                                   (if (= num 1) "" "s"))))
                 t t string))))))
  (string-replace "%%" "%" string))