【问题标题】:using date-time in emacs spreadsheets在 emacs 电子表格中使用日期时间
【发布时间】:2014-12-03 06:50:29
【问题描述】:

我刚刚开始在 emacs 中使用 ses-mode,我计划将它与时间戳一起使用,但我无法以我可以使用的方式解析它们。

我在一周中的三天进行测量,因此我在一次测量和另一次测量之间的距离是 2 天或 3 天。我选择在 emacs 中使用 ses-mode,因为它可以在我的所有计算机上运行,​​包括手机。

我的电子表格包含日期戳、电导率、温度和加仑计数,随后的几行如下所示:

2014-10-03  2.95  33.4  4031070
2014-10-06  3.07  33.5  4086930
2014-10-08  2.97  33.6  4119590

我会再添加两列,第一列是读数之间的天数差异,第二列是“每天加仑”值。

我无法将字符串时间戳解析为我可以进行计算的格式,保留在一个简单的 emacs 电子表格 (SES) 中。

我试过date-to-time,但它总是返回相同的值(14445 17280)

parse-time-string 给了我一个 9 元组,我不能直接传递给 format-time-string

【问题讨论】:

  • SES 很酷,但我最近得出结论,在 Emacs 中为电子表格使用 org-mode 几乎可以肯定是当今更好的方法。如果您还没有研究过该选项,您可能会发现它很有趣/有用。

标签: emacs elisp spreadsheet emacs-ses


【解决方案1】:

函数encode-time 有帮助:

(let ((l (parse-time-string "2014-09-12")))
  (format-time-string "%d %m %Y" (encode-time 0 0 0 (nth 3 l) (nth 4 l) (nth 5 l))))

以下版本使用cl-flet,以避免在需要多次编码时代码加倍。如果您在其他函数中也需要编码,可以使用defun 而不是cl-flet

(eval-when (compile) (require 'cl)) ;; for cl-flet
(let ((A2 "2014-10-08")  ;; just for testing
      (A1 "2014-10-03")) ;; just for testing
  (cl-flet ((encode (str)
              (let ((l (parse-time-string str)))
                (encode-time 0 0 0 (nth 3 l) (nth 4 l) (nth 5 l)))))
    (let* ((t-prev (encode A1))
           (t-this (encode A2)))
      (/ (time-to-seconds (time-subtract t-this t-prev)) (* 24 60 60)))))

作为一个函数:

(eval-when (compile) (require 'cl)) ;; for cl-flet

(defun day-diff (date1 date2)
  "Calculate the difference of dates  in days between DATE1-STR and DATE2-STR."
  (interactive "sDate1:\nsDate2:")
  (cl-flet ((encode (str)
            (let ((l (parse-time-string str)))
              (encode-time 0 0 0 (nth 3 l) (nth 4 l) (nth 5 l)))))
    (setq date1 (encode date1)
      date2 (encode date2))
    (let ((ret (/ (time-to-seconds (time-subtract date1 date2)) (* 24 60 60))))
      (when (called-interactively-p 'any)
    (message "Day difference: %s" ret))
      ret)))

(put 'day-diff 'safe-function t)

使用calc 的替代方法是:

(require 'calc)
(defun day-diff (date1 date2)
  "Calculate the difference of dates  in days between DATE1-STR and DATE2-STR."
  (interactive "sDate1:\nsDate2:")
  (let ((ret (string-to-number (calc-eval (format "<%s>-<%s>" date1 date2)))))
    (when (called-interactively-p 'any)
      (message "Day difference: %s" ret))
    ret))

如果你省略了一些不错的功能,这几乎变成了一个简单的单元格公式:(string-to-number (calc-eval (format "&lt;%s&gt;-&lt;%s&gt;" A1 A2)))

如果您想将这些内容保存在电子表格中,您可以将 defun 放在表格单元格 A1 中。一个更简单的例子:

(progn (defun day-diff (date1 date2) (string-to-number (calc-eval (format "<%s>-<%s>" date1 date2)))) (put 'day 'safe-function t) "Actual header")

为了获得更方便的编辑可能性,您可以切换到 M-x lisp-mode。 在那里你找到

^L
(ses-cell A1 "Actual Header" (progn (defun day-diff (date1 date2) (string-to-number (calc-eval (format "<%s>-<%s>" date1 date2)))) (put 'day 'safe-function t) "Actual header") nil nil)

您可以编辑。但不要插入换行符! ses 用该文件中的行号标识单元格位置!


另一个不错的选择是将函数的定义放入文件局部变量列表中。 通过 M-x lisp-interaction-mode 切换到 lisp 交互模式。 转到文件的末尾。在那里你可以找到这些行:

;; Local Variables:
;; mode: ses
;; End:

将您的函数定义作为eval 添加到此列表中:

;; Local Variables:
;; mode: ses
;; eval:
;; (progn
;;   (defun day-diff (date1 date2)
;;     (string-to-number (calc-eval (format "<%s>-<%s>" date1 date2))))
;;   (put 'day-diff 'safe-function t))
;; End:

您可以添加不带注释字符;progn。在这种情况下,甚至缩进也有效。之后您可以致电comment-region 获取progn

您可以保存文件并运行 M-x normal-mode。之后定义函数,您可以在电子表格中使用它。

【讨论】:

  • 它确实有帮助,但我用它 (let* ((l-prev (parse-time-string A1)) (l-this (parse-time-string A2)) (t-prev (encode-time 0 0 0 (nth 3 l-prev) (nth 4 l-prev) (nth 5 l-prev))) (t-this (encode-time 0 0 0 (nth 3 l-this) (nth 4 l-this) (nth 5 l-this)))) (/ (time-to-seconds (time-subtract t-this t-prev)) (* 24 60 60))) 做的东西看起来很糟糕!
  • 您的编辑看起来已经更好了,但接下来是ses 部分:我如何在电子表格中定义函数,所以我不需要在每个单元格中重复它?
  • (或者唯一的地方是在我的 .emacs 文件中?)
猜你喜欢
  • 1970-01-01
  • 2020-11-21
  • 1970-01-01
  • 2021-12-04
  • 2014-02-27
  • 1970-01-01
  • 2015-06-10
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多