使用时区打印正确的时间,Python

发布于 2024-08-17 22:33:13 字数 4477 浏览 6 评论 0原文

扩展

好吧,我们今天过得不太好今天。

当您将正确的 tzinfo 对象附加到日期时间实例,然后对它进行 strftime() 时,它仍然以 UTC 格式显示,似乎忽略了我附加到它的美丽的 tzinfo 对象。

    # python 2.5.4
    now = datetime.now()
    print now.strftime( "%a %b %d %X" ) # %X is "locale's appropriate time rep"

    pst = now.replace( tzinfo=Pacific )
    print pst.strftime( "%a %b %d %X" )

我们得到:

Mon Jan 18 17:30:16
Mon Jan 18 17:30:16

我发现如果我添加 %z,我可以添加它应该计算出的差异:

Mon Jan 18 17:32:38 
Mon Jan 18 17:32:38 -0800

它只是在 -8 上加上,就好像在说,“你自己做,foo。”

但我希望 strftime() 简单地给我一个带有预先计算的本地时间的字符串。

当我 strftime() 时,如何让 strftime() 为我做小时减法数学?

我正在使用的完整代码如下。

from datetime import tzinfo, timedelta, datetime

ZERO = timedelta(0)
HOUR = timedelta(hours=1)

# A UTC class.

class UTC(tzinfo):
  """UTC"""
  def utcoffset(self, dt):
    return ZERO
  def tzname(self, dt):
    return "UTC"
  def dst(self, dt):
    return ZERO

utc = UTC()

# A class building tzinfo objects for fixed-offset time zones.
# Note that FixedOffset(0, "UTC") is a different way to build a
# UTC tzinfo object.
class FixedOffset(tzinfo):
  """Fixed offset in minutes east from UTC."""

  def __init__(self, offset, name):
    self.__offset = timedelta(minutes = offset)
    self.__name = name

  def utcoffset(self, dt):
    return self.__offset

  def tzname(self, dt):
    return self.__name

  def dst(self, dt):
    return ZERO

# A class capturing the platform's idea of local time.

import time as _time

STDOFFSET = timedelta(seconds = -_time.timezone)
if _time.daylight:
  DSTOFFSET = timedelta(seconds = -_time.altzone)
else:
  DSTOFFSET = STDOFFSET

DSTDIFF = DSTOFFSET - STDOFFSET

class LocalTimezone(tzinfo):
  def utcoffset(self, dt):
    if self._isdst(dt):
      return DSTOFFSET
    else:
      return STDOFFSET

  def dst(self, dt):
    if self._isdst(dt):
      return DSTDIFF
    else:
      return ZERO

  def tzname(self, dt):
    return _time.tzname[self._isdst(dt)]

  def _isdst(self, dt):
    tt = (dt.year, dt.month, dt.day,
          dt.hour, dt.minute, dt.second,
          dt.weekday(), 0, -1)
    stamp = _time.mktime(tt)
    tt = _time.localtime(stamp)
    return tt.tm_isdst > 0

Local = LocalTimezone()


# A complete implementation of current DST rules for major US time zones.

def first_sunday_on_or_after(dt):
  days_to_go = 6 - dt.weekday()
  if days_to_go:
    dt += timedelta(days_to_go)
  return dt

# In the US, DST starts at 2am (standard time) on the first Sunday in April.
DSTSTART = datetime(1, 4, 1, 2)
# and ends at 2am (DST time; 1am standard time) on the last Sunday of Oct.
# which is the first Sunday on or after Oct 25.
DSTEND = datetime(1, 10, 25, 1)

class USTimeZone(tzinfo):
  def __init__(self, hours, reprname, stdname, dstname):
    self.stdoffset = timedelta(hours=hours)
    self.reprname = reprname
    self.stdname = stdname
    self.dstname = dstname

  def __repr__(self):
    return self.reprname

  def tzname(self, dt):
    if self.dst(dt):
      return self.dstname
    else:
      return self.stdname

  def utcoffset(self, dt):
    return self.stdoffset + self.dst(dt)

  def dst(self, dt):
    if dt is None or dt.tzinfo is None:
      # An exception may be sensible here, in one or both cases.
      # It depends on how you want to treat them.  The default
      # fromutc() implementation (called by the default astimezone()
      # implementation) passes a datetime with dt.tzinfo is self.
      return ZERO
    assert dt.tzinfo is self

    # Find first Sunday in April & the last in October.
    start = first_sunday_on_or_after(DSTSTART.replace(year=dt.year))
    end = first_sunday_on_or_after(DSTEND.replace(year=dt.year))

    # Can't compare naive to aware objects, so strip the timezone from
    # dt first.
    if start <= dt.replace(tzinfo=None) < end:
      return HOUR
    else:
      return ZERO

Eastern  = USTimeZone(-5, "Eastern",  "EST", "EDT")
#Central  = USTimeZone(-6, "Central",  "CST", "CDT")
#Mountain = USTimeZone(-7, "Mountain", "MST", "MDT")
Pacific = USTimeZone(-8, "Pacific",  "PST", "PDT")

now = datetime.now()
print now.strftime( "%a %b %d %X %z" )

pst = now.replace( tzinfo=Pacific )
print pst.strftime( "%a %b %d %X %z" )

Extends

Ok, we are not having a good day today.

When you attach the correct tzinfo object to a datetime instance, and then you strftime() it, it STILL comes out in UTC, seemingly ignoring the beautiful tzinfo object I attached to it.

    # python 2.5.4
    now = datetime.now()
    print now.strftime( "%a %b %d %X" ) # %X is "locale's appropriate time rep"

    pst = now.replace( tzinfo=Pacific )
    print pst.strftime( "%a %b %d %X" )

We get:

Mon Jan 18 17:30:16
Mon Jan 18 17:30:16

I found if I add %z, I can add the difference its supposed to have computed:

Mon Jan 18 17:32:38 
Mon Jan 18 17:32:38 -0800

It just tacks on the -8 there, as if to say, "you do it yourself, foo."

But I want strftime() to simply give me a string WITH PRECOMPUTED LOCAL TIME.

How can I get strftime() to do the hour subtraction math for me when I strftime() it?

The full code I'm using is below.

from datetime import tzinfo, timedelta, datetime

ZERO = timedelta(0)
HOUR = timedelta(hours=1)

# A UTC class.

class UTC(tzinfo):
  """UTC"""
  def utcoffset(self, dt):
    return ZERO
  def tzname(self, dt):
    return "UTC"
  def dst(self, dt):
    return ZERO

utc = UTC()

# A class building tzinfo objects for fixed-offset time zones.
# Note that FixedOffset(0, "UTC") is a different way to build a
# UTC tzinfo object.
class FixedOffset(tzinfo):
  """Fixed offset in minutes east from UTC."""

  def __init__(self, offset, name):
    self.__offset = timedelta(minutes = offset)
    self.__name = name

  def utcoffset(self, dt):
    return self.__offset

  def tzname(self, dt):
    return self.__name

  def dst(self, dt):
    return ZERO

# A class capturing the platform's idea of local time.

import time as _time

STDOFFSET = timedelta(seconds = -_time.timezone)
if _time.daylight:
  DSTOFFSET = timedelta(seconds = -_time.altzone)
else:
  DSTOFFSET = STDOFFSET

DSTDIFF = DSTOFFSET - STDOFFSET

class LocalTimezone(tzinfo):
  def utcoffset(self, dt):
    if self._isdst(dt):
      return DSTOFFSET
    else:
      return STDOFFSET

  def dst(self, dt):
    if self._isdst(dt):
      return DSTDIFF
    else:
      return ZERO

  def tzname(self, dt):
    return _time.tzname[self._isdst(dt)]

  def _isdst(self, dt):
    tt = (dt.year, dt.month, dt.day,
          dt.hour, dt.minute, dt.second,
          dt.weekday(), 0, -1)
    stamp = _time.mktime(tt)
    tt = _time.localtime(stamp)
    return tt.tm_isdst > 0

Local = LocalTimezone()


# A complete implementation of current DST rules for major US time zones.

def first_sunday_on_or_after(dt):
  days_to_go = 6 - dt.weekday()
  if days_to_go:
    dt += timedelta(days_to_go)
  return dt

# In the US, DST starts at 2am (standard time) on the first Sunday in April.
DSTSTART = datetime(1, 4, 1, 2)
# and ends at 2am (DST time; 1am standard time) on the last Sunday of Oct.
# which is the first Sunday on or after Oct 25.
DSTEND = datetime(1, 10, 25, 1)

class USTimeZone(tzinfo):
  def __init__(self, hours, reprname, stdname, dstname):
    self.stdoffset = timedelta(hours=hours)
    self.reprname = reprname
    self.stdname = stdname
    self.dstname = dstname

  def __repr__(self):
    return self.reprname

  def tzname(self, dt):
    if self.dst(dt):
      return self.dstname
    else:
      return self.stdname

  def utcoffset(self, dt):
    return self.stdoffset + self.dst(dt)

  def dst(self, dt):
    if dt is None or dt.tzinfo is None:
      # An exception may be sensible here, in one or both cases.
      # It depends on how you want to treat them.  The default
      # fromutc() implementation (called by the default astimezone()
      # implementation) passes a datetime with dt.tzinfo is self.
      return ZERO
    assert dt.tzinfo is self

    # Find first Sunday in April & the last in October.
    start = first_sunday_on_or_after(DSTSTART.replace(year=dt.year))
    end = first_sunday_on_or_after(DSTEND.replace(year=dt.year))

    # Can't compare naive to aware objects, so strip the timezone from
    # dt first.
    if start <= dt.replace(tzinfo=None) < end:
      return HOUR
    else:
      return ZERO

Eastern  = USTimeZone(-5, "Eastern",  "EST", "EDT")
#Central  = USTimeZone(-6, "Central",  "CST", "CDT")
#Mountain = USTimeZone(-7, "Mountain", "MST", "MDT")
Pacific = USTimeZone(-8, "Pacific",  "PST", "PDT")

now = datetime.now()
print now.strftime( "%a %b %d %X %z" )

pst = now.replace( tzinfo=Pacific )
print pst.strftime( "%a %b %d %X %z" )

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

七月上 2024-08-24 22:33:13

.replace 不进行任何计算:它只是替换新返回对象中的一个或多个字段,同时从调用它的对象中复制所有其他字段。

如果我正确理解你的情况,你从一个日期时间对象开始,你知道(通过其他方式)是UTC,但不知道它本身(有一个 tzinfo 属性 None< /code>,意思是“我对自己所在的时区完全一无所知)。

因此,首先,您从输入的时区朴素对象中创建一个时区感知对象,以便通知它它位于 UTC 时区(所有其他字段都会被复制):

aware = naive.replace(tzinfo=utc)

然后,您可以请求有关时区的计算,并结果打印:

print aware.astimezone(Pacific).strftime('%a %b %d %X %z')

.replace does no computation: it simply replaces one or more field in the new returned object, while copying all others from the object it's called on.

If I understand your situation correctly, you start with a datetime object which you know (through other means) is UTC, but doesn't know that itself (is has a tzinfo attribute of None, meaning "I'm totally clueless regarding what timezone I'm in).

So, first, you make a timezone-aware from your input timezone-naive object, in order to inform it that it's in timezone UTC (all other fields just get copied over):

aware = naive.replace(tzinfo=utc)

Then, you can request computations regarding timezones, and printing in consequence:

print aware.astimezone(Pacific).strftime('%a %b %d %X %z')
森林迷了鹿 2024-08-24 22:33:13

使用 dt.replace(tzinfo=tz) 时,您并没有真正转换时间值,您只是说“嘿不,等等,这个时间实际上是 PDT,而不是 UTC”。您可能需要使用datetime.astimezone(tz)来代替。

With dt.replace(tzinfo=tz) you're not really converting the time value, you're just saying 'hey no, wait, this time was actually in PDT, not in UTC'. You'll probably want to use datetime.astimezone(tz) instead.

遗忘曾经 2024-08-24 22:33:13

我认为 Wim 的想法是正确的,只是倒退了。如果您想知道 UTC 时间,请使用:

print pst.astimezone(UTC).strftime( "%a %b %d %X" )

您必须挖掘 UTC 时区类的定义。我理解为什么 Python 不想提供每个可能的 tzinfo 的默认实现,但 UTC 应该包含在基础包中。

I think Wim had the right idea, just backwards. If you want to know what your time would be in UTC, use:

print pst.astimezone(UTC).strftime( "%a %b %d %X" )

You'll have to dig up a definition for a UTC timezone class. I understand why Python didn't want to supply a default implementation of every possible tzinfo, but UTC should have been included in the base package.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文