如何分割重叠的日期时间区间(Org Mode 计时)?

2 投票
1 回答
1126 浏览
提问于 2025-04-15 14:25

我有两个Org文件/子树里的相关任务,其中一些记录的时间是重叠的。这些任务包括一个手动的工作日志和一个生成的git提交日志,具体内容如下。

其中一个子树的CLOCK:条目需要调整,以去掉重叠的时间。另一个子树被认为是完整的,它的CLOCK:条目不需要调整。

编辑:这个问题是关于计算新的时间区间,以消除任何重叠。任何建议都不需要解析Org模式的文件格式。Python的datetime.datetime算法很有用,Emacs Lisp也可以,使用Org模式函数或不使用都可以。

在Python(我比较熟悉)或Emacs Lisp(Org函数可能会有帮助)中,我想要:

  1. 找出时间重叠发生的地方。file1.org会是可变的,而file2.org的时间区间应该被视为固定的/正确的。

  2. 计算file1.org中CLOCK:行的新时间区间,以消除与file2.org CLOCK:行的重叠。

  3. 将结果的新CLOCK:行写出,或者至少写出相关的日期时间。

Python的便利函数tsparse可以将Org模式的时间戳转换为Python的datetime.datetime对象:

>>> from datetime import datetime, timedelta
>>> def tsparse(timestring): return datetime.strptime(timestring,'%Y-%m-%d %a %H:%M')
>>> tsparse('2008-10-15 Wed 00:45')
datetime.datetime(2008, 10, 15, 0, 45)

下面可以找到测试用例。感谢任何关于Python或Emacs Lisp的算法或实现建议。

Jeff


file1.org调整前

* Manually Edited Worklog

** DONE Onsite
   CLOSED: [2009-09-09 Wed 15:00]
   :LOGBOOK:
   CLOCK: [2009-09-09 Wed 07:00]--[2009-09-09 Wed 15:00] =>  8:00
   :END:

** DONE Onsite
   CLOSED: [2009-09-10 Wed 15:00]
   :LOGBOOK:
   CLOCK: [2009-09-10 Thu 08:00]--[2009-09-10 Thu 15:00] =>  7:00
   :END:

file2.org

* Generated commit log

** DONE Commit 1                          :partial:overlap:leading:contained:
   CLOSED: [2009-09-09 Tue 10:18]
   :LOGBOOK:
   CLOCK: [2009-09-09 Wed 06:40]--[2009-09-09 Wed 07:18] =>  0:38
   CLOCK: [2009-09-09 Wed 10:12]--[2009-09-09 Wed 10:18] =>  0:06
   :END:

** DONE Commit 2                               :contained:overlap:contiguous:
   CLOSED: [2009-09-09 Wed 10:20]
   :LOGBOOK:
   CLOCK: [2009-09-09 Wed 10:18]--[2009-09-09 Wed 10:20] =>  0:02
   :END:

** DONE Commit 4                                          :contained:overlap:
   CLOSED: [2009-09-10 Wed 09:53]
   :LOGBOOK:
   CLOCK: [2009-09-10 Wed 09:49]--[2009-09-10 Wed 09:53] =>  0:04
   :END:

** DONE Commit 5                                   :partial:overlap:trailing:
   CLOSED: [2009-09-10 Wed 15:12]
   :LOGBOOK:
   CLOCK: [2009-09-10 Wed 14:45]--[2009-09-10 Wed 15:12] =>  0:27
   :END:

** DONE Commit 6                                    :partial:overlap:leading:
   CLOSED: [2009-09-11 Fri 08:05]
   :LOGBOOK:
   CLOCK: [2009-09-11 Fri 07:50]--[2009-09-11 Fri 08:05] =>  0:15
   :END:

** DONE Commit 7                                                 :nonoverlap:
   CLOSED: [2009-09-11 Fri 15:55]
   :LOGBOOK:
   CLOCK: [2009-09-11 Fri 15:25]--[2009-09-11 Fri 15:55] =>  0:30
   :END:

file1.org调整后

* Manually Edited Worklog

** DONE Onsite
   CLOSED: [2009-09-09 Wed 15:00]
   :LOGBOOK:
   CLOCK: [2009-09-09 Wed 10:20]--[2009-09-09 Wed 14:45] =>  4:25
   CLOCK: [2009-09-09 Wed 07:18]--[2009-09-09 Wed 10:12] =>  2:54
   :END:

** DONE Onsite
   CLOSED: [2009-09-10 Wed 15:00]
   :LOGBOOK:
   CLOCK: [2009-09-10 Thu 08:05]--[2009-09-10 Thu 15:00] =>  6:55
   :END:

1 个回答

2

你是想要帮助解析文件格式吗?还是只是想弄清楚时间重叠的问题?

datetime对象在Python中是可以比较的,所以你可以这样做:

>>> (a,b) = (datetime(2009, 9, 15, 8, 30), datetime(2009, 9, 15, 8, 45))
>>> (c,d) = (datetime(2009, 9, 15, 8, 40), datetime(2009, 9, 15, 8, 50))
>>> a <= b
True
>>> if c <= b <= d:
...     print "overlap, merge these two ranges"
... else:
...     print "separate ranges, leave them alone"
...
overlap, merge these two ranges

如果第一个时间段的结束时间(b)在第二个时间段(c和d)内,那么这两个时间段就重叠了,你可以把这两个时间段合并成一个新的时间段(a,d)。

因为你的数据量看起来比较小,所以你可以直接比较所有的时间段(N的平方),这样就能得到一个可以接受的结果。

撰写回答