[英]How to count days belonging to a given month in the range of two Python datetimes?
I have two Python datetime
and I want to count the days between those dates, counting ONLY the days belonging to the month I choose.我有两个 Python
datetime
,我想计算这些日期之间的天数,只计算属于我选择的月份的天数。 The range might overlap multiple months/years.该范围可能会重叠多个月/年。
Example: If I have 2017-10-29
& 2017-11-04
and I chose to count the days in October, I get 3 (29, 30 & 31 Oct.).示例:如果我有
2017-10-29
和2017-11-04
并且我选择计算 10 月的天数,我会得到 3(10 月 29、30 和 31 日)。
I can't find a straightforward way to do this so I think I'm going to iterate over the days using datetime.timedelta(days=1)
, and increment a count each time the day belongs to the month I chose.我找不到一种直接的方法来做到这一点,所以我想我将使用
datetime.timedelta(days=1)
迭代几天,并在每一天属于我选择的月份时增加一个计数。
Do you know a more performant method?你知道一个更高效的方法吗?
I'm using Python 2.7.10 with the Django framework.我在Django框架中使用Python 2.7.10 。
You can get difference between two datetime objects by simply subtracting them. 您可以通过简单地减去两个日期时间对象来获得它们之间的差异。
So, we start by getting the difference between the two dates. 因此,我们首先获得两个日期之间的差异。 And then we generate all the dates between the two using
然后我们使用生成两个日期之间的所有日期
gen = (start_date + datetime.timedelta(days = e) for e in range(diff + 1))
And since we only want the dates between the specified ones, we apply a filter. 并且由于我们只希望指定日期之间的日期,因此我们应用了一个过滤器。
filter(lambda x : x==10 , gen)
Then we will sum them over. filter(lambda x : x==10 , gen)
然后将它们求和。 And the final code is this: 最终的代码是这样的:
diff = start_date - end_date
gen = (start_date + datetime.timedelta(days = e) for e in range(diff + 1))
filtered_dates = filter(
lambda x : x.month == 10 ,
gen
)
count = sum(1 for e in filtered_dates)
You can also use reduce
but sum()
is a lot more readable. 您也可以使用
reduce
但是sum()
更具可读性。
Iterating over the days would be the most straightforward way to do it. 经过几天的迭代将是最简单的方法。 Otherwise, you would need to know how many days are in a given month and you would need different code for different scenarios:
否则,您将需要知道给定月份中有多少天,并且需要针对不同方案的不同代码:
If you want to support dates spanning more than one year then you would need the input to include month and year. 如果要支持跨越一年以上的日期,则需要输入内容包括月份和年份。
Your example fits scenario #1, which I guess you could do like this: 您的示例适合方案1,我想您可以这样做:
>>> from datetime import datetime, timedelta
>>>
>>> first_date = datetime(2017, 10, 29)
>>>
>>> first_day_of_next_month = first_date.replace(month=first_date.month + 1, day=1)
>>> last_day_of_this_month = first_day_of_next_month - timedelta(1)
>>> number_of_days_in_this_month = last_day_of_this_month.day
>>> number_of_days_in_this_month - first_date.day + 1
3
This is why I would suggest implementing it the way you originally intended and only turning to this if there's a performance concern. 这就是为什么我建议按照您最初打算的方式实现它,并且仅在存在性能问题时才转向它。
A potential method of achieving this is to first compare whether your start or end dates you are comparing have the same month that you want to choose. 实现此目的的一种可能方法是首先比较您比较的开始或结束日期是否具有要选择的同一月。
For example: 例如:
start = datetime(2017, 10, 29)
end = datetime(2017, 11, 4)
We create a function to compare the dates like so: 我们创建一个函数来比较日期,如下所示:
def daysofmonth(start, end, monthsel):
if start.month == monthsel:
days = (datetime(start.year, monthsel+1, 1) - start).days
elif end.month == monthsel:
days = (end - datetime(end.year, monthsel, 1)).days
elif not (monthsel > start.month) & (end.month > monthsel):
return 0
else:
days = (datetime(start.year, monthsel+1, 1) - datetime(start.year, monthsel, 1)).days
return days
So, in our example setting monthsel gives: 因此,在我们的示例中,设置月度可以得出:
>>> daysofmonth(start, end, 10)
>>> 3
Using pandas whit your dates:使用熊猫与您的约会对象:
import pandas as pd
from datetime import datetime
first_date = datetime(2017, 10, 29)
second_date = datetime(2017, 11, 4)
days_count = (second_date - first_date).days
month_date = first_date.strftime("%Y-%m")
values = pd.date_range(start=first_date,periods=days_count,freq='D').to_period('M').value_counts()
print(values)
print(values[month_date])
outputs产出
2017-10 3
2017-11 3
3
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.