I want to create a pandas DatetimeIndex that contains a range of dates around the leap day for various years. Some years are a leap year and some are not. The caveat here though is that I want all of these lists of dates to be the same length. Let's look at some examples.
import pandas as pd
from datetime import timedelta
leap=pd.date_range('2020-02-27-12',pd.to_datetime('2020-02-27-12')+dt.timedelta(days=2),freq='6H')
DatetimeIndex(['2020-02-27 12:00:00', '2020-02-27 18:00:00',
'2020-02-28 00:00:00', '2020-02-28 06:00:00',
'2020-02-28 12:00:00', '2020-02-28 18:00:00',
'2020-02-29 00:00:00', '2020-02-29 06:00:00',
'2020-02-29 12:00:00'],
dtype='datetime64[ns]', freq='6H')
len(leap)
9
One of the most common approaches to avoiding leap days in this format is to simply remove them from the list.
leap=leap[(leap.day != 29) | (leap.month != 2)]
len(leap)
6
This works fine if I just want to remove the leap day and don't care about the specific length of the list.
Let's do the same exercise for a non-leap year.
leap=pd.date_range('2021-02-27-12',pd.to_datetime('2021-02-27-12')+dt.timedelta(days=2),freq='6H')
DatetimeIndex(['2021-02-27 12:00:00', '2021-02-27 18:00:00',
'2021-02-28 00:00:00', '2021-02-28 06:00:00',
'2021-02-28 12:00:00', '2021-02-28 18:00:00',
'2021-03-01 00:00:00', '2021-03-01 06:00:00',
'2021-03-01 12:00:00'],
dtype='datetime64[ns]', freq='6H')
len(leap)
9
Naturally, the first two have the same length. However, when we remove the leap dates from the first list we can now see that the lengths are different, as 6 =/ 9.
This leads to the ultimate question: how can I create a pandas date range that would take the first list and skip over the leap days and go straight to March, keeping the length of the list at 9?
For context, I am indexing geospatial (3D) data using a centered date approach. For example, if I want to look at data at some point on the globe on Jan 5, I analyze the data 2 days before and after Jan 5 (Jan 3-7). In doing this approach over a long period of time (>30 years) I get a better climatological sense of the variable I am analyzing. To do this indexing I am looping over dates and using the pandas date range approach described above. This is the loop I am using to approach a problem in indexing geospatial (3D) data:
times=pd.date_range('1979-09-01','1980-04-30-18', freq='6H')
final_times = times[(times.day != 29) | (times.month != 2)]
years=np.arange(1979,2020,1)
for i in final_times:
print(i)
times_list=[]
for j in years:
times_forward=pd.date_range(i.replace(year=j),i.replace(year=j)+dt.timedelta(days=2), freq='6H')
times_back=pd.date_range(i.replace(year=j)-dt.timedelta(days=2),i.replace(year=j)-dt.timedelta(hours=6), freq='6H')
total_times=times_forward.union(times_back)
times_list.append(total_times)
combined_times=pd.DatetimeIndex([item for sublist in times_list for item in sublist]).sort_values()
When running this code as is the date lists that surround the leap day are shorter in length than those that are not near the leap day.