UP | HOME

Emacs 中的时间计算

我每天都要面对 Emacs 好多个小时,也逐渐熟悉了它的许多特性,其中之一就是时间的计算。我们可以在 Python 中很方便地使用 time 模块进行日期计算,新的 C++11 中引入的 std::chrono 让时间计算也很简洁,当然,这些对于成熟的 Emacs Lisp 来说,更不是问题。

时间包含两部分内容,一个是时间长度——时、分、秒,一个是时间点——某年某月某日。如果要编写一段小程序,在每天可以自动显示儿子成长的时间,就需要把他出生的时间点作为参数,自动提取当前时间进行计算即可。如何实现呢?

Emacs Lisp 中的时间结构如下:

`(SEC-HIGH SEC-LOW MICROSEC PICOSEC)

后面的两个值可依次省略。浮点时间以秒为单位,计算公式如下:

Emacs Lisp 中有关时间操作的基本函数有:

Emacs 中进行时间计算的基本函数:

对于日历计算,在 Emacs 内部转换始终使用格里高利历,历法日期包含九项内容:

(SECONDS MINUTES HOUR DAY MONTH YEAR DOW DST ZONE)

其中:

上述内容除了 DAYMONTH 外,均从 0 开始计数。特别注意的是: 0 年表示 1 B.C., 因此 -37 则表示公元前 38 年。

除了公历外, Emacs 还支持犹太历、伊斯兰历、玛雅历等,当然包括中国的农历。

那么,计算成长时间的方法就很简单了,相应的 elisp 程序如下:

(setq lubo-birth-time (encode-time 0 50 8 12 12 2011)) ;; 出生日期
(setq the-date-time (current-time)) ;; 当前时间
(setq life-time (time-subtract the-date-time lubo-birth-time)) ;; 时间差
(format-seconds "%Y, %D, %H, %M%z" (float-time life-time))

其实,一天严格来说并不是 86400 秒,一年也不是严格的 365 天,因此,在计算日期差时,可以更精确一些。可以定义了一个函数,用于交互式显示成长日期:

;; 显示儿子的成长时间
(defun lubo-live-time ()
  "Display the live time of my son."
  (interactive)
  (let*
      ((birth-time (encode-time 0 50 8 12 12 2011))
       (live-time  (time-subtract (current-time) birth-time))
       (lt-secs    (float-time live-time)))
    (message
     (format "Lubo: %d days; %.2f months; %.2f weeks; -- %s"
             (floor (/ lt-secs 86400))
             (/ lt-secs 2628000) ;; 1 y = 12 m, 1 m ~= 30.4166667 d
             (/ lt-secs 604800)
             (format-seconds "%Y, %D, %H, %M%z" lt-secs)
             ))))

把上述代码添加到 .emacs 中,这样,随时想到儿子,我按一下 M-x lubo-live-time 命令,就可以很开心地看到一串字符了:

Lubo: 637 days; 20.95 months; 91.04 weeks; -- 1 year, 272 days, 7 hours, 33 minutes

版权所有 ©2015: 心蛛 | Date: [2013-09-09 一] | Generated by Emacs 24.4.1 (Org mode 8.3.2), Validate, 88x31.png

comments powered by Disqus