【问题标题】:Unix timestamp to datetime in django with timezone带有时区的 django 中的 Unix 时间戳到日期时间
【发布时间】:2012-09-17 08:56:44
【问题描述】:

我有一个向我发送 unixtimestamp 的 javascript 日历。我在新加坡。我希望将此时间戳解释为新加坡时间戳,然后转换为 utc 以与 db 进行比较。

为了我自己,我无法弄清楚如何告诉 django 这个时间戳来自当前时区,新加坡。

当我打印时间戳时,它会增加 8 小时的时间(这意味着 django 认为我以 UTC 格式输入时间并将其本地化到新加坡语境)

在许多其他事情中,我尝试了: start=datetime.datetime.fromtimestamp(int(start_date)).replace(tzinfo=get_current_timezone())

start_date 是 1325376000(转换为 2012-01-01 00:00:00)

但是,当我打印此输出时,我得到 2012-01-01 08:00:00+06:55。当新加坡是 +08:00 时,我什至不知道 +06:55 来自哪里。我迷路了。

感谢您的帮助。

settings.py:

TIME_ZONE = 'Asia/Singapore'

USE_TZ = True

【问题讨论】:

  • posix 时间戳 1325376000'2012-01-01 00:00:00 UTC+0000''2012-01-01 08:00:00 SGT+0800'。为什么你认为在新加坡应该是00:00:00

标签: django datetime timezone pytz


【解决方案1】:

以上所有方法都是有效的,但不是“django like”。 这是一个简单的例子,一个 django 程序员是如何做到的:

from datetime import datetime

from django.utils.timezone import make_aware


# valid timestamp
value = 1531489250 
# you can pass the following obj to a DateTimeField, when your settings.USE_TZ == True
datetime_obj_with_tz = make_aware(datetime.fromtimestamp(value))

Django github timezone module 上查看更多实用程序以获取完整概览...

【讨论】:

  • 注意:此解决方案通过简单的本地时间引入了不必要的转换(如果未传递 tz 参数,则由 fromtimestamp() 返回)可能会以各种方式失败,例如,在 fromtimestamp() 具有无法访问 tz 数据库或不明确的当地时间。 Pass the tz argument explicitly as shown in my answer 并且在这种情况下您不需要调用make_aware()(将tz 传递给fromtimestamp() 会导致tz.fromutc() 调用比tz.localize() 调用的tz.localize() 更健壮)。
【解决方案2】:

假设你已经安装了pytz

from datetime import datetime
import pytz
local_tz = pytz.timezone("Asia/Singapore") 
utc_dt = datetime.utcfromtimestamp(timestamp).replace(tzinfo=pytz.utc)
local_dt = local_tz.normalize(utc_dt.astimezone(local_tz))

例如:

>>> from datetime import datetime
>>> import pytz
>>> local_tz = pytz.timezone("Asia/Singapore")
>>> utc_dt = datetime.utcfromtimestamp(1325376000).replace(tzinfo=pytz.utc)
>>> utc_dt
datetime.datetime(2012, 1, 1, 0, 0, tzinfo=<UTC>)
>>> local_dt = local_tz.normalize(utc_dt.astimezone(local_tz))
>>> local_dt
datetime.datetime(2012, 1, 1, 8, 0, tzinfo=<DstTzInfo 'Asia/Singapore' SGT+8:00:00 STD>)
>>> local_dt.replace(tzinfo=None)
datetime.datetime(2012, 1, 1, 8, 0)

【讨论】:

  • 我的答案的哪一部分取决于服务器的时区?此外,pytztz.localize(dt)tz.normalize(dt.replace(tzinfo=pytz.utc).astimezone(tz)) 相同(在这种情况下):pytz.sourceforge.net/#localized-times-and-date-arithmetic
  • FFUUU!啊,谢谢!你说得对。我是个白痴。我的答案已更新,以提供实际、正确的答案。
  • “假设你已经安装了pytz”太多了...... :(
  • 这是为什么呢? pytz 是一个简单的安装(或复制+粘贴,如果你愿意)。如果您只处理一个时区并且该时区没有夏令时并且UTC偏移量没有改变(也不会改变)您的应用程序将处理的时间范围,那么编写您自己的时区处理不会太难......但否则几乎可以保证它是不正确的。
  • 它运作良好,唯一的事情是我必须手动插入时区,我怎样才能使这个动态,以便它适用于来自世界各地的用户?我从哪里获得时区?
【解决方案3】:

将 pytz tzinfo 对象传递给fromtimestamp() 方法:

#!/usr/bin/env python
from datetime import datetime
import pytz # $ pip install pytz

tz = pytz.timezone("Asia/Singapore")
print(datetime.fromtimestamp(1325376000, tz))
# -> 2012-01-01 08:00:00+08:00

注意:结果对象是时区感知的:您可以将其与其他感知日期时间对象进行比较,即,您无需将其转换为 UTC 进行比较——您可以按原样使用它。

当新加坡是 +08:00 时,我什至不知道 +06:55 来自哪里。

由于.replace() 调用无效,您会看到+06:55get_current_timezone() 返回具有可变 utc 偏移量的 pytz.timezone("Asia/Singapore")(它可能在不同日期具有不同的 utc 偏移量)。当您调用 .replace() 时,会使用一些随机(取决于实现)tzinfo 对象。问题是.replace() 方法不允许pytz.timezone("Asia/Singapore") 为输入日期选择正确的tzinfo。

>>> list(tz._tzinfos.values())
[<DstTzInfo 'Asia/Singapore' MALT+7:00:00 STD>,
 <DstTzInfo 'Asia/Singapore' MALT+7:20:00 STD>,
 <DstTzInfo 'Asia/Singapore' JST+9:00:00 STD>,
 <DstTzInfo 'Asia/Singapore' SMT+6:55:00 STD>,
 <DstTzInfo 'Asia/Singapore' SGT+7:30:00 STD>,
 <DstTzInfo 'Asia/Singapore' MALT+7:30:00 STD>,
 <DstTzInfo 'Asia/Singapore' MALST+7:20:00 DST>,
 <DstTzInfo 'Asia/Singapore' LMT+6:55:00 STD>,
 <DstTzInfo 'Asia/Singapore' SGT+8:00:00 STD>]

即,+06:55+0800 在新加坡均有效(在不同日期)。这就是为什么您应该仅将 .replace() 用于具有恒定 utc 偏移量的时区,例如 utc 时区本身(偏移量为零,对于任何日期总是)。

fromtimestamp(,tz) 方法在内部调用tz.fromutc(),允许tz 为给定的UTC 时间选择正确的偏移量。

【讨论】:

    猜你喜欢
    • 2019-01-28
    • 2010-10-02
    • 2018-02-08
    • 2013-06-03
    • 1970-01-01
    • 1970-01-01
    • 2011-10-01
    • 1970-01-01
    • 2020-02-05
    相关资源
    最近更新 更多