简体   繁体   English

如何在两个 Python 日期时间范围内计算属于给定月份的天数?

[英]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-292017-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: 否则,您将需要知道给定月份中有多少天,并且需要针对不同方案的不同代码:

  1. The given month is the month of the first date 给定的月份是第一个日期的月份
  2. The given month is the month of the second date 给定的月份是第二个日期的月份
  3. The given month is between the first and the second date (if dates span more than two months) 给定的月份在第一个日期和第二个日期之间(如果日期跨越两个月以上)

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.

相关问题 获取 pandas 中一个月级别的两个日期时间之间的天数 - get number of days between two datetimes on a month level in pandas 如何在给定范围的Python表中添加特定日期的值? - How to add the values for Specific days in Python Table for a given range? 打印给定月份和年份的天数 [Python] - Printing the number of days in a given month and year [Python] 在 Python 中按月计算某个范围内的天数? - Counting the number of days in a range by month in Python? 使用Python计算一个月的工作日数? - Using Python to count the number of business days in a month? Pandas:计算给定开始日期和结束日期之间每个月的天数 - Pandas: Count days in each month between given start and end date Python:如何在处理歧义天(23和25小时)的同时向本地化日期时间增加天数 - Python: How to add days to localized datetimes while handling ambigious days (23 and 25 hours days) 如何检查给定的日期时间对象是否在两个日期时间之间? - How do I check if a given datetime object is “between” two datetimes? 如何按年-月和枢轴聚合天数,使计数变为使用 Python 在该月内求和的 count_source - How to aggregate days by year-month and pivot so that count becomes count_source summed over the month with Python 如何查看给定的日期是否在其他两个datetimes对象之间? - How to see if the given date is between two other datetimes objects?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM