【问题标题】:Compare times with python用python比较时间
【发布时间】:2015-07-23 19:06:45
【问题描述】:

我的文件中有日期标记的数据,例如“2015.05.05-11:46”,我想读取这些行,然后查看它们是否满足某些条件。例如,作为函数的输入,我可能有

get_times('hour', -3.0, -1.2)

有函数定义:

get_times(unit, start_time, end_time):

这意味着我想返回从过去 -3.0 小时到过去 -1.2 小时的所有字符串。我可以通过now = datetime.datetime.now() 获取当前时间。假设我在 time1 = '2015.05.05-11:46' 中阅读,我如何将其与 now 进行比较,并从现在开始找出它是否在 start_timeend_time units 内?

【问题讨论】:

    标签: python datetime


    【解决方案1】:

    您可以正常使用<> 运算符。
    但要让它工作,你必须让所有数据都是datetime 类型。

    例如:

    time_str = "2015.05.05-11:46"
    reference_time = datetime.datetime.strptime(time_str, "%Y.%m.%d-%H:%M")
    
    start_time = reference_time - datetime.timedelta(hours=3)
    end_time = reference_time - datetime.timedelta(hours=1.2)
    now = datetime.datetime.now()
    
    if end_time <= now <= start_time:
        print 'It is in between'
    

    您还可以使用字典将参数传递给timedelta 函数:

    >>> a = datetime.timedelta(hours=3, minutes=10)
    >>> args = {'hours': 3, 'minutes': 10}
    >>> b = datetime.timedelta(**args)
    >>> a == b
    True
    

    【讨论】:

    • 不错。我可以放入测试用例以查找unit,但是有没有办法将hours 表示为字符串,还是必须硬编码为hours
    • 在哪里?在timedelta 参数中?那是关键字,必须这样写
    • @Laurbert515 datetime.timedelta(**{unit: start_time}) - 虽然您需要确保unit 的值与预期的参数名称匹配,所以"hours" 而不是"hour"
    【解决方案2】:

    使用 datetime.strptime 转换您的字符串 '2015.05.05-11:46'

    then = datetime.datetime.strptime('2015.05.05-11:46', "%Y.%m.%d-%H:%M")
    
    now = datetime.datetime.now()
    

    然后使用 datetime.timedelta 来比较时间。

    tdelta = now - then
    
    if datetime.timedelta(hours=1.2) < tdelta < datetime.timedelta(hours=3.0):
        print "In range"
    

    在编写函数时,您可能希望坚持使用 datetime.timedelta 中的单位,除非您有充分的理由不这样做。

    class datetime.timedelta([days[, seconds[, microseconds[, milliseconds[, minutes[, hours[, weeks]]]]]]])
    

    所以,'days', 'seconds', 'microseconds', 'milliseconds', 'minutes', 'hours', 'weeks'

    【讨论】:

    • 然后使用 datetime.timedelta 算出 datetime 格式的开始时间和结束时间,以便进行比较。 pymotw.com/2/datetime
    【解决方案3】:

    根据您的情况需要做几件事。首先,您需要将日期时间字符串转换为日期时间对象以便于比较。我们通过strptime

    input_datetime = datetime.datetime.strptime(i, '%Y.%m.%d-%H:%M')
    

    我们还需要根据您的输入返回开始和结束时间的函数。如果您可以稍作修改并使用hours 而不是hour,我们可以在不设置大if/elif 块的情况下做到这一点。

    def get_times(unit, start_time, end_time):
        now = datetime.datetime.now()
        start_kwarg = {unit: start_time}
        end_kwarg = {unit: end_time}
        time_start = now + datetime.timedelta(**start_kwarg)
        time_end = now + datetime.timedelta(**end_kwarg)
        return time_start, time_end
    

    这将获取您的unit 并创建一个字典,该字典作为关键字参数传递给timedelta。由于hours 是它接受的参数之一,我们可以使用关键字而不是将hour 映射到hours。然后我们返回开始和结束时间。

    最后,我们只需要比较输入时间在开始和结束之间:

    start < input_datetime < end
    

    最终的脚本可能如下所示:

    import datetime
    
    def get_times(unit, start_time, end_time):
        now = datetime.datetime.now()
        start_kwarg = {unit: start_time}
        end_kwarg = {unit: end_time}
        time_start = now + datetime.timedelta(**start_kwarg)
        time_end = now + datetime.timedelta(**end_kwarg)
        return time_start, time_end
    
    start, end = get_times('hours', -3.0, -1.2)
    
    input_times = [
        '2015.05.12-11:46',
        '2014.05.12-11:46',
        '2016.05.12-11:46',
        '2015.04.12-11:46',
        '2015.05.05-11:46'
        ]
    
    for i in input_times:
        input_datetime = datetime.datetime.strptime(i, '%Y.%m.%d-%H:%M')
        print "{} => {}".format(input_datetime, start < input_datetime < end)
    

    输出将如下所示(如果在 2015 年 5 月 12 日下午 12:46 运行):

    2015-05-12 11:46:00 => True
    2014-05-12 11:46:00 => False
    2016-05-12 11:46:00 => False
    2015-04-12 11:46:00 => False
    2015-05-05 11:46:00 => False
    

    【讨论】:

    【解决方案4】:

    希望这是您正在寻找的:

    import datetime
    import time
    
    
    def get_times(unit, start_time, end_time):
        now = datetime.datetime.now().timetuple()
        matched_dates = []
        for date in your_file:
            converted_date = time.strptime(date,"%Y.%m.%d-%H:%M")
            if converted_date.tm_hour > (now.tm_hour + start_time) and converted_date.tm_hour < (now.tm_hour + end_time):
                matched_dates.append(date)
        return matched_dates
    

    【讨论】:

      【解决方案5】:

      要比较文件中的时间,您应该将其转换为 UTC 时间(POSIX 时间戳)或可识别的日期时间对象(本地时间 + UTC 偏移量)。

      start_time, end_time = get_times('hour', -3, -1.2)
      if start_time <= utc_time < end_time:
         # utc_time is in between
      

      您应该使用start_time &lt;= naive_local_time &lt; end_timeConvert input time to UTC or create an aware datetime objects instead.

      如果您的输入文件中的当地时间是连续的,那么您可以在必要时使用该事实来消除时间戳的歧义,请参阅Parsing of Ordered Timestamps in Local Time (to UTC) While Observing Daylight Saving Time

      更多使用time.mktime()pytz、感知日期时间对象的解释和解决方案在:Find if 24 hrs have passed between datetimes - Python

      为什么你不应该使用datetime.now()

      datetime.now() 返回本地时间,因为简单的日期时间对象可能不明确,例如在 DST 转换期间:

      >>> from datetime import datetime
      >>> import pytz
      >>> tz = pytz.timezone('America/New_York')
      >>> tz.localize(datetime(2015,11,1,1,30), is_dst=None)
      Traceback (most recent call last):
        File "<stdin>", line 1, in <module>
        File "/usr/lib/python2.7/dist-packages/pytz/tzinfo.py", line 349, in localize
          raise AmbiguousTimeError(dt)
      pytz.exceptions.AmbiguousTimeError: 2015-11-01 01:30:00
      >>> tz.localize(datetime(2015,11,1,1,30), is_dst=True).astimezone(pytz.utc)
      datetime.datetime(2015, 11, 1, 5, 30, tzinfo=<UTC>)
      >>> tz.localize(datetime(2015,11,1,1,30), is_dst=False).astimezone(pytz.utc)
      datetime.datetime(2015, 11, 1, 6, 30, tzinfo=<UTC>)
      

      注意:如果您删除 UTC 偏移量,则相同的本地时间可能对应不同的 UTC 时间。 datetime.utcnow() 是明确的(除了可能闰秒期间,例如2015-06-30T23:59:60Z)。

      如何实现get_times('hour', -3.0, -1.2)

      使用 UTC 时间或感知日期时间对象:

      #!/usr/bin/env python
      from datetime import datetime, timedelta
      
      def get_times(unit, relative_start, relative_end):
          relative_start, relative_end = [timedelta(**{unit+'s': v})
                                          for v in [relative_start, relative_end]]
          now = datetime.utcnow() # or datetime.now(timezone.utc).astimezone()
          return now + relative_start, now + relative_end
      

      【讨论】:

        猜你喜欢
        • 2019-05-20
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-05-18
        • 2015-06-12
        • 2013-01-12
        相关资源
        最近更新 更多