【问题标题】:Rolling date generation滚动日期生成
【发布时间】:2022-01-12 12:23:44
【问题描述】:

如果我在一个字符串中给出一个日期,例如start_date = '01-Feb-21',我怎样才能从这个输入中生成总共八个日期?

这八个日期是:

['01-Feb-21', # we get this from the input
 '28-Feb-21',
 '01-Jan-21',
 '31-Jan-21',
 '01-Dec-20',
 '31-Dec-20',
 '01-Nov-20',
 '30-Nov-20']

对应start_date的月初和月底以及前3个月。

【问题讨论】:

  • 您会发现 datetime 模块对此非常有帮助
  • 请阐明创建这些日期的规则。
  • @pedro Maia 我想以前 3 个月(包括输入中给出的月份)的日期格式生成第一天和最后一天的日期

标签: python python-3.x function


【解决方案1】:

您可以使用 datetime 完成此操作,但是,获取一个月的最后一天是 tricky

pandasdatetime 之上构建了不错的时间实用功能:

import pandas as pd
from pandas.tseries.offsets import MonthEnd

start_date = "01-Feb-21"
N = 8

fmt = '%d-%b-%y'

# get month starts
s = pd.date_range(end=start_date, periods=N//2, freq='MS').to_series()
out = (pd.concat([s.dt.strftime(fmt),
                  (s + MonthEnd()).dt.strftime(fmt)],  # get month ends
                 axis=1)
         .iloc[::-1]                    # reverse order
         .to_numpy().ravel().tolist()   # convert to flat list
         # line above can also be replace with
         # .stack().to_list()
      )

输出:

['01-Feb-21',
 '28-Feb-21',
 '01-Jan-21',
 '31-Jan-21',
 '01-Dec-20',
 '31-Dec-20',
 '01-Nov-20',
 '30-Nov-20']

【讨论】:

    【解决方案2】:

    这个答案有点长,但它只使用datetimecalendar 模块来获得预期的结果:

    import calendar
    from datetime import datetime, date
    
    
    def generate_rolling_date(input_date, number_of_dates):
        """
        Generate Rolling Date
        :param input_date: Input Date (e.g. '01-Feb-21')
        :param number_of_dates: Number of rolling date to generate
        :return:
        """
        # Convert input_date to datetime according to the format
        parsed_date = datetime.strptime(input_date, "%d-%b-%y")
    
        # Separate Day, Month and Year
        parsed_day = parsed_date.day
        parsed_month = parsed_date.month
        parsed_year = parsed_date.year
    
        # Initialize an empty output list
        output = []
    
        # using calendar module, gets the total number of days i.e. last day in parsed_month
        _, num_days = calendar.monthrange(parsed_year, parsed_month)
    
        # Check if the parsed_day is the last day of the month or not, according to that set the start_date flag
        start_date = False if num_days == parsed_day else True
    
        # Loop through the number_of_dates to generate the rolling dates
        for i in range(number_of_dates):
            # If the parsed_month value is 0, then decrease the parsed_year by 1 and set the parsed_month value to 12
            if parsed_month == 0:
                parsed_year -= 1
                parsed_month = 12
            # Get the total number of days i.e. last day in parsed_month
            _, num_days = calendar.monthrange(parsed_year, parsed_month)
            # If start_date, then get the first day of the month and set start_date to False,
            # so we can get the last day of month in the next loop
            if start_date:
                # Get the first day of the month
                selected_day = date(parsed_year, parsed_month, 1)
                start_date = False
            else:
                # Get the last day of the month
                selected_day = date(parsed_year, parsed_month, num_days)
                # After getting the last day of the month, decrease the parsed_month by 1 to get the previous month
                parsed_month -= 1
                start_date = True
            # Append selected_day to the output
            output.append(date.strftime(selected_day, "%d-%b-%y"))
        # Return the output
        return output
    
    print(generate_rolling_date("01-Feb-21", 8))
    

    它给出以下输出:

    ['01-Feb-21',
     '28-Feb-21',
     '01-Jan-21',
     '31-Jan-21',
     '01-Dec-20',
     '31-Dec-20',
     '01-Nov-20',
     '30-Nov-20']
    

    【讨论】:

    • False if num_days == parsed_day else True 等价于num_days != parsed_day
    • @Jasmijn,是的,明白了。
    猜你喜欢
    • 1970-01-01
    • 2020-12-24
    • 1970-01-01
    • 1970-01-01
    • 2016-10-29
    • 1970-01-01
    • 2017-08-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多