我怎么知道今天是不是因为当地时间的变化而导致的一天,例如python和pandas时间戳中的夏令时?

时间:2019-02-05 09:47:29

标签: python-3.x pandas timezone timezone-offset

根据英国夏令时/夏令时(https://www.gov.uk/when-do-the-clocks-change)的规则,时钟:

  • 3月的最后一个星期日凌晨1点前进1小时,
  • 在10月的最后一个星期日的凌晨2点回到1小时。

在2019年,本地时间发生在3月31日和10月27日之间,但每年的日期略有变化。是否有一种干净的方法来知道每个输入年份的这些日期?

我需要自动检查这些“更改时间”日期,是否可以避免for循环检查每个日期的详细信息以查看它是否是“更改时间”日期?

此刻,我正在探索2019年的这些日期,试图找出可重复/自动的程序,我发现了这一点:

# using datetime from the standard library
march_utc_30 = datetime.datetime(2019, 3, 30, 0, 0, 0, 0, tzinfo=datetime.timezone.utc)
march_utc_31 = datetime.datetime(2019, 3, 31, 0, 0, 0, 0, tzinfo=datetime.timezone.utc)
april_utc_1 = datetime.datetime(2019, 4, 1, 0, 0, 0, 0, tzinfo=datetime.timezone.utc)
# using pandas timestamps
pd_march_utc_30 = pd.Timestamp(march_utc_30) #, tz='UTC')
pd_march_utc_31 = pd.Timestamp(march_utc_31) #, tz='UTC')
pd_april_utc_1 = pd.Timestamp(april_utc_1) #, tz='UTC')
# using pandas wrappers
pd_local_march_utc_30 = pd_march_utc_30.tz_convert('Europe/London')
pd_local_march_utc_31 = pd_march_utc_31.tz_convert('Europe/London')
pd_local_april_utc_1 = pd_april_utc_1.tz_convert('Europe/London')
# then printing all these dates
print("march_utc_30 {} pd_march_utc_30 {} pd_local_march_utc_30 {}".format(march_utc_30, pd_march_utc_30, pd_local_march_utc_30))
print("march_utc_31 {} pd_march_utc_31 {} pd_local_march_utc_31 {}".format(march_utc_31, pd_march_utc_31, pd_local_march_utc_31))
print("april_utc_1  {} pd_april_utc_1  {} pd_local_april_utc_1  {}".format(april_utc_1, pd_april_utc_1, pd_local_april_utc_1))

这些print语句的输出为:

march_utc_30 2019-03-30 00:00:00+00:00 pd_march_utc_30 2019-03-30 00:00:00+00:00 pd_local_march_utc_30 2019-03-30 00:00:00+00:00
march_utc_31 2019-03-31 00:00:00+00:00 pd_march_utc_31 2019-03-31 00:00:00+00:00 pd_local_march_utc_31 2019-03-31 00:00:00+00:00
april_utc_1  2019-04-01 00:00:00+00:00 pd_april_utc_1  2019-04-01 00:00:00+00:00 pd_local_april_utc_1  2019-04-01 01:00:00+01:00

我可以使用for循环来确定当前日期是否是该月的最后一个星期日,或者比较当前日期和日期之间的“小时增量”第二天看看是否有+1,但我想知道是否有更清洁的方法?

年份中是否有其他内容,例如知道输入年份是2019,那么我们确定3月的“更改日期”将是第31天吗?

2 个答案:

答案 0 :(得分:1)

使用dateutil.rrule可以帮助(与pip install python-dateutil一起安装)。

因为我们可以按星期提取日期,所以不需要任何循环,

from dateutil.rrule import rrule, WEEKLY
from dateutil.rrule import SU as Sunday
from datetime import date
import datetime

def get_last_sunday(year, month):
    date = datetime.datetime(year=year, month=month, day=1)
    # we can find max 5 sundays in a months
    days = rrule(freq=WEEKLY, dtstart=date, byweekday=Sunday, count=5)
    # Check if last date is same month,
    # If not this couple year/month only have 4 Sundays
    if days[-1].month == month:
        return days[-1]
    else:
        return days[-2]

def get_march_switch(year):
    # Get 5 next Sundays from first March
    day = get_last_sunday(year, 3)
    return day.replace(hour=1, minute=0, second=0, microsecond=0)

def get_october_switch(year):
    day = get_last_sunday(year, 10)
    return day.replace(hour=2, minute=0, second=0, microsecond=0)

print('2019:')
print('  {}'.format(get_march_switch(2019)))
print('  {}'.format(get_october_switch(2019)))

print('2021:')
print('  {}'.format(get_march_switch(2021)))
print('  {}'.format(get_october_switch(2021)))

get_sundays()返回给定month的第一天起的下5个星期日,因为一个月最多可以包含5个星期日。

然后我只检查get_(march|october)_switch()内的最后一个星期日是否是预期的月份,如果这个月只有4个星期,如果不好,我就选择了这个星期。

最后我确定了小时,秒和微秒。

输出:

2019:
  2019-03-31 01:00:00
  2019-10-27 02:00:00
2021:
  2021-03-28 01:00:00
  2021-10-24 02:00:00

答案 1 :(得分:1)

我知道这个话题已经很老了。但是,今天我有同样的问题,最后我找到了一个对我来说似乎很简单的解决方案,只使用标准日期时间:

我想检查我的日期 refdate 是否是DST的10月-我是通过以下方式完成的:

refdate 是我的标准datetime对象。 如果您有熊猫时间戳记,则可以使用.to_pydatetime()

将其转换为本地日期时间
if refdate.month == 10 and refdate.weekday() == 6 and (refdate + dt.timedelta(weeks = 1)).month == 11:
    oct_dst = 1