Updated On : Sep-07,2022 Time Investment : ~20 mins

Dates, Timestamps, Timedeltas, Periods & Time Zone Handling in Python using Pandas

Many real-world datasets related to fields like finance, geography, earthquakes, healthcare, etc are time series data.

Properly interpreting and handling time-series data requires good knowledge of generating properly formatted datetime related columns.

Python library Pandas provides a list of tools that helps us convert data to proper datetime format, generate a new range of datetime, and many other datetime manipulation functions.

> What Can You Learn From This Article?

As a part of this article, we have explained various Pandas functions to work with dates, timestamps, time deltas, periods, and time zones. We have explained how to create date ranges, timestamps, time deltas, time delta ranges, periods, and period ranges with simple examples. We even explained how to modify them by adding / subtracting time deltas from them. Apart from this, we have covered in detail how to add and modify time zone of time series data.

Below, we have listed important sections of tutorial to give an overview of the material covered.

Important Sections Of Tutorial

  1. Date Ranges
    • Create Date Ranges
    • How to Filter Date Range?
    • How to Convert Strings to Date Times using Pandas "to_datetime()" Function?
  2. Timestamps
    • Create Timestamps
    • Adding / Subtracting Time Stamps
  3. Time Deltas
    • Create Time Deltas
    • Adding / Subtracting Time Deltas
    • Add / Subtract Time Delta From Time Stamps
    • Add / Subtract Time Delta From Date Ranges
  4. Time Delta Ranges
    • Create Time Delta Ranges
    • Move Time Delta Ranges By Adding / Subtracting Time Delta
    • How to Convert Strings to Timedeltas using Pandas "to_timedelta()" Function?
  5. Period (TimeSpan)
    • Create Periods
    • Move Periods By Adding / Subtracting Time Delta
  6. Period Ranges
    • Create Period Ranges
    • Move Period Ranges By Adding / Subtracting Time Delta
    • How to Filter Period Range?
    • Convert Datetime Range to Period Range using DataFrame "to_period()" Function
  7. Time Zones
    • Add Time Zone to Pandas Series / DataFrame using "tz_localize()"
    • Convert Time Zone of Pandas Series / DataFrame using "tz_convert()"

1. Create Date Ranges using Pandas "date_range()" Function

Dates, Timestamps, Timedeltas Periods & Time Zone Handling in Python using Pandas

Pandas provide very helpful function date_range() which lets us generate a range of fixed frequency dates. It takes arguments like start, end, periods, and freq to generate a range of dates though all of the parameters are not compulsory. We'll explain how to generate various date ranges below with different frequencies with various examples.

import pandas as pd
import numpy as np

We can create a list of date ranges by setting start, periods and freq parameters or start, end and freq parameters. If we don't provide freq parameter value then the default value is D which refers to 1 day. It returns a list of dates as DatetimeIndex series. We'll create date ranges by setting various strings of date formats to check which formats work with pandas date_range() function.

pd.date_range(start="2020 Jan 1", periods=5)
DatetimeIndex(['2020-01-01', '2020-01-02', '2020-01-03', '2020-01-04',
               '2020-01-05'],
              dtype='datetime64[ns]', freq='D')
pd.date_range(start="2020 January 1", periods=5)
DatetimeIndex(['2020-01-01', '2020-01-02', '2020-01-03', '2020-01-04',
               '2020-01-05'],
              dtype='datetime64[ns]', freq='D')
pd.date_range(start="1 Jan 2020", periods=5)
DatetimeIndex(['2020-01-01', '2020-01-02', '2020-01-03', '2020-01-04',
               '2020-01-05'],
              dtype='datetime64[ns]', freq='D')
pd.date_range(start="Jan 1, 2020", periods=5)
DatetimeIndex(['2020-01-01', '2020-01-02', '2020-01-03', '2020-01-04',
               '2020-01-05'],
              dtype='datetime64[ns]', freq='D')
pd.date_range(start="2020-7-1", periods=5)
DatetimeIndex(['2020-07-01', '2020-07-02', '2020-07-03', '2020-07-04',
               '2020-07-05'],
              dtype='datetime64[ns]', freq='D')
pd.date_range(start="2020/7/1", periods=5)
DatetimeIndex(['2020-07-01', '2020-07-02', '2020-07-03', '2020-07-04',
               '2020-07-05'],
              dtype='datetime64[ns]', freq='D')

We can see that all of the above examples generated 5 days from the start date given. We can see that pandas can handle various date formats as well.

pd.date_range(start="1-7-2020", periods=5)
DatetimeIndex(['2020-01-07', '2020-01-08', '2020-01-09', '2020-01-10',
               '2020-01-11'],
              dtype='datetime64[ns]', freq='D')
pd.date_range(start="7-1-2020", periods=5)
DatetimeIndex(['2020-07-01', '2020-07-02', '2020-07-03', '2020-07-04',
               '2020-07-05'],
              dtype='datetime64[ns]', freq='D')

We can see from the above two examples that the first one did not generate results we expected. The reason behind this is that if you provide year last then pandas assume that first value is month then day.

Below we have given a few more examples where we generate date ranges by setting start, end, and freq parameters. Pandas uses D for a day, H for an hour, S for seconds, T/min for minutes, B for business days, M for month-end, MS for month start and ms/L for milliseconds.

pd.date_range(start="1-1-2020", end="1-5-2020", freq="D")
DatetimeIndex(['2020-01-01', '2020-01-02', '2020-01-03', '2020-01-04',
               '2020-01-05'],
              dtype='datetime64[ns]', freq='D')
pd.date_range(start="1-1-2020", end="1-10-2020", freq="B")
DatetimeIndex(['2020-01-01', '2020-01-02', '2020-01-03', '2020-01-06',
               '2020-01-07', '2020-01-08', '2020-01-09', '2020-01-10'],
              dtype='datetime64[ns]', freq='B')
pd.date_range(start="1-1-2020 00:00", end="1-1-2020 5:00", freq="H")
DatetimeIndex(['2020-01-01 00:00:00', '2020-01-01 01:00:00',
               '2020-01-01 02:00:00', '2020-01-01 03:00:00',
               '2020-01-01 04:00:00', '2020-01-01 05:00:00'],
              dtype='datetime64[ns]', freq='H')
pd.date_range(start="1-1-2020 00:00", end="1-1-2020 00:05", freq="30S")
DatetimeIndex(['2020-01-01 00:00:00', '2020-01-01 00:00:30',
               '2020-01-01 00:01:00', '2020-01-01 00:01:30',
               '2020-01-01 00:02:00', '2020-01-01 00:02:30',
               '2020-01-01 00:03:00', '2020-01-01 00:03:30',
               '2020-01-01 00:04:00', '2020-01-01 00:04:30',
               '2020-01-01 00:05:00'],
              dtype='datetime64[ns]', freq='30S')
print(pd.date_range(start="1-1-2020 00:00", end="1-1-2020 00:05", freq="T"))
print(pd.date_range(start="1-1-2020 00:00", end="1-1-2020 00:05", freq="2min"))
DatetimeIndex(['2020-01-01 00:00:00', '2020-01-01 00:01:00',
               '2020-01-01 00:02:00', '2020-01-01 00:03:00',
               '2020-01-01 00:04:00', '2020-01-01 00:05:00'],
              dtype='datetime64[ns]', freq='T')
DatetimeIndex(['2020-01-01 00:00:00', '2020-01-01 00:02:00',
               '2020-01-01 00:04:00'],
              dtype='datetime64[ns]', freq='2T')
pd.date_range(start="1-1-2020", periods=5, freq="M")
DatetimeIndex(['2020-01-31', '2020-02-29', '2020-03-31', '2020-04-30',
               '2020-05-31'],
              dtype='datetime64[ns]', freq='M')
pd.date_range(start="1-1-2020", periods=5, freq="MS")
DatetimeIndex(['2020-01-01', '2020-02-01', '2020-03-01', '2020-04-01',
               '2020-05-01'],
              dtype='datetime64[ns]', freq='MS')
print(pd.date_range(start="1-1-2020", periods=5, freq="100ms"))
print(pd.date_range(start="1-1-2020", end="1-1-2020 00:00:00.500000", freq="100L"))
print(pd.date_range(start="1-1-2020", end="1-1-2020 00:00:01", freq="100L"))
DatetimeIndex([       '2020-01-01 00:00:00', '2020-01-01 00:00:00.100000',
               '2020-01-01 00:00:00.200000', '2020-01-01 00:00:00.300000',
               '2020-01-01 00:00:00.400000'],
              dtype='datetime64[ns]', freq='100L')
DatetimeIndex([       '2020-01-01 00:00:00', '2020-01-01 00:00:00.100000',
               '2020-01-01 00:00:00.200000', '2020-01-01 00:00:00.300000',
               '2020-01-01 00:00:00.400000', '2020-01-01 00:00:00.500000'],
              dtype='datetime64[ns]', freq='100L')
DatetimeIndex([       '2020-01-01 00:00:00', '2020-01-01 00:00:00.100000',
               '2020-01-01 00:00:00.200000', '2020-01-01 00:00:00.300000',
               '2020-01-01 00:00:00.400000', '2020-01-01 00:00:00.500000',
               '2020-01-01 00:00:00.600000', '2020-01-01 00:00:00.700000',
               '2020-01-01 00:00:00.800000', '2020-01-01 00:00:00.900000',
                      '2020-01-01 00:00:01'],
              dtype='datetime64[ns]', freq='100L')
pd.date_range(start="1-1-2020", end="1-10-2020", freq="1D4H")
DatetimeIndex(['2020-01-01 00:00:00', '2020-01-02 04:00:00',
               '2020-01-03 08:00:00', '2020-01-04 12:00:00',
               '2020-01-05 16:00:00', '2020-01-06 20:00:00',
               '2020-01-08 00:00:00', '2020-01-09 04:00:00'],
              dtype='datetime64[ns]', freq='28H')
pd.date_range(start="1-1-2020", end="1-10-2020", freq="1D4H30S")
DatetimeIndex(['2020-01-01 00:00:00', '2020-01-02 04:00:30',
               '2020-01-03 08:01:00', '2020-01-04 12:01:30',
               '2020-01-05 16:02:00', '2020-01-06 20:02:30',
               '2020-01-08 00:03:00', '2020-01-09 04:03:30'],
              dtype='datetime64[ns]', freq='100830S')

1.1 Filter Date Range

We can also subscript series based on various combinations as well. We can pass various date time formats to filter a list of ranges. We'll explain it below with few examples.

rng = pd.date_range(start="1-1-2020", periods=6, freq="D")
ser = pd.Series(data=range(6), index=rng)
ser
2020-01-01    0
2020-01-02    1
2020-01-03    2
2020-01-04    3
2020-01-05    4
2020-01-06    5
Freq: D, dtype: int64
ser["1/1/2020":"1/4/2020"]
2020-01-01    0
2020-01-02    1
2020-01-03    2
2020-01-04    3
Freq: D, dtype: int64
ser["1/5/2020":]
2020-01-05    4
2020-01-06    5
Freq: D, dtype: int64
from datetime import datetime

ser[datetime(2020,1,3):]
2020-01-03    2
2020-01-04    3
2020-01-05    4
2020-01-06    5
Freq: D, dtype: int64

We can also pass partial indexing like only year and month or only year and it'll filter all values matching those combinations. We have explained it as well below with few examples.

ser["2020-1":]
2020-01-01    0
2020-01-02    1
2020-01-03    2
2020-01-04    3
2020-01-05    4
2020-01-06    5
Freq: D, dtype: int64
ser["2020":]
2020-01-01    0
2020-01-02    1
2020-01-03    2
2020-01-04    3
2020-01-05    4
2020-01-06    5
Freq: D, dtype: int64

1.2 How to Convert List Of Strings to Date Time using Pandas "to_datetime()" Function?

Pandas also provide list of functions like to_datetime() which can be used to convert list of strings to pandas date time formatted list. It also accepts format which you can use to specify date-time format if it fails to recognize exact time format by itself.

pd.to_datetime(["1-1-2020","1-2-2020", "1-3-2020"])
DatetimeIndex(['2020-01-01', '2020-01-02', '2020-01-03'], dtype='datetime64[ns]', freq=None)
pd.to_datetime(["1 Jan 2020","2 Jan 2020", "3 Jan 2020"], )
DatetimeIndex(['2020-01-01', '2020-01-02', '2020-01-03'], dtype='datetime64[ns]', freq=None)
pd.to_datetime(["2020/1/1","2020/1/2", "2020/1/3"])
DatetimeIndex(['2020-01-01', '2020-01-02', '2020-01-03'], dtype='datetime64[ns]', freq=None)

Below examples explain when you will want to use format attribute of to_datetime() method when it's not creating proper date time.

pd.to_datetime(["2020/1/1","2020/2/1", "2020/3/1"])
DatetimeIndex(['2020-01-01', '2020-02-01', '2020-03-01'], dtype='datetime64[ns]', freq=None)
pd.to_datetime(["2020/1/1","2020/2/1", "2020/3/1"], format="%Y/%d/%m")
DatetimeIndex(['2020-01-01', '2020-01-02', '2020-01-03'], dtype='datetime64[ns]', freq=None)

2. Create Timestamps using Pandas "Timestamp()" Function

Dates, Timestamps, Timedeltas Periods & Time Zone Handling in Python using Pandas

Timestamp function lets us create an object of a particular point in time. We'll need it to represent a value that changes with different time stamps. We can create a timestamp by setting various date formats as explained by the below examples. It lets us pass values till nanoseconds.

pd.Timestamp("Jan 2020")
Timestamp('2020-01-01 00:00:00')
pd.Timestamp("12 Jan 2020")
Timestamp('2020-01-12 00:00:00')
pd.Timestamp("12 Jan 2020 20:20")
Timestamp('2020-01-12 20:20:00')
pd.Timestamp("12 Jan 2020 20:20:20.100")
Timestamp('2020-01-12 20:20:20.100000')
pd.Timestamp("12 Jan 2020 20:20:20.200000")
Timestamp('2020-01-12 20:20:20.200000')
pd.Timestamp("12 Jan 2020 20:20:20.000200000")
Timestamp('2020-01-12 20:20:20.000200')

We can create timestamps by setting year, month, day, hour, minute, second, microsecond and nanosecond separately as well. We'll explain it below with few examples.

pd.Timestamp(year=2020, month=1, day=1, hour=10, minute=10, second=30, microsecond=100)
Timestamp('2020-01-01 10:10:30.000100')
pd.Timestamp(year=2020, month=1, day=1, hour=10, minute=10, second=30, microsecond=100, nanosecond=100)
Timestamp('2020-01-01 10:10:30.000100100')

2.1 Adding / Subtracting Time Stamps

We can add one timestamp to another timestamp as well as subtract one timestamp to another timestamp to move values by that much amount of time. We have explained it below with few examples to make the concept clear. The output of time stamp addition and subtraction is time delta which we have explained in the next section.

t1 = pd.Timestamp("12 Jan 2020 12:12:45")
t2 = pd.Timestamp("12 Jan 2020 13:14:20")

(t2 -t1), (t1 - t2)
(Timedelta('0 days 01:01:35'), Timedelta('-1 days +22:58:25'))
t1 = pd.Timestamp("12 Jan 2020")
t2 = pd.Timestamp("13 Jan 2020")

(t2 - t1),
(Timedelta('1 days 00:00:00'),)

3. Create Time Deltas using Pandas "Timedelta()" Function

Dates, Timestamps, Timedeltas Periods & Time Zone Handling in Python using Pandas

Timedelta function lets us create a difference between the two timestamps. We might need this function to analyze how far 2 date/time values are from each other. We'll explain below with a few examples of how to create time deltas using pandas. We can create time deltas consisting of days and days with hour:min:seconds: nanoseconds. If we don't provide value for a particular part then its default value will be assumed.

pd.Timedelta("1 days")
Timedelta('1 days 00:00:00')
pd.Timedelta("1 days 10:00:00")
Timedelta('1 days 10:00:00')
pd.Timedelta("1 days 10:10:00")
Timedelta('1 days 10:10:00')
pd.Timedelta("1 days 10:10:10")
Timedelta('1 days 10:10:10')
pd.Timedelta("1 days 10:10:10.100000")
Timedelta('1 days 10:10:10.100000')

3.1 Adding / Subtracting Time Deltas

We can perform addition and subtraction functions on time deltas to get combined time delta and time delta difference respectively. We'll explain it with various examples.

t1 = pd.Timedelta("1 days 10:10:10.100000")
t2 = pd.Timedelta("2 days 10:10:10.100000")

t2 - t1
Timedelta('1 days 00:00:00')
t1 + t2
Timedelta('3 days 20:20:20.200000')

3.2 Add / Subtract Time Delta From Time Stamps

Time deltas as very useful when you want to move your timestamps by a particular time delta. We can add and subtract time deltas from timestamp to get dates moved. We have explained it below with few examples.

pd.Timestamp("12 Jan 2020") + pd.Timedelta("1 days")
Timestamp('2020-01-13 00:00:00')
pd.Timestamp("Jan 2020") + pd.Timedelta("1 days")
Timestamp('2020-01-02 00:00:00')
pd.Timestamp("12 Jan 2020") - pd.Timedelta("1 days")
Timestamp('2020-01-11 00:00:00')
pd.Timestamp("12 Jan 2020") + pd.Timedelta("4H")
Timestamp('2020-01-12 04:00:00')
pd.Timestamp("12 Jan 2020") + pd.Timedelta("30min")
Timestamp('2020-01-12 00:30:00')
pd.Timestamp("12 Jan 2020") + pd.Timedelta("30 seconds")
Timestamp('2020-01-12 00:00:30')

3.3 Add / Subtract Time Delta From Date Ranges

We can add and subtract time deltas from date ranges as well and it'll move all values of date ranges by that much time delta. We'll explain it below with few examples.

pd.date_range(start="1-1-2020", end="1-5-2020", freq="D") + pd.Timedelta("1 days")
DatetimeIndex(['2020-01-02', '2020-01-03', '2020-01-04', '2020-01-05',
               '2020-01-06'],
              dtype='datetime64[ns]', freq='D')
pd.date_range(start="1-1-2020", end="1-5-2020", freq="D") - pd.Timedelta("1 days")
DatetimeIndex(['2019-12-31', '2020-01-01', '2020-01-02', '2020-01-03',
               '2020-01-04'],
              dtype='datetime64[ns]', freq='D')
pd.date_range(start="1-1-2020", end="1-5-2020", freq="D") + pd.Timedelta("4H30T30S")
DatetimeIndex(['2020-01-01 04:30:30', '2020-01-02 04:30:30',
               '2020-01-03 04:30:30', '2020-01-04 04:30:30',
               '2020-01-05 04:30:30'],
              dtype='datetime64[ns]', freq='D')

4. Create Time Delta Ranges using Pandas "timedelta_range()" Function

Pandas provides function named timedelta_range() just like date_range() and period_range() to create range of time deltas. It lets us create list of time deltas by following almost the same format as date_range() and period_range(). We have explained below few examples of timedelta_range() usage.

pd.timedelta_range(start="1 day", periods=10)
TimedeltaIndex([ '1 days',  '2 days',  '3 days',  '4 days',  '5 days',
                 '6 days',  '7 days',  '8 days',  '9 days', '10 days'],
               dtype='timedelta64[ns]', freq='D')
pd.timedelta_range(start="1 day", periods=10, freq="30D")
TimedeltaIndex([  '1 days',  '31 days',  '61 days',  '91 days', '121 days',
                '151 days', '181 days', '211 days', '241 days', '271 days'],
               dtype='timedelta64[ns]', freq='30D')
pd.timedelta_range(start="1 day", periods=10, freq="10H")
TimedeltaIndex(['1 days 00:00:00', '1 days 10:00:00', '1 days 20:00:00',
                '2 days 06:00:00', '2 days 16:00:00', '3 days 02:00:00',
                '3 days 12:00:00', '3 days 22:00:00', '4 days 08:00:00',
                '4 days 18:00:00'],
               dtype='timedelta64[ns]', freq='10H')
pd.timedelta_range(start="1 day", end="2 day", freq="4H")
TimedeltaIndex(['1 days 00:00:00', '1 days 04:00:00', '1 days 08:00:00',
                '1 days 12:00:00', '1 days 16:00:00', '1 days 20:00:00',
                '2 days 00:00:00'],
               dtype='timedelta64[ns]', freq='4H')
pd.timedelta_range(start="1 hour", end="2 hour", freq="10min")
TimedeltaIndex(['01:00:00', '01:10:00', '01:20:00', '01:30:00', '01:40:00',
                '01:50:00', '02:00:00'],
               dtype='timedelta64[ns]', freq='10T')
pd.timedelta_range(start="1 min", end="5 min", freq="T")
TimedeltaIndex(['00:01:00', '00:02:00', '00:03:00', '00:04:00', '00:05:00'], dtype='timedelta64[ns]', freq='T')
pd.timedelta_range(start="1 day", periods=10) + pd.Timedelta("1 days")
TimedeltaIndex([ '2 days',  '3 days',  '4 days',  '5 days',  '6 days',
                 '7 days',  '8 days',  '9 days', '10 days', '11 days'],
               dtype='timedelta64[ns]', freq='D')

4.1 Move Time Delta Ranges By Adding / Subtracting Time Delta

We can move time delta ranges by adding or subtracting time delta from it. We have explained it below with few examples.

pd.timedelta_range(start="1 day", periods=10) - pd.Timedelta("1 days")
TimedeltaIndex(['0 days', '1 days', '2 days', '3 days', '4 days', '5 days',
                '6 days', '7 days', '8 days', '9 days'],
               dtype='timedelta64[ns]', freq='D')
pd.timedelta_range(start="1 day", periods=10) + pd.Timedelta("2 days")
TimedeltaIndex([ '3 days',  '4 days',  '5 days',  '6 days',  '7 days',
                 '8 days',  '9 days', '10 days', '11 days', '12 days'],
               dtype='timedelta64[ns]', freq='D')
pd.timedelta_range(start="1 day", periods=10) + pd.Timedelta("2D5H")
TimedeltaIndex([ '3 days 05:00:00',  '4 days 05:00:00',  '5 days 05:00:00',
                 '6 days 05:00:00',  '7 days 05:00:00',  '8 days 05:00:00',
                 '9 days 05:00:00', '10 days 05:00:00', '11 days 05:00:00',
                '12 days 05:00:00'],
               dtype='timedelta64[ns]', freq='D')
pd.timedelta_range(start="1 day", periods=10) + pd.Timedelta("2D5H30min")
TimedeltaIndex([ '3 days 05:30:00',  '4 days 05:30:00',  '5 days 05:30:00',
                 '6 days 05:30:00',  '7 days 05:30:00',  '8 days 05:30:00',
                 '9 days 05:30:00', '10 days 05:30:00', '11 days 05:30:00',
                '12 days 05:30:00'],
               dtype='timedelta64[ns]', freq='D')

4.2 How to Convert List Of Strings to Timedeltas using Pandas "to_timedelta()" Function?

Pandas also provide a function named to_timedelta() which can be used to convert list of strings to time deltas. We can modify these time deltas by adding and subtracting other time deltas.

Below, we have explained few examples explaining how to convert list of strings to time deltas using pandas 'to_timedelta()' function.

pd.to_timedelta(["1 day","2 day", "3 day"])
TimedeltaIndex(['1 days', '2 days', '3 days'], dtype='timedelta64[ns]', freq=None)
pd.to_timedelta(["1 day 6 hour","2 day 6 hour", "3 day 6 hour"])
TimedeltaIndex(['1 days 06:00:00', '2 days 06:00:00', '3 days 06:00:00'], dtype='timedelta64[ns]', freq=None)
pd.to_timedelta(["1 hour","2 hour", "3 hour"])
TimedeltaIndex(['01:00:00', '02:00:00', '03:00:00'], dtype='timedelta64[ns]', freq=None)
pd.to_timedelta(["1 hour 20 min","2 hour 20 min", "3 hour 20 min"])
TimedeltaIndex(['01:20:00', '02:20:00', '03:20:00'], dtype='timedelta64[ns]', freq=None)
pd.to_timedelta(["10 min","20 min", "30 min"])
TimedeltaIndex(['00:10:00', '00:20:00', '00:30:00'], dtype='timedelta64[ns]', freq=None)
pd.to_timedelta(["1 second","2 second", "3 second"])
TimedeltaIndex(['00:00:01', '00:00:02', '00:00:03'], dtype='timedelta64[ns]', freq=None)
pd.to_timedelta(["1 millisecond","2 millisecond", "3 millisecond"])
TimedeltaIndex(['00:00:00.001000', '00:00:00.002000', '00:00:00.003000'], dtype='timedelta64[ns]', freq=None)
pd.to_timedelta(["1 microsecond","2 microsecond", "3 microsecond"])
TimedeltaIndex(['00:00:00.000001', '00:00:00.000002', '00:00:00.000003'], dtype='timedelta64[ns]', freq=None)
pd.to_timedelta(["1 nanosecond","2 nanosecond", "3 nanosecond"])
TimedeltaIndex(['00:00:00.000000', '00:00:00.000000', '00:00:00.000000'], dtype='timedelta64[ns]', freq=None)

4.2.1 Add / Subtract Time Deltas to Create New Time Deltas

pd.to_timedelta(["1 day","2 day", "3 day"]) + pd.to_timedelta(["1 day","2 day", "3 day"])
TimedeltaIndex(['2 days', '4 days', '6 days'], dtype='timedelta64[ns]', freq='2D')
pd.to_timedelta(["1 hour","2 hour", "3 hour"]) + pd.to_timedelta(["10 min","20 min", "30 min"])
TimedeltaIndex(['01:10:00', '02:20:00', '03:30:00'], dtype='timedelta64[ns]', freq='70T')
pd.to_timedelta(["1 day","2 day", "3 day"]) +\
pd.to_timedelta(["1 hour","2 hour", "3 hour"]) +\
pd.to_timedelta(["10 min","20 min", "30 min"])
TimedeltaIndex(['1 days 01:10:00', '2 days 02:20:00', '3 days 03:30:00'], dtype='timedelta64[ns]', freq='1510T')
pd.to_timedelta(["1 hour","2 hour", "3 hour"]) - pd.to_timedelta(["10 min","20 min", "30 min"])
TimedeltaIndex(['00:50:00', '01:40:00', '02:30:00'], dtype='timedelta64[ns]', freq='50T')
pd.to_timedelta(["1 day","2 day", "3 day"]) - pd.to_timedelta(["23 hour","22 hour", "21 hour"])
TimedeltaIndex(['0 days 01:00:00', '1 days 02:00:00', '2 days 03:00:00'], dtype='timedelta64[ns]', freq='25H')

5. Create Period (TimeSpan) using Pandas "Period()" Function

Dates, Timestamps, Timedeltas Periods & Time Zone Handling in Python using Pandas

Pandas provide a Period() function to represent the time span. We'll need periods when we want to represent values that are the same throughout the period and do not change much. Period function lets us pass freq like Timestamp function and if we don't pass it then it'll detect it from date format passed. We'll explain the creation of various periods by various examples below.

pd.Period(value="1-1-2020")
Period('2020-01-01', 'D')
pd.Period("1-2020")
Period('2020-01', 'M')
pd.Period("2020")
Period('2020', 'A-DEC')
pd.Period("1-1-2020 10:00:00")
Period('2020-01-01 10:00:00', 'S')
pd.Period("1-1-2020 10:00")
Period('2020-01-01 10:00', 'T')
pd.Period("1-1-2020 10")
Period('2020-01-01 10:00', 'H')
pd.Period("1-1-2020 10:00:00.100000")
Period('2020-01-01 10:00:00.100', 'L')

5.1 Move Periods By Adding / Subtracting Time Delta

We can add and subtract time deltas from periods as well. We have explained it below with few examples.

pd.Period("1-1-2020 10:10") + pd.Timedelta("1 days")
Period('2020-01-02 10:10', 'T')
pd.Period("1-1-2020 10:10:10") - pd.Timedelta("1 days")
Period('2019-12-31 10:10:10', 'S')
pd.Period("1-1-2020 10") + pd.Timedelta("10H")
Period('2020-01-01 20:00', 'H')
pd.Period("1-1-2020 10") - pd.Timedelta("10H")
Period('2020-01-01 00:00', 'H')

6. Create Period Ranges using Pandas "period_range()" Function

Just like date_range() function, period_range() function lets us generate list of periods. This function has almost all parameters the same as that date_range() function. We have explained various ways to create the period range below.

pd.period_range(start="1-1-2020", periods=5)
PeriodIndex(['2020-01-01', '2020-01-02', '2020-01-03', '2020-01-04',
             '2020-01-05'],
            dtype='period[D]', freq='D')
pd.period_range(start="1-1-2020", periods=5, freq="4H")
PeriodIndex(['2020-01-01 00:00', '2020-01-01 04:00', '2020-01-01 08:00',
             '2020-01-01 12:00', '2020-01-01 16:00'],
            dtype='period[4H]', freq='4H')
pd.period_range(start="1-1-2020", periods=5, freq="M")
PeriodIndex(['2020-01', '2020-02', '2020-03', '2020-04', '2020-05'], dtype='period[M]', freq='M')
pd.period_range(start="1-1-2020", periods=5, freq="T")
PeriodIndex(['2020-01-01 00:00', '2020-01-01 00:01', '2020-01-01 00:02',
             '2020-01-01 00:03', '2020-01-01 00:04'],
            dtype='period[T]', freq='T')
pd.period_range(start="1-1-2020", periods=6, freq="12min")
PeriodIndex(['2020-01-01 00:00', '2020-01-01 00:12', '2020-01-01 00:24',
             '2020-01-01 00:36', '2020-01-01 00:48', '2020-01-01 01:00'],
            dtype='period[12T]', freq='12T')
pd.period_range(start="1-1-2020", periods=4, freq="5S")
PeriodIndex(['2020-01-01 00:00:00', '2020-01-01 00:00:05',
             '2020-01-01 00:00:10', '2020-01-01 00:00:15'],
            dtype='period[5S]', freq='5S')

6.1 Move Period Ranges By Adding / Subtracting Time Delta

We can add and subtract time delta from a list of periods the same way we did with date ranges. It'll move the list of periods by that much time delta amount. We have explained it below with few examples.

pd.period_range(start="1-1-2020", periods=4, freq="5S") + pd.Timedelta("1 days")
PeriodIndex(['2020-01-02 00:00:00', '2020-01-02 00:00:05',
             '2020-01-02 00:00:10', '2020-01-02 00:00:15'],
            dtype='period[5S]', freq='5S')
pd.period_range(start="1-1-2020", periods=4, freq="5S") + pd.Timedelta("5 seconds")
PeriodIndex(['2020-01-01 00:00:05', '2020-01-01 00:00:10',
             '2020-01-01 00:00:15', '2020-01-01 00:00:20'],
            dtype='period[5S]', freq='5S')
pd.period_range(start="1-1-2020", periods=4, freq="5S") + pd.Timedelta("1min")
PeriodIndex(['2020-01-01 00:01:00', '2020-01-01 00:01:05',
             '2020-01-01 00:01:10', '2020-01-01 00:01:15'],
            dtype='period[5S]', freq='5S')

6.2 How to Filter Period Range?

We can also subscript series based on various combinations as well. We can pass various date time formats to filter the list of ranges. We'll explain it below with few examples.

rng = pd.period_range(start="1-1-2020", periods=6, freq="D")
ser = pd.Series(data=range(6), index=rng)
ser
2020-01-01    0
2020-01-02    1
2020-01-03    2
2020-01-04    3
2020-01-05    4
2020-01-06    5
Freq: D, dtype: int64
ser["1/1/2020":"1/4/2020"]
2020-01-01    0
2020-01-02    1
2020-01-03    2
2020-01-04    3
Freq: D, dtype: int64
ser["1/3/2020":]
2020-01-03    2
2020-01-04    3
2020-01-05    4
2020-01-06    5
Freq: D, dtype: int64
from datetime import datetime

ser[datetime(2020,1,3):]
2020-01-03    2
2020-01-04    3
2020-01-05    4
2020-01-06    5
Freq: D, dtype: int64

We can also pass partial indexing like only year and month or only year and it'll filter all values matching those combinations. We have explained it as well below with few examples.

ser["2020-1"]
2020-01-01    0
2020-01-02    1
2020-01-03    2
2020-01-04    3
2020-01-05    4
2020-01-06    5
Freq: D, dtype: int64
ser["2020"]
2020-01-01    0
2020-01-02    1
2020-01-03    2
2020-01-04    3
2020-01-05    4
2020-01-06    5
Freq: D, dtype: int64

6.3 Convert Datetime Range to Period Range using DataFrame "to_period()" Function

data = np.random.randn(5, 5)
date_range = pd.date_range(start="2020 Jan 1", periods=5)

df = pd.DataFrame(data, index=date_range)

df
0 1 2 3 4
2020-01-01 -1.446748 0.330445 -1.324648 0.107889 -2.799933
2020-01-02 -0.148446 0.975899 -2.500117 0.113521 1.027202
2020-01-03 1.042154 -0.829378 1.103656 -0.476558 0.103873
2020-01-04 -0.109266 -0.508841 0.681631 0.212538 1.317936
2020-01-05 0.631357 -0.690396 -0.142200 -0.690300 0.310838
df.index
DatetimeIndex(['2020-01-01', '2020-01-02', '2020-01-03', '2020-01-04',
               '2020-01-05'],
              dtype='datetime64[ns]', freq='D')
df.index.to_period()
PeriodIndex(['2020-01-01', '2020-01-02', '2020-01-03', '2020-01-04',
             '2020-01-05'],
            dtype='period[D]', freq='D')

7. Handle Time Zones in Python using Pandas

Dates, Timestamps, Timedeltas Periods & Time Zone Handling in Python using Pandas

Pandas let us specify timezone when creating date ranges, timestamps, etc. Till now, we have created all date ranges and timestamps without any time stamp set. We'll now explore ways to set timezones and conversion from one timezone to another timezone. We can specify timezone by setting string value to argument tz of date_range() and Timestamp(). Python library pytz maintains a list of all available time zone names.

from pytz import common_timezones, all_timezones

print("Number of Common Timezones : ", len(common_timezones))
print("Number of All Timezones : ", len(all_timezones))
print("Difference between all timezones and common timezones : ", list(set(all_timezones) - set(common_timezones)))
Number of Common Timezones :  439
Number of All Timezones :  594
Difference between all timezones and common timezones :  ['Asia/Ujung_Pandang', 'America/Knox_IN', 'Singapore', 'Asia/Dacca', 'Australia/North', 'ROC', 'Asia/Ashkhabad', 'Pacific/Ponape', 'Asia/Katmandu', 'Etc/GMT-1', 'Brazil/Acre', 'Etc/GMT-6', 'PRC', 'Etc/GMT-10', 'Asia/Harbin', 'Asia/Thimbu', 'Etc/GMT-7', 'Etc/GMT-14', 'Pacific/Samoa', 'US/Samoa', 'Etc/GMT+7', 'Brazil/West', 'Pacific/Truk', 'Turkey', 'Etc/GMT-2', 'MST7MDT', 'EST5EDT', 'CET', 'Asia/Saigon', 'Australia/Victoria', 'Greenwich', 'Australia/Yancowinna', 'US/Michigan', 'Africa/Asmera', 'Australia/South', 'America/Buenos_Aires', 'Asia/Calcutta', 'America/Rosario', 'Navajo', 'Etc/GMT-3', 'US/Aleutian', 'Brazil/DeNoronha', 'Australia/LHI', 'HST', 'Etc/GMT+12', 'MET', 'Asia/Kashgar', 'Etc/GMT-5', 'Portugal', 'Asia/Istanbul', 'W-SU', 'US/Indiana-Starke', 'Canada/Yukon', 'Universal', 'Jamaica', 'Antarctica/South_Pole', 'America/Indianapolis', 'America/Atka', 'Europe/Tiraspol', 'America/Fort_Wayne', 'Etc/GMT-13', 'GMT0', 'Australia/NSW', 'Asia/Tel_Aviv', 'Etc/GMT+4', 'Kwajalein', 'UCT', 'Etc/Zulu', 'America/Cordoba', 'Europe/Nicosia', 'GB', 'Iran', 'America/Mendoza', 'America/Virgin', 'Etc/Greenwich', 'Iceland', 'Mexico/BajaNorte', 'MST', 'GB-Eire', 'Eire', 'Canada/Saskatchewan', 'Australia/Currie', 'Australia/Canberra', 'America/Montreal', 'ROK', 'America/Shiprock', 'Etc/GMT+1', 'Etc/Universal', 'Africa/Timbuktu', 'WET', 'Poland', 'Asia/Chungking', 'Etc/GMT+11', 'Etc/GMT+10', 'America/Coral_Harbour', 'America/Jujuy', 'America/Catamarca', 'Etc/GMT+8', 'GMT+0', 'Hongkong', 'NZ-CHAT', 'Japan', 'EET', 'Israel', 'Etc/GMT-9', 'Etc/UCT', 'Etc/GMT-8', 'Etc/GMT', 'Asia/Macao', 'Chile/EasterIsland', 'Etc/GMT-0', 'GMT-0', 'America/Ensenada', 'Chile/Continental', 'Etc/GMT+0', 'Cuba', 'EST', 'Asia/Chongqing', 'Pacific/Johnston', 'Mexico/BajaSur', 'Etc/GMT0', 'US/East-Indiana', 'NZ', 'Etc/GMT-12', 'Europe/Belfast', 'Etc/GMT+6', 'Atlantic/Jan_Mayen', 'Australia/ACT', 'Brazil/East', 'Etc/GMT+5', 'Etc/UTC', 'Etc/GMT+9', 'America/Porto_Acre', 'Australia/Queensland', 'Pacific/Yap', 'Etc/GMT+3', 'Australia/Tasmania', 'America/Godthab', 'Etc/GMT-11', 'America/Argentina/ComodRivadavia', 'PST8PDT', 'Atlantic/Faeroe', 'Egypt', 'Asia/Rangoon', 'Libya', 'America/Santa_Isabel', 'Etc/GMT+2', 'Mexico/General', 'Pacific/Enderbury', 'Asia/Ulan_Bator', 'Zulu', 'CST6CDT', 'America/Louisville', 'Australia/West', 'Etc/GMT-4']
rng = pd.date_range(start="1-1-2020", periods=5, freq="M")
rng.tz
rng = pd.date_range(start="1-1-2020", periods=5, freq="M", tz="US/Eastern")
rng.tz
<DstTzInfo 'US/Eastern' LMT-1 day, 19:04:00 STD>
ts = pd.Timestamp("1-1-2020")
print(ts)
ts.tz
2020-01-01 00:00:00
ts = pd.Timestamp("1-1-2020", tz="Asia/Calcutta")
print(ts)
ts.tz
2020-01-01 00:00:00+05:30
<DstTzInfo 'Asia/Calcutta' IST+5:30:00 STD>

7.1 Add Time Zone to Pandas Series / DataFrame using "tz_localize()"

Pandas provide a function named tz_localize() to set a timezone for date ranges, and timestamps that do not have any timezone set previously. It returns a modified date range, and timestamp with time zone passed to tz_localize().

rng = pd.date_range(start="1-1-2020", periods=5, freq="M")
print(rng)
print("Timezone : ", rng.tz)
DatetimeIndex(['2020-01-31', '2020-02-29', '2020-03-31', '2020-04-30',
               '2020-05-31'],
              dtype='datetime64[ns]', freq='M')
Timezone :  None
rng = rng.tz_localize("US/Eastern")
print(rng)
print("Timezone : ", rng.tz)
DatetimeIndex(['2020-01-31 00:00:00-05:00', '2020-02-29 00:00:00-05:00',
               '2020-03-31 00:00:00-04:00', '2020-04-30 00:00:00-04:00',
               '2020-05-31 00:00:00-04:00'],
              dtype='datetime64[ns, US/Eastern]', freq='M')
Timezone :  US/Eastern
ts = pd.Timestamp("1-1-2020")
print(ts)
print("Timezone : ", ts.tz)
2020-01-01 00:00:00
Timezone :  None
ts = ts.tz_localize("US/Central")
print(ts)
print("Timezone : ", ts.tz)
2020-01-01 00:00:00-06:00
Timezone :  US/Central

7.2 Convert Time Zone of Pandas Series / DataFrame using "tz_convert()"

We can convert date ranges and timestamps from one timezone to another timezone using tz_convert() method. We can pass a new timezone to tz_convert() method and it'll return modified date range and timestamp with time modified according to new timezone. We'll explain its usage with a few examples below.

ts = pd.Timestamp("1-1-2020", tz="US/Central")
print(ts)
print("Timezone : ", ts.tz)
2020-01-01 00:00:00-06:00
Timezone :  US/Central
ts = ts.tz_convert("US/Eastern")
print(ts)
print("Timezone : ", ts.tz)
2020-01-01 01:00:00-05:00
Timezone :  US/Eastern
rng = pd.date_range(start="1-1-2020", periods=5, freq="D", tz="US/Eastern")
print(rng)
print("Timezone : ", rng.tz)
DatetimeIndex(['2020-01-01 00:00:00-05:00', '2020-01-02 00:00:00-05:00',
               '2020-01-03 00:00:00-05:00', '2020-01-04 00:00:00-05:00',
               '2020-01-05 00:00:00-05:00'],
              dtype='datetime64[ns, US/Eastern]', freq='D')
Timezone :  US/Eastern
rng = rng.tz_convert("US/Central")
print(rng)
print("Timezone : ", rng.tz)
DatetimeIndex(['2019-12-31 23:00:00-06:00', '2020-01-01 23:00:00-06:00',
               '2020-01-02 23:00:00-06:00', '2020-01-03 23:00:00-06:00',
               '2020-01-04 23:00:00-06:00'],
              dtype='datetime64[ns, US/Central]', freq='D')
Timezone :  US/Central
rng = rng.tz_convert("Asia/Calcutta")
print(rng)
print("Timezone : ", rng.tz)
DatetimeIndex(['2020-01-01 10:30:00+05:30', '2020-01-02 10:30:00+05:30',
               '2020-01-03 10:30:00+05:30', '2020-01-04 10:30:00+05:30',
               '2020-01-05 10:30:00+05:30'],
              dtype='datetime64[ns, Asia/Calcutta]', freq='D')
Timezone :  Asia/Calcutta
rng = rng.tz_convert("Asia/Istanbul")
print(rng)
print("Timezone : ", rng.tz)
DatetimeIndex(['2020-01-01 08:00:00+03:00', '2020-01-02 08:00:00+03:00',
               '2020-01-03 08:00:00+03:00', '2020-01-04 08:00:00+03:00',
               '2020-01-05 08:00:00+03:00'],
              dtype='datetime64[ns, Asia/Istanbul]', freq='D')
Timezone :  Asia/Istanbul

We can notice above that time has been moved when changed from one timezone to another. It takes care of daylight savings time as well.

Sunny Solanki  Sunny Solanki

YouTube Subscribe Comfortable Learning through Video Tutorials?

If you are more comfortable learning through video tutorials then we would recommend that you subscribe to our YouTube channel.

Need Help Stuck Somewhere? Need Help with Coding? Have Doubts About the Topic/Code?

When going through coding examples, it's quite common to have doubts and errors.

If you have doubts about some code examples or are stuck somewhere when trying our code, send us an email at coderzcolumn07@gmail.com. We'll help you or point you in the direction where you can find a solution to your problem.

You can even send us a mail if you are trying something new and need guidance regarding coding. We'll try to respond as soon as possible.

Share Views Want to Share Your Views? Have Any Suggestions?

If you want to

  • provide some suggestions on topic
  • share your views
  • include some details in tutorial
  • suggest some new topics on which we should create tutorials/blogs
Please feel free to contact us at coderzcolumn07@gmail.com. We appreciate and value your feedbacks. You can also support us with a small contribution by clicking DONATE.


Subscribe to Our YouTube Channel

YouTube SubScribe

Newsletter Subscription