正如标题所说,我正在尝试生成一个与两个日期之间某个特定日期相关的日期时间列表。
因此,给定一个开始日期,结束日期和一个月中的某一天,我希望看到该月的那一天的每一次出现:
from datetime import datetime
end_date = datetime(2012, 9, 15, 0, 0)
start_date = datetime(2012, 6, 1, 0, 0)
day_of_month = 16
dates = "magic code goes here"
然后日期将保持一个数组:
dates == [
datetime(2012, 6, 16, 0, 0),
datetime(2012, 7, 16, 0, 0),
datetime(2012, 8, 16, 0, 0)
]
我遇到的问题是我必须执行的检查次数。首先,我必须检查它是否是开始年份,如果是,那么我必须在开始月份开始,但如果月份的日期在开始日期之前,那么我必须跳过那个月。同样的事情适用于期末。更不用说我必须检查期间是否在同一年开始和结束。总而言之,它变成了一堆嵌套的if
和for
语句。
这是我的解决方案:
import numpy as np
for year in np.arange(start_date.year, end_date.year + 1):
for month in np.arange(1, 13):
date = datetime(year, month, day_of_month, 0, 0)
if start_date < date < end_date:
dates.append(date)
有没有更多的Pythonic方法来实现这个目标?
答案 0 :(得分:3)
这是一个快速而肮脏(但效率相当高)的解决方案:
import datetime
d = start_date
days = []
while d <= end_date: # Change to < if you do not want the end_date
if d.day == day_of_month:
days.append(d)
d += datetime.timedelta(1)
days
# [datetime.datetime(2012, 6, 16, 0, 0),
# datetime.datetime(2012, 7, 16, 0, 0),
# datetime.datetime(2012, 8, 16, 0, 0)]
理想情况下,您希望使用pandas
。
答案 1 :(得分:2)
使用pandas.date_range
这是一种简洁但无效的方式。
from datetime import datetime
import pandas as pd
end_date = datetime(2012, 9, 15, 0, 0)
start_date = datetime(2012, 6, 1, 0, 0)
day_of_month = 16
rng = [i.to_pydatetime() for i in pd.date_range(start_date, end_date, freq='1D') if i.day == day_of_month]
# [datetime.datetime(2012, 6, 16, 0, 0),
# datetime.datetime(2012, 7, 16, 0, 0),
# datetime.datetime(2012, 8, 16, 0, 0)]
以下是使用日期范围生成器的更有效方法,该方法不依赖于pandas
:
def daterange(start_date, end_date):
for n in range(int ((end_date - start_date).days)):
yield start_date + timedelta(n)
rng = [i for i in daterange(start_date, end_date) if i.day == day_of_month]
# [datetime.datetime(2012, 6, 16, 0, 0),
# datetime.datetime(2012, 7, 16, 0, 0),
# datetime.datetime(2012, 8, 16, 0, 0)]