在Python中获取给定日期列表中每个月的最后一天

3

我正在使用Python 2.7、PyCharm和Anaconda。

我有一个日期列表,想要获取其中每个月的最后一个日期。

有什么函数或库可以帮助我做到这一点吗?

我从CSV文件中读取日期并将它们存储为datetime

以下是我的代码:

Dates=[]
Dates1=[]
for date in dates:
    temp=xlrd.xldate_as_tuple(int(date),0)
    Dates1.append(datetime.datetime(temp[0],temp[1],temp[2]))

for date in Dates1:
    if not (date<startDate or date>endDate):
        Dates.append(date)

为了更清晰地说明,假设我有以下内容:
Dates = [2015-01-20, 2015-01-15, 2015-01-17, 2015-02-21, 2015-02-06] 

(假设它是以datetime格式)。

我想要检索的列表是:

[2015-01-20, 2015-02-21]

到目前为止,我已经在谷歌上搜索了很多,特别是在Stack Overflow上,但我只能找到如何获取每个月的最后一天的答案,而不是从用户指定的列表中获取。


2
你可以展示一下你写的产生这些日期的代码吗?你目前尝试了什么? - rayryeng
找到本月的实际最后一天,然后从该日期中减去每个日期。最小的数字是最接近的。 - Bob Dylan
我认为问题并不十分清楚。你想要特定月份的最后一个有效日期吗(例如,如果你有[2015-01-20、2015-01-15、2015-01-17],那么你想要的是2015-01-31)?还是想要在你的集合中最晚的日期(所以对于这三个日期,你想要的是2015-01-20)?如果你想要2015-01-31,那么你的问题就是这个问题的副本(https://dev59.com/pHVD5IYBdhLWcg3wO5ED)。 - John Y
1
你还没有真正回答我的问题,但是根据我之前评论中列出的三个日期,听起来你想要2015年1月20日。是这样吗?大多数人(包括下面的两个答案)都理解你的问题是想要2015年1月31日。 - John Y
1
抱歉,我应该说只有Michael Laszlo的回答存在错误的解释;leroyJr似乎已经按照您想要的方式阅读了您的问题。 - John Y
显示剩余3条评论
3个回答

5

Pandas非常适合处理这个任务。将您的csv文件加载到数据帧中,然后按月分组并使用聚合函数找到最大日期:

import pandas as pd
import numpy as np

df = pd.read_csv('/path/to/file/')          # Load a dataframe with your file
df.index = df['my_date_field']              # set the dataframe index with your date
dfg = df.groupby(pd.TimeGrouper(freq='M'))  # group by month / alternatively use MS for Month Start / referencing the previously created object

# Finally, find the max date in each month
dfg.agg({'my_date_field': np.max})

# To specifically coerce the results of the groupby to a list:
dfg.agg({'my_date_field': np.max})['my_date_field'].tolist()

但是我得到的仍然是一个<pandas.core.groupby.DataFrameGroupBy object at 0x1552CDF0>,我似乎无法像访问普通列表/数组一样访问它。例如dfg [0]。 - Pedro Braz
只需再走一步,就可以从DataFrameGroupBy转换为列表:dfg.agg({'a_date': np.max})['a_date'].tolist() # 选择列并强制转换 - leroyJr
1
如果在数据框投影中只选择了单个列,则可以使用更简单的聚合命令(只需函数):Dates.groupby(pd.TimeGrouper(freq='M')).agg(np.max).tolist() - leroyJr

4

对于年份 y 和月份 mcalendar.monthrange(y, m)[1] 返回该月的最后一天的日期。

以下脚本接受一个名为 datesdatetime 对象列表,并创建一个名为 month_last_dates 的新列表,其中包含与 dates 成员所在的每个月的最后一个日期对应的 datetime 对象。

import datetime
import calendar

tuples = [(2015, 8, 1), (2015, 9, 16), (2015, 10, 4)]
dates = [datetime.datetime(y, m, d) for y, m, d in tuples]

month_last_dates = len(dates) * [None]
for i, date in enumerate(dates):
  y, m, d = date.year, date.month, date.day
  last = calendar.monthrange(y, m)[1]
  print y, m, last  # Output for testing purposes.
  month_last_dates[i] = datetime.datetime(y, m, last)

以下是使用列表推导式更简洁的等效脚本:

import datetime
import calendar

tuples = [(2015, 8, 1), (2015, 9, 16), (2015, 10, 4)]
dates = [datetime.datetime(y, m, d) for y, m, d in tuples]

month_last_dates = [datetime.datetime(date.year, date.month,
      calendar.monthrange(date.year, date.month)[1]) for date in dates]

# Output for testing purposes.
for date in month_last_dates:
  print date.year, date.month, date.day

在您的情况下,鉴于列表 Dates,您可以按照以下方式创建一个新列表:

last_dates = [datetime.datetime(date.year, date.month,
      calendar.monthrange(date.year, date.month)[1]) for date in Dates]

这是一个很好的答案,但结果列表与之前的大小相同,理想情况下,我希望得到一个具有唯一日期的列表。有什么想法吗?谢谢! - Pedro Braz
1
当然,你可以对 last_dates 进行这样的操作。在我给你的上面的代码后写:last_dates = list(set(last_dates)) - Michael Laszlo

0

这个非常完美,只需要一行代码:

dates = [datetime.date(2023, 3, 21), datetime.date(2023, 3, 1), datetime.date(2023, 2, 22), datetime.date(2023, 2, 14)]
eom_dates = set(pd.Series(dates,index=dates).groupby(lambda x:x.month).max())

这将导致:

{datetime.date(2023, 2, 22), datetime.date(2023, 3, 21)}

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