Emacs Lisp: xah-fix-datetime πŸš€

By Xah Lee. Date: . Last updated: .

Here's a command that fix datetime under cursor into yyyy-mm-dd format.

put this in your Emacs Init File:

(defun xah-fix-datetime (&optional Begin End)
  "Change timestamp under cursor into a yyyy-mm-dd format.
If there's a text selection, use that as input, else use current line.
Replace the text in selection or current line.

Any β€œday of week”, or β€œtime” info, or any other parts of the string, are discarded.
For example:
 TUESDAY, FEB 15, 2011 05:16 ET β†’ 2011-02-15
 November 28, 1994              β†’ 1994-11-28
 Nov. 28, 1994                  β†’ 1994-11-28
 11/28/1994                     β†’ 1994-11-28
 1994/11/28                     β†’ 1994-11-28

URL `http://xahlee.info/emacs/emacs/elisp_datetime_parser.html'
Version: 2020-09-08 2022-02-04"
  (interactive)
  (require 'parse-time)
  (let (xp1 xp2 xin)
    (if Begin
        (setq xp1 Begin)
      (if (region-active-p)
          (setq xp1 (region-beginning))
        (setq xp1 (line-beginning-position))))
    (if End
        (setq xp2 End)
      (if (region-active-p)
          (setq xp2 (region-end))
        (setq xp2 (line-end-position))))

    (setq xin (string-trim (buffer-substring-no-properties xp1 xp2)))

    (setq
     xin
     (cond
      ;; yyyymmdd
      ((string-match "\\([0-9][0-9][0-9][0-9]\\)\\([0-9][0-9]\\)\\([0-9][0-9]\\)" xin)
       (concat (match-string-no-properties 1 xin) "-" (match-string-no-properties 2 xin) "-" (match-string-no-properties 3 xin)))

      ;; yyyy/mm/dd
      ((string-match "\\([0-9][0-9][0-9][0-9]\\)/\\([0-9][0-9]\\)/\\([0-9][0-9]\\)" xin)
       (concat (match-string-no-properties 1 xin) "-" (match-string-no-properties 2 xin) "-" (match-string-no-properties 3 xin)))

      ;; mm/dd/yyyy
      ((string-match "\\([0-9][0-9]\\)/\\([0-9][0-9]\\)/\\([0-9][0-9][0-9][0-9]\\)" xin)
       (concat (match-string-no-properties 3 xin) "-" (match-string-no-properties 1 xin) "-" (match-string-no-properties 2 xin)))
      ;; m/dd/yyyy
      ((string-match "\\([0-9]\\)/\\([0-9][0-9]\\)/\\([0-9][0-9][0-9][0-9]\\)" xin)
       (concat (match-string-no-properties 3 xin) "-0" (match-string-no-properties 1 xin) "-" (match-string-no-properties 2 xin)))

      ;; USA convention of mm/dd/yy
      ((string-match "\\([0-9][0-9]\\)/\\([0-9][0-9]\\)/\\([0-9][0-9]\\)" xin)
       (concat (format-time-string "%C") (match-string-no-properties 3 xin) "-" (match-string-no-properties 1 xin) "-" (match-string-no-properties 2 xin)))
      ;; USA convention of m/dd/yy
      ((string-match "\\([0-9]\\)/\\([0-9][0-9]\\)/\\([0-9][0-9]\\)" xin)
       (concat (format-time-string "%C") (match-string-no-properties 3 xin) "-0" (match-string-no-properties 1 xin) "-" (match-string-no-properties 2 xin)))

      ;; some ISO 8601. yyyy-mm-ddThh:mm
      ((string-match "\\([0-9][0-9][0-9][0-9]\\)-\\([0-9][0-9]\\)-\\([0-9][0-9]\\)T[0-9][0-9]:[0-9][0-9]" xin)
       (concat (match-string-no-properties 1 xin) "-" (match-string-no-properties 2 xin) "-" (match-string-no-properties 3 xin)))
      ;; some ISO 8601. yyyy-mm-dd
      ((string-match "\\([0-9][0-9][0-9][0-9]\\)-\\([0-9][0-9]\\)-\\([0-9][0-9]\\)" xin)
       (concat (match-string-no-properties 1 xin) "-" (match-string-no-properties 2 xin) "-" (match-string-no-properties 3 xin)))
      ;; some ISO 8601. yyyy-mm
      ((string-match "\\([0-9][0-9][0-9][0-9]\\)-\\([0-9][0-9]\\)" xin)
       (concat (match-string-no-properties 1 xin) "-" (match-string-no-properties 2 xin)))

      ;; else
      (t
       (progn
         (setq xin (replace-regexp-in-string "January " "Jan. " xin))
         (setq xin (replace-regexp-in-string "February " "Feb. " xin))
         (setq xin (replace-regexp-in-string "March " "Mar. " xin))
         (setq xin (replace-regexp-in-string "April " "Apr. " xin))
         (setq xin (replace-regexp-in-string "May " "May. " xin))
         (setq xin (replace-regexp-in-string "June " "Jun. " xin))
         (setq xin (replace-regexp-in-string "July " "Jul. " xin))
         (setq xin (replace-regexp-in-string "August " "Aug. " xin))
         (setq xin (replace-regexp-in-string "September " "Sep. " xin))
         (setq xin (replace-regexp-in-string "October " "Oct. " xin))
         (setq xin (replace-regexp-in-string "November " "Nov. " xin))
         (setq xin (replace-regexp-in-string "December " "Dec. " xin))

         (setq xin (replace-regexp-in-string "\\([0-9]+\\)st" "\\1" xin))
         (setq xin (replace-regexp-in-string "\\([0-9]+\\)nd" "\\1" xin))
         (setq xin (replace-regexp-in-string "\\([0-9]+\\)rd" "\\1" xin))
         (setq xin (replace-regexp-in-string "\\([0-9]\\)th" "\\1" xin))

         (let (xdateList xyear xmonth xdate xyyyy xmm xdd)
           (setq xdateList (parse-time-string xin))
           (setq xyear (nth 5 xdateList))
           (setq xmonth (nth 4 xdateList))
           (setq xdate (nth 3 xdateList))

           (setq xyyyy (number-to-string xyear))
           (setq xmm (if xmonth (format "%02d" xmonth) ""))
           (setq xdd (if xdate (format "%02d" xdate) ""))
           (concat xyyyy "-" xmm "-" xdd))))))
    (delete-region xp1 xp2)
    (insert xin)))
(defun xah-fix-datetime-string (Datetime)
  "Return a new string of Datetime in yyyy-mm-dd format.
Other datetime info such as hours, minutes, time zone, are discarded. This function calls `xah-fix-datetime' to do work.

URL `http://xahlee.info/emacs/emacs/elisp_datetime_parser.html'
Version: 2020-09-08"
  (with-temp-buffer
    (insert Datetime)
    (xah-fix-datetime (point-min) (point-max))
    (buffer-substring-no-properties (point-min) (point-max))))

Datetime