【问题标题】:python - datetime with timezone to epochpython - 带有时区的日期时间到纪元
【发布时间】:2012-08-23 08:10:32
【问题描述】:

在下面的代码中,我正在计算现在纪元和当前纪元的开始。

import time
import pytz
from datetime import datetime

tz1 = pytz.timezone('CST6CDT')
utc = pytz.timezone('UTC')
now = pytz.UTC.localize(datetime.utcnow())
now_tz = now.astimezone(tz1)
print now_tz
print now_tz.strftime('%s')

begin_day = now_tz.replace(hour=0, minute=0, second=0)
print begin_day

print begin_day.strftime('%s')

打印语句:

2012-08-28 13:52:21.595718-05:00
1346187141
2012-08-28 00:00:00.595718-05:00
1346137200

使用 CDT 时区将纪元转换为时间戳: 1346187141 - 2012 年 8 月 28 日 15:52:21, 1346137200 - 2012年8月28日02:00:00

我希望第二个纪元是一天的开始,但现在是凌晨 2 点。转换为纪元时,它看起来仍在使用本地时区 PST。

我做错了什么?或者这可以用不同的方式完成吗?

谢谢!

【问题讨论】:

    标签: python datetime timezone epoch


    【解决方案1】:

    将带有时区的日期时间转换为纪元(POSIX 时间戳):

    from datetime import datetime
    import pytz
    
    tz = pytz.timezone('CST6CDT')
    
    # a datetime with timezone
    dt_with_tz = tz.localize(datetime(2012, 8, 28, 19, 33, 50), is_dst=None)
    
    # get timestamp
    ts = (dt_with_tz - datetime(1970, 1, 1, tzinfo=pytz.utc)).total_seconds()
    # -> 1346200430.0
    

    这是在 Python 3 中为时区感知 datetime 对象实现 datetime.timestamp 方法的方式。

    要获得“现在的时代”:

    from datetime import datetime
    
    now_epoch = (datetime.utcnow() - datetime(1970, 1, 1)).total_seconds()
    

    或者(假设 time 使用 POSIX 纪元):

    import time
    
    now_epoch = time.time()
    

    获取“当前日期的开始”更复杂,因为不同时区的当前日期可能不同:

    from datetime import datetime, time
    import pytz
    
    tz = pytz.timezone('CST6CDT')
    
    # get current date in given timezone
    today = datetime.now(tz).date()
    # -> datetime.date(2013, 6, 22)
    
    # get beginning of current day in given timezone as a datetime with timezone
    midnight = tz.localize(datetime.combine(today, time(0, 0)), is_dst=None)
    # -> datetime.datetime(2013, 6, 22, 0, 0, tzinfo=<DstTzInfo 'CST6CDT'...>)
    
    # get timestamp
    ts = (midnight - datetime(1970, 1, 1, tzinfo=pytz.utc)).total_seconds()
    # -> 1371877200.0 
    

    How do I get the UTC time of “midnight” for a given timezone?

    假设UTC日期获得“当前时代的开始”:

    from datetime import datetime, date
    
    # get current date in UTC
    utc_date = datetime.utcnow().date()
    # -> datetime.date(2013, 6, 23)
    
    # get timestamp
    ts = (utc_date - date(1970, 1, 1)).days * 86400
    # -> 1371945600
    

    Converting datetime.date/datetime.datetime to UTC timestamp in Python

    【讨论】:

      【解决方案2】:

      注意:我的回答完全错误。(我想删除它,但在删除接受标志之前无法这样做。)

      请参阅J.F.Sebastian's answer

      这里的代码展示了now_tz 的值,我们的两种方法会产生不同的结果。

      import calendar
      import pytz
      import datetime as dt
      
      tz1 = pytz.timezone('US/Eastern')
      utc = pytz.timezone('UTC')
      now = utc.localize(dt.datetime(2002, 10, 28), is_dst=None)
      now_tz = now.astimezone(tz1)
      now_epoch = calendar.timegm(now_tz.utctimetuple())
      begin_day = tz1.normalize(now_tz.replace(hour=0, minute=0, second=0))
      
      midnight = tz1.localize(dt.datetime.combine(now_tz, dt.time(0, 0)), is_dst=None)
      if begin_day != midnight:
          print(begin_day)
          # 2002-10-27 01:00:00-04:00  # my result -- is not midnight
          print(midnight)
          # 2002-10-27 00:00:00-04:00  # J.F.Sebastian's result is correct
      

      (原始答案已编辑)

      【讨论】:

      • 救了我的命!正是我需要的。
      • 使用America/Chicago 而不是CST6CST。 tzdb 中只有少数 POSIX 时区,它们只是为了向后兼容支持。
      • 注意:如果午夜与 tz1 时区中的 now_tz 有不同的 UTC 偏移量,now_tz.replace(hour=0,...) 可以返回未规范化的日期时间对象。 tz1.normalize() 可能需要调用,以便 tzinfo 反映正确的时区。如果午夜前后 DST 更改(巴西),则结果未定义。 tz.localize(is_dst=None) raises an exception in this case 而不是默默地返回错误答案(尽管有时可能适合抑制异常)。
      • @J.F.Sebastian:感谢您的评论。我无法reproduce the problem。请举个例子好吗?
      • @unutbu:简单。有两个问题:1.unnormalized datetime object due to .replace() 2.午夜(当地时间)可能不明确甚至不存在(例如,由于 DST):pytz.timezone('Brazil/East').localize(datetime(2014, 10, 19), is_dst=None)
      【解决方案3】:

      最新版本的simple-date(版本0.2 on pypi)将为您管理详细信息:

      >>> from simpledate import *
      >>> now_utc = SimpleDate(tz='UTC')
      >>> now_tz = now_utc.convert(tz='CST6CDT')
      >>> begin_day = now_tz.replace(hour=0, minute=0, second=0, microsecond=0)
      >>> now_utc.timestamp
      1371950295.777453
      >>> now_tz.timestamp
      1371950295.777453
      >>> begin_day.timestamp
      1371877200.0
      

      我们可以向后检查时间戳(尽管很明显,切换时区并没有改变纪元,而移动到一天的开始却改变了):

      >>> SimpleDate(1371877200.0, tz='CST6CDT')
      SimpleDate('2013-06-22 00:00:00.000000 CDT', tz='CST6CDT')
      >>> SimpleDate(1371877200.0, tz='UTC')
      SimpleDate('2013-06-22 05:00:00.000000 UTC')
      

      【讨论】:

      • .replace() 调用失败(无限递归)例如,SimpleDate('2014-08-20 03:29:35.203607 UTC').replace(hour=0, minute=0, second=0, microsecond=0) (simple-date==0.4.8)。
      猜你喜欢
      • 2019-02-04
      • 2019-08-22
      • 2023-03-27
      • 2017-06-22
      • 1970-01-01
      • 1970-01-01
      • 2016-03-29
      • 1970-01-01
      • 2016-11-02
      相关资源
      最近更新 更多