【问题标题】:Check if any time in a list is between two timestamps检查列表中的任何时间是否在两个时间戳之间
【发布时间】:2018-11-30 14:57:25
【问题描述】:

我正在用 Python 实现一些计划任务。主程序 24/7 全天候运行,它以类似于 cron 的方式运行单个任务。我需要确定是否应该再次运行任务。

在这种情况下,我将获得任务最后一次运行的时间、当前时间(均作为 Unix 时间戳,通过 datetime.datetime.utcnow().timestamp() 获得,并可轻松转换为 datetime.datetime 对象),以及计划时间(例如,每小时每 15 分钟一次,如 0:151:15、...、23:15)。我想确定是否有任何预定时间在上次运行时间和当前时间之间,可能是一个布尔值。保证预定时间始终是“时间”(例如“2:00”),不涉及“日期”(例如任何一个月的第一天或任何星期一)。

示例数据:

import datetime

scheduled = [datetime.time(h, m) for h, m in [(0, 15), (6, 15), (12, 15), (18, 15)]]
previous = datetime.datetime(2018, 11, 30, 5)
truthy = datetime.datetime(2018, 11, 30, 7)
falsey = datetime.datetime(2018, 11, 30, 6)

# some_method() is what I want
assert some_method(scheduled, previous, falsey) is False
assert some_method(scheduled, previous, truthy) is True

这里有一些我还想介绍的特殊情况

scheduled = [datetime.time(1, 0)]  # 1:00 AM
previous = datetime.datetime(2018, 11, 30, 23)
truthy = datetime.datetime(2018, 12, 1, 2, 0)
falsey = datetime.datetime(2018, 12, 1, 0, 30)

assert some_method(scheduled, previous, falsey) is False
assert some_method(scheduled, previous, truthy) is True

上面的示例应该是True,因为预定时间“凌晨 1 点”介于“11 月 30 日晚上 11 点”和“12 月 1 日凌晨 2 点”之间。我无法直接比较时间,因为“凌晨 1 点”不是在同一天的“凌晨 2 点”和“晚上 11 点”之间,而是在不同日期的两个时间之间。

【问题讨论】:

  • @9769953 TypeError: '<' not supported between instances of 'datetime.datetime' and 'datetime.time'
  • 我不明白你想如何/通过什么逻辑来比较没有天的时间和有天的时间。
  • @timgeb 这是一些日常任务,我想确定是否应该再次运行它们,如第一段所述。检查时间是我面临的实际问题。
  • 我猜,对于列表中的每个时间戳,您应该使用要比较的两个日期的日期创建两个临时日期时间。如果其中任何一个在(previous < temp) & (temp < next) 中比较为真,那么这是一个有效的时间戳。
  • 那么如果any是正确的(True),那么整个数组本质上是正确的?

标签: python python-3.x datetime time


【解决方案1】:

一个简单的方法似乎是以下函数:

def some_method(scheduled, prev, next):
    date1 = prev.date()
    date2 = next.date()
    if (next - prev).total_seconds() > 86400:
       return True
    for s in scheduled:
        for date in {date1, date2}:
            temp = datetime.datetime(date.year, date.month, date.day, s.hour, s.minute, s.second)
            if prev < temp < next:
                return True
    return False

我会把它留给其他人来美化它,但这似乎行得通。

【讨论】:

  • 这在某种程度上似乎是一个好方法,但是当prev 是 11 月 30 日的 18:00 和 next 是 12 月 2 日的 6:00 时,这会在预定时间为 false 12:00(实际上,中间有 1 个实例,即 12 月 1 日的 12:00)。
  • @iBug 查看编辑。虽然我担心我可能仍然忽略了一些边缘情况。
【解决方案2】:

使用timedelta 和比较timetuples 怎么样?

def some_method(scheduled, prev, datetime_to_check):
    yesterday = datetime_to_check - datetime.timedelta(days=1)
    schedule = [(*yesterday.timetuple()[:3], s.hour, s.minute) for s in scheduled]
    schedule.extend((*datetime_to_check.timetuple()[:3], s.hour, s.minute) for s in scheduled)
    prev_tup = prev.timetuple()
    check_tup = datetime_to_check.timetuple()
    for scheduled_time in schedule:
        if prev_tup < scheduled_time < check_tup:
            return True
    return False

【讨论】:

    猜你喜欢
    • 2022-06-12
    • 2021-09-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-01-23
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多