Сообщить об ошибке.

Операции со значениями datetime объектов Series/index в pandas

Внимание. Представлениями datetime в библиотеке pandas являются следующие объекты:

У объектов Series/index есть метод доступа Series.dt, позволяющий кратко возвращать свойства, подобные дате и времени, для значений, если они являются представлениями datetime (смотрите выше) или pandas.PeriodIndex.

Это поведение позволяет использовать приятные выражения:

>>> s = pd.Series(pd.date_range("20130101 09:10:12", periods=4))
>>> s
# 0   2013-01-01 09:10:12
# 1   2013-01-02 09:10:12
# 2   2013-01-03 09:10:12
# 3   2013-01-04 09:10:12
# dtype: datetime64[ns]

>>> s[s.dt.day == 2]
# 1   2024-01-02 09:10:12
# dtype: datetime64[ns]

Series.dt выдаст ошибку TypeError, если получить доступ к значениям, отличным от даты и времени.

Встроенные методы объекта Series.dt:

  • Series.dt.date: возвращает массив объектов Python datetime.date().

  • Series.dt.time: возвращает массив объектов datetime.time().

  • Series.dt.timetz: возвращает массив объектов datetime.time() с часовыми поясами.

  • Series.dt.year: возвращает год.

  • Series.dt.month: возвращает месяц.

  • Series.dt.day: возвращает день.

  • Series.dt.hour: возвращает час.

  • Series.dt.minute: возвращает минуту.

  • Series.dt.second: возвращает секунду.

  • Series.dt.microsecond: возвращает микросекунду.

  • Series.dt.nanosecond: возвращает наносекунду.

  • Series.dt.dayofweek: возвращает день недели. Предполагается, что неделя начинается в понедельник, который обозначается 0, и заканчивается в воскресенье, которое обозначается 6. Этот метод доступен как для Series со значениями datetime (с использованием метода доступа .dt), так и для DatetimeIndex.

  • Series.dt.day_of_week: возвращает день недели. Тоже, что и pandas.Series.dt.dayofweek.

  • Series.dt.weekday: возвращает день недели. Тоже, что и pandas.Series.dt.dayofweek.

  • Series.dt.dayofyear: возвращает номер дня в году.

  • Series.dt.day_of_year: возвращает номер дня в году.

  • Series.dt.days_in_month: возвращает количество дней в месяце.

  • Series.dt.quarter: возвращает квАртал даты.

  • Series.dt.is_month_start: проверяет, является ли дата первым днем месяца. Возвращает серию логических значений.

  • Series.dt.is_month_end: проверяет, является ли дата последним днем месяца. Возвращает серию логических значений.

  • Series.dt.is_quarter_start: проверяет, является ли дата первым днем квартала.

  • Series.dt.is_quarter_end: проверяет, является ли дата последним днем квартала.

  • Series.dt.is_year_start: проверяет, является ли дата первым днем года.

  • Series.dt.is_year_end: проверяет, является ли дата первым днем года.

  • Series.dt.is_leap_year: логический индикатор, если дата относится к високосному году. Високосные годы - это годы, кратные четырем, за исключением лет, делящихся на 100, но не на 400.

  • Series.dt.daysinmonth: возвращает количество дней в месяце.

  • Series.dt.days_in_month: возвращает количество дней в месяце.

  • Series.dt.tz: возвращает часовой пояс.

  • Series.dt.freq: возвращает псевдоним периода pandas

  • Series.dt.unit: возвращает точность периода pandas

  • Series.dt.normalize(): преобразует время в полночь. Компонент даты-времени преобразуется в полночь, т.е. 00:00:00. Это полезно в тех случаях, когда время не имеет значения. Длина не меняется. Часовые пояса не затрагиваются. Этот метод доступен для Series и непосредственно для массива/индекса даты и времени.

    >>> idx = pd.date_range(start='2024-08-01 10:00', freq='H', periods=3, tz='Europe/Moscow')
    >>> idx
    # DatetimeIndex(['2024-08-01 10:00:00+03:00', '2024-08-01 11:00:00+03:00',
    #                '2024-08-01 12:00:00+03:00'],
    #               dtype='datetime64[ns, Europe/Moscow]', freq='H')
    >>> idx.normalize()
    # DatetimeIndex(['2024-08-01 00:00:00+03:00', '2024-08-01 00:00:00+03:00',
    #                '2024-08-01 00:00:00+03:00'],
    #               dtype='datetime64[ns, Europe/Moscow]', freq=None)
    
  • Series.dt.isocalendar(): рассчитывает год, неделю и день в соответствии со стандартом ISO 8601.

    >>> ser = pd.to_datetime(pd.Series(["2010-01-01", pd.NaT]))
    >>> ser.dt.isocalendar()
    #    year  week   day
    # 0  2009    53     5
    # 1  <NA>  <NA>  <NA>
    
  • Series.dt.to_period(): преобразует DatetimeArray/Index в PeriodArray/PeriodIndex.

    >>> import datetime
    >>> now = datetime.date.today()
    >>> rng = pd.date_range(now, periods=100)
    # создаем серию с данными `range`
    >>> sr = pd.Series(range)
    >>> sr.index = [f'День {x}' for x in sr.dt.day]
    >>> sr
    # День 25   2024-01-25
    # День 26   2024-01-26
    # День 27   2024-01-27
    # День 28   2024-01-28
    # День 29   2024-01-29
    #              ...    
    # День 29   2024-04-29
    # День 30   2024-04-30
    # День 1    2024-05-01
    # День 2    2024-05-02
    # День 3    2024-05-03
    # Length: 100, dtype: datetime64[ns]  
    
    # преобразуем даты в период по месяцам
    >>> sr.dt.to_period(freq='M')
    # День 25    2024-01
    # День 26    2024-01
    # День 27    2024-01
    # День 28    2024-01
    # День 29    2024-01
    #             ...   
    # День 29    2024-04
    # День 30    2024-04
    # День 1     2024-05
    # День 2     2024-05
    # День 3     2024-05
    # Length: 100, dtype: period[M]
    

    Дополнительно можно посмотреть методы DatetimeIndex.to_period() и DataFrame.to_period().

  • Series.dt.to_pydatetime(): возвращает данные в виде массива объектов datetime.datetime. Текущее поведение .to_pydatetime устарело. В будущей версии (> 2.1) будет возвращать Series, содержащую объекты python datetime вместо ndarray.

    >>> s = pd.Series(pd.date_range('20240310', periods=2))
    >>> s
    # 0   2024-03-10
    # 1   2024-03-11
    # dtype: datetime64[ns]
    
    >>> s.dt.to_pydatetime()
    # array([datetime.datetime(2024, 3, 10, 0, 0),
    #        datetime.datetime(2024, 3, 11, 0, 0)], dtype=object)
    
  • Series.dt.tz_localize(): метод принимает объект Array/Index с "наивным" datetime часового пояса (tz) и учитывает этот часовой пояс. Он не перемещает время в другой часовой пояс. Этот метод можно использовать для обратного действия - для создания объекта, не знающего часовой пояс. Для этого необходимо передать tz=None.

    >>> tz_naive = pd.date_range('2018-03-01 09:00', periods=3)
    >>> tz_naive
    # DatetimeIndex(['2018-03-01 09:00:00', '2018-03-02 09:00:00',
    #                '2018-03-03 09:00:00'],
    #               dtype='datetime64[ns]', freq='D')
    >>> tz_aware = tz_naive.tz_localize(tz='Europe/Moscow')
    >>> tz_aware
    # DatetimeIndex(['2018-03-01 09:00:00+03:00', '2018-03-02 09:00:00+03:00',
    #                '2018-03-03 09:00:00+03:00'],
    #               dtype='datetime64[ns, Europe/Moscow]', freq=None)
    

    С помощью tz=None удаляем информацию о часовом поясе, сохранив местное время (не преобразованное в UTC):

    >>> tz_aware.tz_localize(None)
    # DatetimeIndex(['2018-03-01 09:00:00', '2018-03-02 09:00:00',
    #                '2018-03-03 09:00:00'],
    #               dtype='datetime64[ns]', freq=None)
    
  • Series.dt.tz_convert(): преобразует Array/Index с datetime с поддержкой tz-версии из одного часового пояса в другой.

    >>> dti = pd.date_range(start='2024-08-01 09:00', freq='H', periods=3, tz='Europe/Moscow')
    >>> dti
    # DatetimeIndex(['2024-08-01 09:00:00+03:00', '2024-08-01 10:00:00+03:00',
    #                '2024-08-01 11:00:00+03:00'],
    #               dtype='datetime64[ns, Europe/Moscow]', freq='H')
    
    >>> dti.tz_convert('Europe/Berlin')
    # DatetimeIndex(['2024-08-01 08:00:00+02:00', '2024-08-01 09:00:00+02:00',
    #                '2024-08-01 10:00:00+02:00'],
    #               dtype='datetime64[ns, Europe/Berlin]', freq='H')
    

    С помощью tz=None можно удалить часовой пояс (после преобразования в UTC, если это необходимо).

  • Series.dt.strftime(): возвращает индекс форматированных строк, заданный форматом строк, как в стандартной библиотеки python.

    >>> rng = pd.date_range(pd.Timestamp("2024-03-10 09:00"), periods=3, freq='s')
    >>> rng.strftime('%B %d, %Y, %r')
    # Index(['March 10, 2024, 09:00:00 AM', 'March 10, 2024, 09:00:01 AM',
    #        'March 10, 2024, 09:00:02 AM'],
    #       dtype='object')
    
  • Series.dt.round(): выполняет операцию округления данных до заданного частоты/периода freq.

    Для Index

    >>> rng = pd.date_range('1/1/2024 11:59:00', periods=3, freq='min')
    >>> rng
    # DatetimeIndex(['2024-01-01 11:59:00', '2024-01-01 12:00:00',
    #                '2024-01-01 12:01:00'],
    #               dtype='datetime64[ns]', freq='T')
    
    # Округляем до ближайшего часа 
    >>> rng.round('H')
    # DatetimeIndex(['2024-01-01 12:00:00', '2024-01-01 12:00:00',
    #                '2024-01-01 12:00:00'],
    #               dtype='datetime64[ns]', freq=None)
    

    Для Series

    >>> pd.Series(rng).dt.round("H")
    # 0   2024-01-01 12:00:00
    # 1   2024-01-01 12:00:00
    # 2   2024-01-01 12:00:00
    # dtype: datetime64[ns]
    
  • Series.dt.floor(): выполняет поэтапную операцию с данными с указанной частотой/периодом freq.

    Для Index

    >>> rng = pd.date_range('1/1/2024 11:59:00', periods=3, freq='min')
    >>> rng
    # DatetimeIndex(['2024-01-01 11:59:00', '2024-01-01 12:00:00',
    #                '2024-01-01 12:01:00'],
    #               dtype='datetime64[ns]', freq='T')
    
    >>> rng.floor('H')
    # DatetimeIndex(['2024-01-01 11:00:00', '2024-01-01 12:00:00',
    #                '2024-01-01 12:00:00'],
    #               dtype='datetime64[ns]', freq=None)
    

    Для Series

    >>> pd.Series(rng).dt.floor("H")
    # 0   2024-01-01 11:00:00
    # 1   2024-01-01 12:00:00
    # 2   2024-01-01 12:00:00
    # dtype: datetime64[ns]
    
  • Series.dt.ceil(): выполняет операцию ceil над данными с указанной частотой.

    >>> rng = pd.date_range('1/1/2024 11:59:00', periods=3, freq='min')
    >>> rng
    # DatetimeIndex(['2024-01-01 11:59:00', '2024-01-01 12:00:00',
    #                '2024-01-01 12:01:00'],
    #               dtype='datetime64[ns]', freq='T')
    
    >>> rng.ceil('H')
    # DatetimeIndex(['2024-01-01 12:00:00', '2024-01-01 12:00:00',
    #                '2024-01-01 13:00:00'],
    #               dtype='datetime64[ns]', freq=None)
    
  • Series.dt.month_name(): возвращает названия месяцев с указанной локализацией locale. Например locale='ru_RU.utf8'.

    >>> s = pd.Series(pd.date_range(start='2024-01', freq='M', periods=3))
    >>> s
    # 0   2024-01-31
    # 1   2024-02-29
    # 2   2024-03-31
    # dtype: datetime64[ns]
    
    >>> s.dt.month_name(locale='ru_RU.utf8')
    # 0     Января
    # 1    Февраля
    # 2      Марта
    # dtype: object
    
  • Series.dt.day_name(): возвращает названия дней недели с указанной локализацией locale. Например locale='ru_RU.utf8'.

    >>> s = pd.Series(pd.date_range(start='2024-01-01', freq='D', periods=3))
    >>> s
    # 0   2024-01-01
    # 1   2024-01-02
    # 2   2024-01-03
    # dtype: datetime64[ns]
    
    >>> s.dt.day_name(locale='ru_RU.utf8')
    # 0    Понедельник
    # 1        Вторник
    # 2          Среда
    # dtype: object
    
  • Series.dt.start_time: возвращает временную метку начала периода.

  • Series.dt.end_time: возвращает временную метку конца периода.

  • Series.dt.days: возвращает количество дней для каждого элемента.

  • Series.dt.seconds: возвращает количество секунд ( >= 0 и меньше 1 дня) для каждого элемента.

  • Series.dt.microseconds: возвращает количество микросекунд ( >= 0 и меньше 1 дня) для каждого элемента.

  • Series.dt.nanoseconds: возвращает количество наносекунд ( >= 0 и меньше 1 дня) для каждого элемента.

  • Series.dt.components: возвращает dataframe компонентов datatine для Timedeltas.

  • Series.dt.to_pytimedelta(): возвращает массив собственных объектов datetime.timedelta. Стандартная библиотека datetime Python использует другое представление timedelta. Этот метод преобразует серию Timedeltas в формат datetime.timedelta с той же длиной, что и исходная Series.

  • Series.dt.total_seconds(): возвращает общую длительность каждого элемента, выраженную в секундах.


Обзор использования объекта Series.dt

Пример с Series, значение которой являются объектами datetime:

>>> s = pd.Series(pd.date_range("20130101 09:10:12", periods=4))
>>> s
# 0   2013-01-01 09:10:12
# 1   2013-01-02 09:10:12
# 2   2013-01-03 09:10:12
# 3   2013-01-04 09:10:12
# dtype: datetime64[ns]

>>> s.dt.hour
# 0    9
# 1    9
# 2    9
# 3    9
# dtype: int32

>>> s.dt.second
# 0    12
# 1    12
# 2    12
# 3    12
# dtype: int32

>>> s.dt.day
# 0    1
# 1    2
# 2    3
# 3    4
# dtype: int32

Это позволяет использовать такие приятные выражения:

>>> s[s.dt.day == 2]
# 1   2024-01-02 09:10:12
# dtype: datetime64[ns]

Можно легко выполнить преобразования с учетом tz:

>>> stz = s.dt.tz_localize("Europe/Moscow")
>>> stz
# 0   2024-01-01 09:10:12+03:00
# 1   2024-01-02 09:10:12+03:00
# 2   2024-01-03 09:10:12+03:00
# 3   2024-01-04 09:10:12+03:00
# dtype: datetime64[ns, Europe/Moscow]

>>> stz.dt.tz
# <DstTzInfo 'Europe/Moscow' LMT+2:30:00 STD>

Также можно связать эти типы операций:

>>> s.dt.tz_localize("UTC").dt.tz_convert("Europe/Moscow")
# 0   2024-01-01 12:10:12+03:00
# 1   2024-01-02 12:10:12+03:00
# 2   2024-01-03 12:10:12+03:00
# 3   2024-01-04 12:10:12+03:00
# dtype: datetime64[ns, Europe/Moscow]

Можно форматировать значения даты и времени как строки с помощью Series.dt.strftime(), который поддерживает тот же формат, что и стандартный .strftime(format).

Пример с объектом DatetimeIndex:

>>> s = pd.Series(pd.date_range("20240101", periods=4))
>>> s
# 0   2024-01-01
# 1   2024-01-02
# 2   2024-01-03
# 3   2024-01-04
# dtype: datetime64[ns]

>>> s.dt.strftime("%d.%m.%Y г.")
# 0    01.01.2024 г.
# 1    02.01.2024 г.
# 2    03.01.2024 г.
# 3    04.01.2024 г.
# dtype: object

Пример с объектом PeriodIndex:

>>> s = pd.Series(pd.period_range("20240101", periods=4))
>>> s
# 0    2024-01-01
# 1    2024-01-02
# 2    2024-01-03
# 3    2024-01-04
# dtype: period[D]

>>> s.dt.strftime("%d.%m.%Y г.")
# 0    01.01.2024 г.
# 1    02.01.2024 г.
# 2    03.01.2024 г.
# 3    04.01.2024 г.
# dtype: object

Series.dt работает для типов period.Period и timedeltas.Timedelta.

# объект `period.Period`
>>> s = pd.Series(pd.period_range("20240101", periods=4, freq="D"))
>>> s
# 0    2024-01-01
# 1    2024-01-02
# 2    2024-01-03
# 3    2024-01-04
# dtype: period[D]

>>> s.dt.year
# 0    2024
# 1    2024
# 2    2024
# 3    2024
# dtype: int64

>>> s.dt.day
# 0    1
# 1    2
# 2    3
# 3    4
# dtype: int64
# объект `timedeltas.Timedelta`
>>> s = pd.Series(pd.timedelta_range("1 day 00:00:05", periods=4, freq="s"))
>>> s
# 0   1 days 00:00:05
# 1   1 days 00:00:06
# 2   1 days 00:00:07
# 3   1 days 00:00:08
# dtype: timedelta64[ns]

>>> s.dt.days
# 0    1
# 1    1
# 2    1
# 3    1
# dtype: int64

>>> s.dt.seconds
# 0    5
# 1    6
# 2    7
# 3    8
# dtype: int32

>>> s.dt.components
#    days  hours  minutes  seconds  milliseconds  microseconds  nanoseconds
# 0     1      0        0        5             0             0            0
# 1     1      0        0        6             0             0            0
# 2     1      0        0        7             0             0            0
# 3     1      0        0        8             0             0            0