pandas.date_range() generates a sequence of dates or timestamps and returns them as a DatetimeIndex. We can control the starting date, ending date, number of periods, frequency, timezone and whether the boundary dates are included.
pd.date_range(), not DataFrame.date_range(). The function belongs directly to Pandas and returns a DatetimeIndex.pd.date_range(
start=None,
end=None,
periods=None,
freq=None,
tz=None,
normalize=False,
name=None,
inclusive='both',
unit=None
)
| Parameter | Purpose |
|---|---|
start | Starting date or timestamp. |
end | Ending date or timestamp. |
periods | Number of timestamps to generate. |
freq | Frequency such as day, hour, month start or month end. |
tz | Timezone of the resulting DatetimeIndex. |
normalize | Normalize start and end timestamps to midnight before generating the range. |
name | Name assigned to the resulting DatetimeIndex. |
inclusive | Control whether start and end boundaries are included. |
unit | Set the datetime resolution such as seconds, milliseconds, microseconds or nanoseconds. |
Common valid combinations are:
start + end
start + periods
end + periods
start + end + periods
start + periods + freq
end + periods + freq
start + end + freq
When start and end are supplied without periods, the usual default frequency is one calendar day.
import pandas as pd
dates=pd.date_range(
start='2020-04-20',
end='2020-04-27'
)
print(dates)
Output
DatetimeIndex(['2020-04-20', '2020-04-21', '2020-04-22', '2020-04-23',
'2020-04-24', '2020-04-25', '2020-04-26', '2020-04-27'],
dtype='datetime64[us]', freq='D')
The default frequency is daily, represented by D. Both the starting and ending dates are included by default.
datetime64[us] or datetime64[ns] can differ between Pandas versions and depending on the supplied values. The generated dates remain the important part of the result.Use periods to specify how many timestamps should be generated.
import pandas as pd
dates=pd.date_range(
start='2026-09-01',
periods=5
)
print(dates)
Output
DatetimeIndex(['2026-09-01', '2026-09-02', '2026-09-03',
'2026-09-04', '2026-09-05'],
dtype='datetime64[us]', freq='D')
dates=pd.date_range(
end='2026-09-05',
periods=5
)
This generates five daily dates ending on 5 September 2026.
If start, end and periods are supplied without a frequency, Pandas creates evenly spaced timestamps between the two boundaries.
dates=pd.date_range(
start='2020-04-20',
end='2020-04-27',
periods=3
)
print(dates)
Output
DatetimeIndex(['2020-04-20 00:00:00',
'2020-04-23 12:00:00',
'2020-04-27 00:00:00'],
dtype='datetime64[us]', freq=None)
The timestamps are evenly distributed between the start and end values. They are not automatically restricted to complete days.
The freq parameter determines the distance between consecutive timestamps.
dates=pd.date_range(
start='2026-09-01',
periods=5,
freq='D'
)
Common frequency aliases include:
| Alias | Frequency |
|---|---|
D | Calendar day |
B | Business day |
W | Week |
MS | Month start |
ME | Month end |
QS | Quarter start |
QE | Quarter end |
YS | Year start |
YE | Year end |
h | Hour |
min | Minute |
s | Second |
See the Pandas frequency aliases section for more date and time frequencies.
dates=pd.date_range(
start='2026-09-01',
periods=5,
freq='D'
)
dates=pd.date_range(
start='2026-09-01',
periods=5,
freq='3D'
)
print(dates)
Output
DatetimeIndex(['2026-09-01', '2026-09-04', '2026-09-07',
'2026-09-10', '2026-09-13'],
dtype='datetime64[us]', freq='3D')
dates=pd.date_range(
start='2026-09-01',
periods=4,
freq='3D6h'
)
Each timestamp is 3 days and 6 hours after the previous one.
Use B to generate standard business days. Saturdays and Sundays are skipped.
import pandas as pd
dates=pd.date_range(
start='2026-09-04',
periods=5,
freq='B'
)
print(dates)
Output
DatetimeIndex(['2026-09-04', '2026-09-07', '2026-09-08',
'2026-09-09', '2026-09-10'],
dtype='datetime64[us]', freq='B')
This standard business-day frequency excludes weekends. It does not automatically know every country's public holidays.
dates=pd.date_range(
start='2026-01-01',
periods=6,
freq='MS'
)
print(dates)
Output
DatetimeIndex(['2026-01-01', '2026-02-01', '2026-03-01',
'2026-04-01', '2026-05-01', '2026-06-01'],
dtype='datetime64[us]', freq='MS')
dates=pd.date_range(
start='2026-01-01',
periods=6,
freq='ME'
)
print(dates)
Output
DatetimeIndex(['2026-01-31', '2026-02-28', '2026-03-31',
'2026-04-30', '2026-05-31', '2026-06-30'],
dtype='datetime64[us]', freq='ME')
ME for month end. Older tutorials may show M, but the old month-end alias was removed in Pandas 3.0.Use YE for year end. An ending month can also be specified.
dates=pd.date_range(
start='2010-04-20',
end='2020-04-27',
freq='YE-FEB'
)
print(dates)
Output
DatetimeIndex(['2011-02-28', '2012-02-29', '2013-02-28',
'2014-02-28', '2015-02-28', '2016-02-29',
'2017-02-28', '2018-02-28', '2019-02-28',
'2020-02-29'],
dtype='datetime64[us]', freq='YE-FEB')
The leap-year dates show 29 February where applicable.
A-FEB. Current Pandas uses the year-end alias YE-FEB.dates=pd.date_range(
start='2026-09-05 09:00',
periods=5,
freq='h'
)
print(dates)
Output
DatetimeIndex(['2026-09-05 09:00:00', '2026-09-05 10:00:00',
'2026-09-05 11:00:00', '2026-09-05 12:00:00',
'2026-09-05 13:00:00'],
dtype='datetime64[us]', freq='h')
dates=pd.date_range(
start='2026-09-05 00:00',
periods=5,
freq='5h30min'
)
print(dates)
Output
DatetimeIndex(['2026-09-05 00:00:00', '2026-09-05 05:30:00',
'2026-09-05 11:00:00', '2026-09-05 16:30:00',
'2026-09-05 22:00:00'],
dtype='datetime64[us]', freq='330min')
dates=pd.date_range(
start='2026-09-05 10:00',
periods=5,
freq='min'
)
dates=pd.date_range(
start='2026-09-05 10:00',
periods=5,
freq='s'
)
h for hours and min for minutes. Older examples using H and T are no longer suitable for current Pandas.Timestamp.today() can supply the current local date and time.
import pandas as pd
today=pd.Timestamp.today().normalize()
dates=pd.date_range(
end=today,
periods=10,
freq='D'
)
print(dates)
This creates exactly ten dates ending with today. Using normalize() changes the current timestamp to midnight before the range is generated.
import pandas as pd
now=pd.Timestamp.now()
dates=pd.date_range(
start=now,
periods=5,
freq='h'
)
print(dates)
The actual output depends on the time at which the program is run.
date_range() returns a DatetimeIndex. Use tolist() to convert it to a Python list.
import pandas as pd
dates=pd.date_range(
start='2026-09-01',
periods=5
)
date_list=dates.tolist()
print(date_list)
The resulting list contains Pandas Timestamp objects.
date_strings=dates.strftime(
'%Y-%m-%d'
).tolist()
print(date_strings)
Output
['2026-09-01', '2026-09-02', '2026-09-03',
'2026-09-04', '2026-09-05']
The inclusive parameter controls whether the start and end boundaries are included.
The available values are:
'both'
'left'
'right'
'neither'
dates=pd.date_range(
start='2026-09-01',
end='2026-09-05',
inclusive='both'
)
Output
2026-09-01
2026-09-02
2026-09-03
2026-09-04
2026-09-05
dates=pd.date_range(
start='2026-09-01',
end='2026-09-05',
inclusive='right'
)
Output
2026-09-02
2026-09-03
2026-09-04
2026-09-05
dates=pd.date_range(
start='2026-09-01',
end='2026-09-05',
inclusive='left'
)
Output
2026-09-01
2026-09-02
2026-09-03
2026-09-04
dates=pd.date_range(
start='2026-09-01',
end='2026-09-05',
inclusive='neither'
)
Output
2026-09-02
2026-09-03
2026-09-04
closed='left' or closed='right'. Use inclusive with current Pandas.With normalize=True, the start and end values are normalized to midnight before the date range is generated.
import pandas as pd
dates=pd.date_range(
start='2026-09-05 14:35:20',
periods=3,
freq='D',
normalize=True
)
print(dates)
Output
DatetimeIndex(['2026-09-05', '2026-09-06', '2026-09-07'],
dtype='datetime64[us]', freq='D')
Without normalization, the time 14:35:20 would be retained in each generated timestamp.
The tz parameter creates a timezone-aware DatetimeIndex.
import pandas as pd
dates=pd.date_range(
start='2026-09-05 09:00',
periods=3,
freq='4h',
tz='Asia/Kolkata'
)
print(dates)
Output
DatetimeIndex(['2026-09-05 09:00:00+05:30',
'2026-09-05 13:00:00+05:30',
'2026-09-05 17:00:00+05:30'],
dtype='datetime64[us, Asia/Kolkata]', freq='4h')
The name parameter assigns a name to the resulting DatetimeIndex.
dates=pd.date_range(
start='2026-09-01',
periods=3,
name='report_date'
)
print(dates.name)
Output
report_date
The name parameter does not convert the result into a DataFrame. The result remains a DatetimeIndex.
The unit parameter can request a particular datetime resolution. Supported values include seconds, milliseconds, microseconds and nanoseconds.
dates=pd.date_range(
start='2026-09-05 10:00:00',
periods=3,
freq='h',
unit='s'
)
print(dates.dtype)
Output
datetime64[s]
For anchored frequencies such as month start or month end, the starting value itself may not be a valid timestamp for that frequency.
For example:
dates=pd.date_range(
start='2026-01-15',
periods=3,
freq='MS'
)
print(dates)
Output
DatetimeIndex(['2026-02-01', '2026-03-01', '2026-04-01'],
dtype='datetime64[us]', freq='MS')
15 January is not a month-start boundary, so the first valid MS timestamp is 1 February.
Similarly, with ME, Pandas moves to the next valid month-end timestamp when necessary.
Several older frequency aliases have changed. When writing new code, prefer the current forms below.
| Current Alias | Meaning | Older Alias to Avoid |
|---|---|---|
h | Hour | H |
min | Minute | T |
ME | Month end | M |
QE | Quarter end | Q |
YE | Year end | Y |
YE-FEB | Year ending in February | A-FEB |
Aliases such as D, B, W, MS, YS, s, ms, us and ns continue to represent their corresponding frequencies.
Incorrect:
df.date_range(...)
Correct:
pd.date_range(...)
For current Pandas, avoid old code such as:
freq='H'
freq='T'
freq='M'
freq='A-FEB'
Use:
freq='h'
freq='min'
freq='ME'
freq='YE-FEB'
Old:
closed='right'
Current:
inclusive='right'
periods means the number of generated timestamps. Their distance depends on freq.
pd.date_range(
start='2026-09-01',
periods=3,
freq='ME'
)
This generates three month-end timestamps, not three days.
The function determines the range from combinations of start, end, periods and freq. Do not try to independently fix all four values when they conflict.
For frequencies such as MS or ME, the first result must be a valid boundary for that frequency.
pd.date_range() creates a DatetimeIndex.start and end to define date boundaries.periods to control how many timestamps are generated.freq to control the distance between timestamps.D generates calendar days and B standard business days.MS for month start and ME for month end.YS for year start and YE for year end.h for hours and min for minutes.5h30min.inclusive controls whether start and end boundaries are included.normalize=True resets the start and end times to midnight before generating the range.tz creates a timezone-aware DatetimeIndex.name assigns a name to the DatetimeIndex.unit controls datetime resolution where supported.tolist() converts the DatetimeIndex to a Python list.MS and ME start from the next valid boundary when necessary.H, T, M, Y and A-FEB should not be used in current Pandas date_range() examples.Author & Instructor at plus2net
I write and maintain practical tutorials on Python, PHP, SQL, JavaScript, HTML, jQuery, and web development at plus2net. The tutorials focus on clear explanations, working examples, and code that readers can test and adapt while learning.