确定当前日期的起始时间和结束时间(UTC -> EST -> UTC); Python

46

我将所有时间存储为UTC,并且我的系统设置为UTC(尽管我在东部标准时间)。

我的日期存储格式如下:

Wed, 20 Feb 2013 03:51:39 +0000

然而,我想基于美国东部时间今天的信息进行选择,所以我的尝试如下:

  • Get current time as UTC and change to EST

    datetime.utcnow().replace(tzinfo=tz.tzutc()).astimezone(tz.gettz('America/New_York'))
    2013-02-19 23:17:20.560898-05:00
    
  • Next I want to get the start time for the EST day (2013-02-19 00:00:00.000000-05:00) and the end time (2013-02-19 23:59:59.99999-05:00)

  • Once I have those values, I'd like to convert back to UTC, so I have a high and low value I can clamp by that's correct my EST (my timezone).

如果这不是做这件事的最好方式,或者我漏掉了某些东西(对我来说似乎过于复杂),请帮助我看到光明!

TIA

根据答案更新:

d1 = datetime.utcnow().replace(tzinfo=tz.tzutc()).astimezone(tz.gettz('America/New_York'))
print d1.strftime("%m %d %Y") ; d2 = d1.replace(day=d1.day + 1) ; print d2.strftime("%m %d %Y")

那将给我

02 20 2013
02 21 2013

哪个是正确的?我现在需要从中生成完整的东部标准时间,然后转换为协调世界时。这一点我无法弄清楚。实际上,完成后我可能想要将其转换为UTC时代时间戳,因为这将使我的数据库操作非常简单(<,>,==等)。


我不明白你现在想做什么。我原以为你想要获取2013年2月20日00:00 UTC的EST时间。但是你现在的代码只是以非常复杂的方式获取今天(和明天)的日期... - Lennart Regebro
(In EST, to boot, not UTC) - Lennart Regebro
不要替换日期。那样会在每个月的结尾出现错误。按照我的回答使用timedelta。同时,停止试图一行完成所有操作。你不应该只使用我的回答的“大部分”,而应该全部使用,因为它是完整的。你上面的代码非常难以阅读。 最后,你没有使用时间吗?你只打印出了日期。如果你不想要时间,那么这其中的大部分就毫无意义了。首先,日期没有时区。 - Lennart Regebro
Python:给定UTC中的当前时间,你如何确定特定时区当天的开始和结束时间? - jfs
请注意,不要轻易编辑9年前的问题,特别是那些已经有高赞答案的问题。"我现在需要..."这样的表述很容易被认为是所谓的移动目标问题。也许这种情况在这里并不适用,但请小心并重新考虑你的措辞... - Yunnosch
11个回答

62

将当前时间转换为UTC然后转换为EST的第一步似乎有点毫无意义。您会用这个时间做些什么吗?

除此之外,它似乎相当简单。您想获取一个以UTC表示的EST日期的开始和结束时间,因此您创建它们并将它们转换为UTC。这不是很复杂。:-)

您可能需要查看匹配程序,以便您可以使用今天的开始时间作为较低值,明天的开始时间作为较高值,这样您就不必处理那个23:59:59.9999时间了。

更新:

从我最初的理解您的问题来看,这是您想要做的事情:

首先,您想获取当前日期在UTC中的表示方式(因此在EST晚上11点时,您想要22日,因为在UTC中这是22日。

>>> from datetime import datetime
>>> today = datetime.utcnow().date()
>>> today
datetime.date(2013, 2, 21)

其次,您需要以UTC时间为当天的00:00:00作为搜索的起点。

>>> from dateutil import tz
>>> start = datetime(today.year, today.month, today.day, tzinfo=tz.tzutc())
datetime.datetime(2013, 2, 21, 0, 0, tzinfo=tzutc())

除非您想知道那个时间在纽约是多少:

>>> from dateutil import tz
>>> est = tz.gettz('America/New_York')
>>> start = start.astimezone(est)
>>> start
datetime.datetime(2013, 2, 20, 19, 0, tzinfo=tzfile('/usr/share/zoneinfo/America/New_York'))

而且你也希望明天是结束的时间:

>>> from datetime import timedelta
>>> end = start + timedelta(1)
>>> end
datetime.datetime(2013, 2, 21, 19, 0, tzinfo=tzfile('/usr/share/zoneinfo/America/New_York'))

概要:

today = datetime.utcnow().date()
start = datetime(today.year, today.month, today.day, tzinfo=tz.tzutc()).astimezone(est)
end = start + timedelta(1)

苦于让它正常工作。我已经更新了我的原始帖子,附上了我的代码。 - mr-sk
谢谢 - 我最终使用了大部分内容。我会更新我的原始帖子并附上答案。 - mr-sk
开始时间为什么是昨天而不是今天?结束时间为什么是今天而不是明天?附注:我将.astimezone(est)替换为.astimezone()以获取本地时区。 - user13888987

26

使用 datetimepytz 将解决您的问题。

def get_start_and_end():
    tz = pytz.timezone('Asia/Shanghai')
    today = datetime.now(tz=tz)
    start = today.replace(hour=0, minute=0, second=0, microsecond=0)
    end = start + timedelta(1)

    return start, end

有没有办法用本地时间替换 'Asia/Shanghai'?我尝试了 get_localzone(),但是出现了 AttributeError: 'America/Toronto' object has no attribute 'upper' - user13888987
1
它也可以工作:end = today.replace(hour=23, minute=59, second=59, microsecond=999999) - Hill

8

这只是部分答案,因为其他部分已经被很好地解释了。我有一段时间都在苦恼这个问题,因为有些技术具有包含搜索功能,我不想包括下一天的第一微秒的任何数据。

我找到的快速准确找到当天结束时间的解决方案是:

reference_time.replace(hour=0, minute=0, second=0, microsecond=0) + timedelta(days=1,microseconds=-1)

8

这个问题虽然老了,但也许这会有所帮助:

import datetime
end_of_today = datetime.datetime.combine(datetime.datetime.today(), datetime.time(23, 59, 59, 999999))

甚至是datetime.datetime.combine(datetime.datetime.now(), datetime.time.max) - undefined

7

我会建议你看一下 Delorean,来解决你的问题需要遵循以下几个步骤。

首先需要解析你的字符串。最好使用 Delorean 的 parse 方法。

>>> from delorean import parse
>>> d = parse("Wed, 20 Feb 2013 03:51:39 +0000")
>>> d
Delorean(datetime=2013-02-20 03:51:39+00:00, timezone=UTC)

一旦您将解析的日期时间转换为 Delorean 对象,您只需将其转换为 EST。
>>> d = d.shift('US/Eastern')
>>> d
Delorean(datetime=2013-02-19 22:51:39-05:00, timezone=US/Eastern)

虽然毫无意义。在你的问题中从未使用过它,但使用 Delorean 很容易。

然后您可以获得当前的 EST 时间。

from delorean import Delorean

>>> d1 = Delorean(timezone="US/Eastern")
>>> d1
Delorean(datetime=2013-02-21 00:35:56.405256-05:00, timezone=US/Eastern)

现在进行截断步骤。
>>> d.truncate('day')
Delorean(datetime=2013-02-21 00:00:00-05:00, timezone=US/Eastern)

将上述简单转换应用到UTC。

现在获取当天结束时间。

d = d.next_day(1) # move to the next day

然后将时间向后调整一秒钟。图书馆需要这样做,我将对此进行更新。只需通过使用datetime属性请求Delorean示例中的日期时间即可。
d.datetime - timedelta(seconds=1)
datetime.datetime(2013, 2, 21, 23, 59, 59, tzinfo=<DstTzInfo 'US/Eastern' EST-1 day, 19:00:00 STD>)

祝你好运,但这个库应该简化你处理日期时间操作的过程 :)

1
往回移动一秒钟?那不是这一天的结束,这一天中还缺少了整整一秒钟。你可以减去一微秒,或者进行比较,使用 if some_datetime < start_of_next_day,这才是正确的做法。 - Daniel F

3

你觉得这个怎么样?

import datetime
datetime.datetime.combine(datetime.date.today(), datetime.time(00, 00, 00))
datetime.datetime.combine(datetime.date.today(), datetime.time(23, 59, 59))

这个解决方案不包括微秒的情况。如果你添加 999999 微秒 - 这将更加正确,因为你实际上覆盖了整个一天:datetime.datetime.combine(datetime.date.today(), datetime.time(23, 59, 59, 999999)) - finomayato

2

我刚遇到了这个问题,这里是我找到的最简单的解决方案:

from delorean import Delorean
today_d = Delorean()
sod_dt = today_d.start_of_day
eod_dt = today_d.end_of_day
sod_d = Delorean(sod_dt)
eod_d = Delorean(eod_dt)
sod_e = sod_d.epoch
eod_e = eod_d.epoch

确认:

In [69]: eod_e - sod_e
Out[69]: 86399.99999904633

大多数人认为这已经足够接近了。

2

如果您已经使用 Arrow,那么这里有一个不错的解决方案

import arrow

now = arrow.now('US/Eastern')
start = now.floor('day')
end = now.ceil('day')

# Use the "datetime" property to access the actual datetime
print(start.datetime)

1
为了获取一天中的最小和最大时间,您可以使用datetime.time,它可以给您最早和最晚的可表示时间: time.min --> datetime.time(0, 0) time.max --> datetime.time(23, 59, 59, 999999)
然后,您可以将其与datetime.now()或所需的特定日期相结合,以获取所需的结果。
from datetime import datetime, time
tmp = datetime.combine(datetime.now(), time.max)
print(tmp) --> 2022-09-27 23:59:59.999999

from datetime import datetime, time
tmp = datetime.combine(datetime.now(), time.max)
print(tmp) --> 2022-09-27 00:00:00

1

使用Python3.8,我们可以按照以下方式进行操作:

from datetime import datetime, timedelta, time
from pytz import timezone

today = datetime.utcnow()
start_of_day = datetime.combine(today, time.min).astimezone(tz=timezone('America/New_York'))
end_of_day = datetime.combine(today, time.max).astimezone(tz=timezone('America/New_York'))

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接