简体   繁体   English

日期时间范围中前一天/月/年的第一个可用日期

[英]First available date previous day/month/year from a datetime range

I have a datetime instance with dates ( dfDates ): 我有一个带有日期( dfDates )的datetime实例:

2017-03-01 00:00
2017-03-02 00:00
2017-03-04 00:00
...

For the last day (here: 2017-03-04 ) I calculate the previous day/month/year/etc. 对于最后一天(这里: 2017-03-04 ),我计算前一天/月/年/等。 as follows: 如下:

def previous_day(dtToday):
    return dtToday - pd.DateOffset(days=1)

This returns 2017-03-03 . 这将返回2017-03-03 However, this business day is not available in my range of dates ( dfDates ). 但是,该工作日在我的日期范围( dfDates )中不可用。

I am therefore looking for a robust way to find the date that is the closest to the previous day/month/year/etc.. In this case for the previous day it should return 2017-03-02 . 因此,我正在寻找一种可靠的方法来查找最接近前一天/月/年/等的日期。在这种情况下,对于前一天,它应该返回2017-03-02

Note, I understand that you can do something like index -1 to get the previous day. 请注意,我知道您可以执行类似于索引-1来获取前一天。 It becomes however complicated when taking the previous month (there are not always 30 days in a month) and even the previous year (there are not always 252 working days in a year). 但是,如果使用上个月(一个月中并不总是有30天)甚至上一年(一年中并不总是有252工作日),情况就会变得很复杂。 Is there therefore a robust method to get the closest available date? 因此,是否有一种可靠的方法来获取最接近的可用日期?

Update 更新

I understand also that you can use timedelta as follows: 我也了解您可以使用timedelta如下:

from datetime import datetime, timedelta

d = datetime.today() - timedelta(days=days_to_subtract)

However, how does that relate to dtToday and how can I link it with dfDates ? 然而,如何不会涉及到dtToday ,我怎么能与它联系起来dfDates dtToday in my case is not always datetime.today() . 在我的情况下, dtToday并不总是datetime.today() Sometimes its a random date. 有时是随机日期。

Not the most efficient, but you can try: 不是最有效的,但是您可以尝试:

# From your function
day_minus_one = previous_day(dtToday)

# Return LAST element in INDEX of DF FROM START TO DAY_MINUS_ONE
actual = df.loc[:day_minus_one].index[-1]

This essentially returns you the last index of a copy of your df, up to and including day_minus_one, if any of the dates exist . 本质上,这将返回您df副本的最后一个索引直到存在date_minus_one(包括date_minus_one)为止 This should give you the closest date, or the date itself. 这应该为您提供最接近的日期或日期本身。

You can try: 你可以试试:

# Returns LAST element of INDEX of df from DAY_MINUS_ONE_HUNDRED to DAY_MINUS_ONE
actual_better = df.loc[day_minus_one_hundred:day_minus_one].index[-1]

To only look back one_hundred days from minus_one if your dataset is huge, so you don't have to return a huge array just to find one date. 如果数据集很大,则只需从minus_one中回顾一百天,因此您不必返回庞大的数组即​​可找到一个日期。

If I understand correctly, you don't want to actually subtract 1 day, you want to get the previous available day from the list of available dates. 如果我理解正确,那么您实际上不想减去1天,而是希望从可用日期列表中获得前一个可用日期。 If that's the case, then consider this : 如果是这样,请考虑以下问题:

available_dates = [
  2017-03-01 00:00,
  2017-03-02 00:00,
  2017-03-04 00:00,
  ...
]

def previous_day(dtToday):
    today_index = available_dates.index(dtToday)
    return available_dates[today_index-1]

This assumes, of course, that your available_dates is sorted 当然,这假设您的available_dates已排序

EDIT: 编辑:

If you want to be able to subtract month and years, then something a little bit more complex is needed : 如果您希望能够减去月份和年份,则需要稍微复杂一点:

# Sorted
available_dates = [
  2017-03-01 00:00,
  2017-03-02 00:00,
  2017-03-04 00:00,
  ...
]

subtract_from_date(date, day=None, month=None, year=None):
  # check if it's day/month/yeah
  ...
  # do the actual subtraction and store it in substracted_date
  ...
  # get the closest date
  for index, date in enumerate(available_dates):
     if date > substracted_date:
       return available_dates[index-1]

I solved it like this: 我这样解决了:

  • dtToday = the reference date dtToday =参考日期
  • dtDates = a datetime sequence of the available dates dtDates =可用日期的日期时间序列
  • nbOffset = the number of days/months/years we want to go back nbOffset =我们要返回的天数/月数/年数

Code: 码:

def previous_day(dtToday, dtDates, nbOffset):
    prevx   = dtToday - pd.DateOffset(days=nbOffset)
    return test_day_in(prevx, dtDates)

def previous_month(dtToday, dtDates, nbOffset):
    prevx = dtToday - pd.DateOffset(months=nbOffset)
    return test_day_in(prevx, dtDates)

def previous_year(dtToday, dtDates, nbOffset):
    prevx = dtToday - pd.DateOffset(years=nbOffset)
    return test_day_in(prevx, dtDates)

def test_day_in(dtTest, dtDates):
    if dtTest in dtDates:
        return dtTest
    else:
        return tryNextDay(dtTest, dtDates)

def tryNextDay(dtTest, dtDates):

    # if not outside the bound
    if (dtTest < dtDates.min()):
        return dtDates.min()

    # check if next day exist
    if (dtTest + pd.DateOffset(days=1) <= dtDates.max()):
        return previous_day(dtTest + pd.DateOffset(days=2), dtDates, 1) # 2-1
    else:
        print('warning, tryNextDay triggered')
        # should not be triggered, it should take by default the dtDates.min() if far outside range
        return dtTest

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM