Даты начала и окончания месяца Python между двумя датами

#python #pandas #numpy #datetime #python-datetime

#python #pandas #numpy #дата и время #python-datetime

Вопрос:

Мне нужно, чтобы даты начала и окончания каждого месяца были между двумя датами. В настоящее время я создаю список вручную каждый раз, когда мне это нужно.

 start = 2019-10-01
end = today
  

Ожидаемый результат:

 start_times = ['10/1/2019 05:00:00 AM','11/1/2019 05:00:00 AM','12/1/2019 05:00:00 AM','1/1/2020 05:00:00 AM','2/1/2020 05:00:00 AM','3/1/2020 05:00:00 AM' '4/1/2020 05:00:00 AM','5/1/2020 05:00:00 AM','6/1/2020 05:00:00 AM','7/1/2020 05:00:00 AM','8/1/2020 05:00:00 AM']
end_times = ['10/31/2019 08:00:00 PM','11/30/2019 08:00:00 PM','12/31/2019 08:00:00 PM','1/31/2020 08:00:00 PM','2/29/2020 08:00:00 PM','3/31/2020 08:00:00 PM','4/30/2020 08:00:00 PM','5/31/2020 08:00:00 PM','6/30/2020 08:00:00 PM','7/31/2020 08:00:00 PM','8/31/2020 08:00:00 PM']
  

Есть идеи о том, как действовать здесь.

Комментарии:

1. откуда берутся 5 утра и 8 вечера?

2. Для выполнения остальной части программы даты должны быть в этом формате. В противном случае возникает ошибка.

Ответ №1:

Поскольку вам нужен диапазон дат и конкретное форматирование, я бы предложил использовать numpy для создания диапазона дат и вычислений, а затем использовать python datetime для форматирования следующим образом:

 import numpy as np
import datetime as dt

def dateRange(start='2019-10-01', end='2020-08-28'):
    
    start_date = np.datetime64(start[:-3])  
    #Add one month to end date so last month is included
    end_date = np.datetime64(end[:-3])   np.timedelta64(1, 'M')
    #Create Date Range
    date_range = np.arange(start_date, end_date, dtype='datetime64[M]')
    #Add 5 AM to start_dates
    start_dates = date_range   np.timedelta64(5, 'h')
    #Add 1 Month and subrtract 4 hours to 8 PM on last day of month
    end_dates = date_range   np.timedelta64(1, 'M') - np.timedelta64(4, 'h')
    #Apply Formatting   
    final_start_dates = [parse_date(np.datetime_as_string(d, unit='s')) for d in start_dates]
    final_end_dates = [parse_date(np.datetime_as_string(d, unit='s')) for d in end_dates]
    
    return final_start_dates, final_end_dates

def parse_date(date_string):
    #parse numpy date string
    date_time = date_string.split('T')
    date_parts = date_time[0].split('-')
    time_parts = date_time[1][:-1].split(':')
    #convert string values to ints
    datetime_ints = [int(d) for d in date_parts]   [int(time_parts[0])]
    
    #apply formatting
    return dt.datetime(*datetime_ints).strftime('%m/%d/%Y %I:%M:%S %p')
  

Вывод:

 >>> start,end=dateRange()
>>> start
['10/01/2019 05:00:00 AM', '11/01/2019 05:00:00 AM', '12/01/2019 05:00:00 AM', '01/01/2020 05:00:00 AM', '02/01/2020 05:00:00 AM', '03/01/2020 05:00:00 AM', '04/01/2020 05:00:00 AM', '05/01/2020 05:00:00 AM', '06/01/2020 05:00:00 AM', '07/01/2020 05:00:00 AM', '08/01/2020 05:00:00 AM']
>>> end
['10/31/2019 08:00:00 PM', '11/30/2019 08:00:00 PM', '12/31/2019 08:00:00 PM', '01/31/2020 08:00:00 PM', '02/29/2020 08:00:00 PM', '03/31/2020 08:00:00 PM', '04/30/2020 08:00:00 PM', '05/31/2020 08:00:00 PM', '06/30/2020 08:00:00 PM', '07/31/2020 08:00:00 PM', '08/31/2020 08:00:00 PM']
  

Я думаю, это то, что вы ищете в своем вопросе о создании каждого дня. На самом деле это проще.

 def all_dates(start='2019-10-01', end='2019-10-15'):
    
    start_date = np.datetime64(start)   
    #Add one day to end date so last say is included
    end_date = np.datetime64(end)   np.timedelta64(1, 'D')
    #Create Date Range
    date_range = np.arange(start_date, end_date, dtype='datetime64[D]')
    
    final_start_dates = [parse_date(np.datetime_as_string(d   np.timedelta64(5, 'h'), unit='s')) for d in date_range]
    
    final_end_dates = [parse_date(np.datetime_as_string(d   np.timedelta64(20, 'h'), unit='s')) for d in date_range]
    
    return final_start_dates, final_end_dates
  

Вывод:

 >>> start, end = all_dates()
>>> start
['10/1/2019 05:00:00 AM', '10/2/2019 05:00:00 AM', '10/3/2019 05:00:00 AM', '10/4/2019 05:00:00 AM', '10/5/2019 05:00:00 AM', '10/6/2019 05:00:00 AM', '10/7/2019 05:00:00 AM', '10/8/2019 05:00:00 AM', '10/9/2019 05:00:00 AM', '10/10/2019 05:00:00 AM', '10/11/2019 05:00:00 AM', '10/12/2019 05:00:00 AM', '10/13/2019 05:00:00 AM', '10/14/2019 05:00:00 AM', '10/15/2019 05:00:00 AM']
>>> end
['10/1/2019 08:00:00 PM', '10/2/2019 08:00:00 PM', '10/3/2019 08:00:00 PM', '10/4/2019 08:00:00 PM', '10/5/2019 08:00:00 PM', '10/6/2019 08:00:00 PM', '10/7/2019 08:00:00 PM', '10/8/2019 08:00:00 PM', '10/9/2019 08:00:00 PM', '10/10/2019 08:00:00 PM', '10/11/2019 08:00:00 PM', '10/12/2019 08:00:00 PM', '10/13/2019 08:00:00 PM', '10/14/2019 08:00:00 PM', '10/15/2019 08:00:00 PM']
  

Комментарии:

1. У меня вопрос. Теперь я хочу создавать каждый день с таймингами 5 утра и 8 вечера. Как мне это получить?

2. Спасибо. На самом деле я изменил ваш исходный код, чтобы создавать даты месяца или дня в зависимости от требований. Спасибо за ваш ответ.

Ответ №2:

Последним днем будет первый день следующего месяца минус 1.

 from datetime import datetime
from datetime import timedelta

start = datetime(year = 2020, month = 5, day = 16)

start_times = datetime(year = start.year, month = start.month, day = 1)

if start.month == 12:
    end_times = datetime(year = start.year   1, month = 1, day = 1) - timedelta(days = 1)
else:
    end_times = datetime(year = start.year, month = start.month   1, day = 1) - timedelta(days = 1)
    
print(start_times)
print(end_times)
  

вывод:

 2020-05-01 00:00:00
2020-05-31 00:00:00