如何方便地把时间戳 22-3-8 09:59 变成 org-mode 可以识别的格式?

就是微博显示的时间戳,直接复制时格式与 org-mode 有差别。

emacs/org-mode 有没有现成的函数实现类似的功能?

写了一个勉强能用的:

(defun qi/convert-weibo-timestamp-to-org-style ()
  "Convert timestamp from Weibo to org timestamp style.

For example,
from   `22-3-12 14:22' to `[2022-03-12 14:22]',
from `2022-3-12 14:22' to `[2022-03-12 14:22]'."

  (interactive)
  ;; TODO: better way to get boundary
  (unless (use-region-p) (user-error "No region marked."))

  (let ((time-str (string-trim (buffer-substring (region-beginning) (region-end)))))
    (unless (string-match-p "[0-9]\\{2,4\\}-[0-9]\\{1,2\\}-[0-9]\\{1,2\\} [0-9]\\{2\\}:[0-9]\\{2\\}"
                            time-str)
      (user-error "Bad format: `%s'" time-str))
    (let* ((date-time      (split-string time-str))
           (date           (car date-time))
           (time           (cadr date-time))
           (year-month-day (split-string date "-"))
           (year           (string-to-number (car year-month-day)))
           (century        2000)        ; TODO: better way to get century
           (year           (if (< year 100) (+ century year) year))
           (month          (string-to-number (nth 1 year-month-day)))
           (day            (string-to-number (nth 2 year-month-day))))
      (kill-region (region-beginning) (region-end))
      (insert (format "[%d-%02d-%02d %s]" year month day time)))))
1 个赞

你这个还要先选中,感觉太麻烦了,直接用replace-regexp 不好吗?

既然都上正则表达式了,为何不尽其用?

用分组直接把值抠出来:

(let ((s "22-3-12 14:22")
      (r (concat
          "\\([0-9]\\{2\\}\\([0-9]\\{2\\}\\)?\\)-\\([0-9]\\([0-9]\\)?\\)-\\([0-9]\\([0-9]\\)?\\)"
          " \\([0-9]\\{2\\}:[0-9]\\{2\\}\\)")))
  (if (string-match r s)
      (concat
       "["
       (concat (unless (match-string 2 s) "20") (match-string 1 s)) "-"
       (concat (unless (match-string 4 s)  "0") (match-string 3 s)) "-"
       (concat (unless (match-string 6 s)  "0") (match-string 5 s)) " "
       (match-string 7 s)
       "]")
    (user-error "Bad format: %s" s)))
;; => "[2022-03-12 14:22]"

或更严谨一些,再用 parse-time-string 过一遍:

(let ((s "22-3-12 14:22")
      (r (concat
          "\\([0-9]\\{2\\}\\([0-9]\\{2\\}\\)?\\)-\\([0-9]\\([0-9]\\)?\\)-\\([0-9]\\([0-9]\\)?\\)"
          " \\([0-9]\\{2\\}:[0-9]\\{2\\}\\)")))
  (if (string-match r s)
      (format-time-string
       "[%Y-%m-%d %H:%M]"
       (encode-time
        (parse-time-string
         (concat
          (concat (unless (match-string 2 s) "20") (match-string 1 s)) "-"
          (concat (unless (match-string 4 s)  "0") (match-string 3 s)) "-"
          (concat (unless (match-string 6 s)  "0") (match-string 5 s)) "T"
          (match-string 7 s) ":00" "+08:00"))))
    (user-error "Bad format: %s" s)))
;; => "[2022-03-12 14:22]"

想过,但是我对 emacs 的正则 api 不熟悉。