Документация Pendulum
Версия 3.0
Документация
Установка
Установить pendulum очень просто:
$ pip install pendulum
или, если вы используете poetry:
$ poetry add pendulum
Дополнительные возможности
Pendulum предоставляет опциональные возможности, которые нужно явно подключать при установке.
Доступные опции:
test: набор вспомогательных средств для тестирования, позволяющих управлять течением времени.
Установить их можно, указав при установке Pendulum:
$ pip install pendulum[test]
или, если вы используете poetry:
$ poetry add pendulum[test]
Введение
Pendulum — это Python-пакет для удобной работы с датой и временем.
Он предоставляет классы, которые являются прямой заменой встроенных (и наследуются от них).
Особое внимание уделено корректной работе с часовыми поясами на основе реализации tzinfo. Например, все сравнения выполняются в UTC или в часовом поясе используемой даты и времени.
>>> import pendulum
>>> dt_toronto = pendulum.datetime(2012, 1, 1, tz='America/Toronto')
>>> dt_vancouver = pendulum.datetime(2012, 1, 1, tz='America/Vancouver')
>>> print(dt_vancouver.diff(dt_toronto).in_hours())
3
Часовой пояс по умолчанию (кроме метода now()) всегда UTC.
Создание экземпляров
Есть несколько способов создать новый экземпляр DateTime.
Основной — вспомогательная функция datetime().
>>> import pendulum
>>> dt = pendulum.datetime(2015, 2, 5)
>>> isinstance(dt, datetime)
True
>>> dt.timezone.name
'UTC'
datetime() устанавливает время в 00:00:00, если оно не задано, и часовой пояс (аргумент tz) в UTC. Иначе можно передать экземпляр Timezone или строку с названием часового пояса.
>>> import pendulum
>>> pendulum.datetime(2015, 2, 5, tz='Europe/Paris')
>>> tz = pendulum.timezone('Europe/Paris')
>>> pendulum.datetime(2015, 2, 5, tz=tz)
Note
Поддерживаются строки часовых поясов из базы данных IANA time zone.
Также поддерживается специальная строка local — она соответствует вашей текущей временной зоне.
Warning
В отличие от версии 1.x, аргумент tz передаётся только по имени.
Функция local() похожа на datetime(), но автоматически подставляет локальный часовой пояс.
>>> import pendulum
>>> dt = pendulum.local(2015, 2, 5)
>>> print(dt.timezone.name)
'America/Toronto'
Note
local() — это псевдоним для datetime(..., tz='local').
Есть также метод now().
>>> import pendulum
>>> now = pendulum.now()
>>> now_in_london_tz = pendulum.now('Europe/London')
>>> now_in_london_tz.timezone_name
'Europe/London'
Наряду с now() есть статические функции для создания известных моментов времени. Важно: today(), tomorrow() и yesterday() принимают параметр часового пояса, а время у них устанавливается в 00:00:00.
>>> now = pendulum.now()
>>> print(now)
'2016-06-28T16:51:45.978473-05:00'
>>> today = pendulum.today()
>>> print(today)
'2016-06-28T00:00:00-05:00'
>>> tomorrow = pendulum.tomorrow('Europe/London')
>>> print(tomorrow)
'2016-06-29T00:00:00+01:00'
>>> yesterday = pendulum.yesterday()
>>> print(yesterday)
'2016-06-27T00:00:00-05:00'
Pendulum использует даты и время с учётом часового пояса; это рекомендуемый способ работы с библиотекой. Если нужен «наивный» объект DateTime, используйте функцию naive().
>>> import pendulum
>>> naive = pendulum.naive(2015, 2, 5)
>>> naive.timezone
None
Функция from_format() аналогична встроенной datetime.strptime(), но использует собственные токены для создания экземпляра DateTime.
>>> dt = pendulum.from_format('1975-05-21 22', 'YYYY-MM-DD HH')
>>> print(dt)
'1975-05-21T22:00:00+00:00'
Note
Все доступные токены описаны в разделе Formatter.
Можно передать аргумент tz для указания часового пояса:
>>> dt = pendulum.from_format('1975-05-21 22', 'YYYY-MM-DD HH', tz='Europe/London')
'1975-05-21T22:00:00+01:00'
Для работы с Unix-временными метками используется from_timestamp(): создаётся экземпляр DateTime по заданной метке, при необходимости задаётся часовой пояс (по умолчанию UTC).
>>> dt = pendulum.from_timestamp(-1)
>>> print(dt)
'1969-12-31T23:59:59+00:00'
>>> dt = pendulum.from_timestamp(-1, tz='Europe/London')
>>> print(dt)
'1970-01-01T00:59:59+01:00'
Если у вас уже есть экземпляр datetime.datetime, из него можно создать DateTime с помощью функции instance().
>>> dt = datetime(2008, 1, 1)
>>> p = pendulum.instance(dt)
>>> print(p)
'2008-01-01T00:00:00+00:00'
Разбор строк
Библиотека поддерживает формат RFC 3339, большинство форматов ISO 8601 и ряд других распространённых форматов.
>>> import pendulum
>>> dt = pendulum.parse('1975-05-21T22:00:00')
>>> print(dt)
'1975-05-21T22:00:00+00:00'
# Часовой пояс можно задать аргументом tz
>>> dt = pendulum.parse('1975-05-21T22:00:00', tz='Europe/Paris')
>>> print(dt)
'1975-05-21T22:00:00+01:00'
# Не по ISO 8601, но часто встречается
>>> dt = pendulum.parse('1975-05-21 22:00:00')
При передаче нестандартной или сложной строки будет выброшено исключение; в таких случаях лучше использовать from_format().
Если нужно использовать парсер dateutil, передайте strict=False.
>>> import pendulum
>>> dt = pendulum.parse('31-01-01')
Traceback (most recent call last):
...
ParserError: Unable to parse string [31-01-01]
>>> dt = pendulum.parse('31-01-01', strict=False)
>>> print(dt)
'2031-01-01T00:00:00+00:00'
RFC 3339
| Строка | Результат |
|---|---|
| 1996-12-19T16:39:57-08:00 | 1996-12-19T16:39:57-08:00 |
| 1990-12-31T23:59:59Z | 1990-12-31T23:59:59+00:00 |
ISO 8601
Дата и время
| Строка | Результат |
|---|---|
| 20161001T143028+0530 | 2016-10-01T14:30:28+05:30 |
| 20161001T14 | 2016-10-01T14:00:00+00:00 |
| Строка | Результат |
|---|---|
| 2012 | 2012-01-01T00:00:00+00:00 |
| 2012-05-03 | 2012-05-03T00:00:00+00:00 |
| 20120503 | 2012-05-03T00:00:00+00:00 |
| 2012-05 | 2012-05-01T00:00:00+00:00 |
Порядковый день года
| Строка | Результат |
|---|---|
| 2012-007 | 2012-01-07T00:00:00+00:00 |
| 2012007 | 2012-01-07T00:00:00+00:00 |
Номер недели
| Строка | Результат |
|---|---|
| 2012-W05 | 2012-01-30T00:00:00+00:00 |
| 2012W05 | 2012-01-30T00:00:00+00:00 |
| 2012-W05-5 | 2012-02-03T00:00:00+00:00 |
| 2012W055 | 2012-02-03T00:00:00+00:00 |
Время
При передаче только времени дата по умолчанию — сегодня.
| Строка | Результат |
|---|---|
| 00:00 | 2016-12-17T00:00:00+00:00 |
| 12:04:23 | 2016-12-17T12:04:23+00:00 |
| 120423 | 2016-12-17T12:04:23+00:00 |
| 12:04:23.45 | 2016-12-17T12:04:23.450000+00:00 |
Интервалы
| Строка | Результат |
|---|---|
| 2007-03-01T13:00:00Z/2008-05-11T15:30:00Z | 2007-03-01T13:00:00+00:00 -> 2008-05-11T15:30:00+00:00 |
| 2008-05-11T15:30:00Z/P1Y2M10DT2H30M | 2008-05-11T15:30:00+00:00 -> 2009-07-21T18:00:00+00:00 |
| P1Y2M10DT2H30M/2008-05-11T15:30:00Z | 2007-03-01T13:00:00+00:00 -> 2008-05-11T15:30:00+00:00 |
Note
В parse() можно передать аргумент exact=True, чтобы получить тип, соответствующий строке:
>>> import pendulum
>>> pendulum.parse('2012-05-03', exact=True)
Date(2012, 05, 03)
>>> pendulum.parse('12:04:23', exact=True)
Time(12, 04, 23)
Локализация
Локализация применяется в методе format() через аргумент locale.
>>> import pendulum
>>> dt = pendulum.datetime(1975, 5, 21)
>>> dt.format('dddd DD MMMM YYYY', locale='de')
'Mittwoch 21 Mai 1975'
>>> dt.format('dddd DD MMMM YYYY')
'Wednesday 21 May 1975'
Метод diff_for_humans() тоже локализуется; глобальную локаль можно задать через pendulum.set_locale().
>>> import pendulum
>>> pendulum.set_locale('de')
>>> pendulum.now().add(years=1).diff_for_humans()
'in 1 Jahr'
>>> pendulum.set_locale('en')
Локаль для одного вызова можно задать аргументом locale в diff_for_humans().
>>> pendulum.set_locale('de')
>>> dt = pendulum.now().add(years=1)
>>> dt.diff_for_humans(locale='fr')
'dans 1 an'
Атрибуты и свойства
У Pendulum больше атрибутов и свойств, чем у стандартного класса datetime.
>>> import pendulum
>>> dt = pendulum.parse('2012-09-05T23:26:11.123789')
# Эти свойства возвращают целые числа
>>> dt.year
2012
>>> dt.month
9
>>> dt.day
5
>>> dt.hour
23
>>> dt.minute
26
>>> dt.second
11
>>> dt.microsecond
123789
>>> dt.day_of_week
3
>>> dt.day_of_year
248
>>> dt.week_of_month
1
>>> dt.week_of_year
36
>>> dt.days_in_month
30
>>> dt.timestamp()
1346887571.123789
>>> dt.float_timestamp
1346887571.123789
>>> dt.int_timestamp
1346887571
>>> pendulum.datetime(1975, 5, 21).age
41 # вычислено относительно now() в том же поясе
>>> dt.quarter
3
# Разница с UTC в секундах (int), со знаком
>>> pendulum.from_timestamp(0).offset
0
>>> pendulum.from_timestamp(0, 'America/Toronto').offset
-18000
# Разница с UTC в часах (float), со знаком
>>> pendulum.from_timestamp(0, 'America/Toronto').offset_hours
-5.0
>>> pendulum.from_timestamp(0, 'Australia/Adelaide').offset_hours
9.5
# Экземпляр часового пояса
>>> pendulum.now().timezone
>>> pendulum.now().tz
# Название часового пояса
>>> pendulum.now().timezone_name
# Действует ли летнее время
>>> dt = pendulum.datetime(2012, 1, 1, tz='America/Toronto')
>>> dt.is_dst()
False
>>> dt = pendulum.datetime(2012, 9, 1, tz='America/Toronto')
>>> dt.is_dst()
True
# Совпадает ли часовой пояс с локальным
>>> pendulum.now().is_local()
True
>>> pendulum.now('Europe/London').is_local()
False
# Находится ли экземпляр в UTC
>>> pendulum.now().is_utc()
False
>>> pendulum.now('Europe/London').is_local()
False
>>> pendulum.now('UTC').is_utc()
True
Fluent-помощники
Pendulum предоставляет методы, возвращающие новый экземпляр с изменёнными атрибутами. Ни один из них (кроме явной установки часового пояса) не меняет часовой пояс исходного экземпляра. В частности, установка timestamp не переводит часовой пояс в UTC.
>>> import pendulum
>>> dt = pendulum.now()
>>> dt.set(year=1975, month=5, day=21).to_datetime_string()
'1975-05-21 13:45:18'
>>> dt.set(hour=22, minute=32, second=5).to_datetime_string()
'2016-11-16 22:32:05'
Дату и время можно менять методами on() и at():
>>> dt.on(1975, 5, 21).at(22, 32, 5).to_datetime_string()
'1975-05-21 22:32:05'
>>> dt.at(10).to_datetime_string()
'2016-11-16 10:00:00'
>>> dt.at(10, 30).to_datetime_string()
'2016-11-16 10:30:00'
Часовой пояс тоже можно изменить:
>>> dt.set(tz='Europe/London')
set(tz=...) меняет только информацию о поясе без пересчёта времени, а in_timezone() (или in_tz()) переводит время в указанный пояс.
>>> import pendulum
>>> dt = pendulum.datetime(2013, 3, 31, 2, 30)
>>> print(dt)
'2013-03-31T02:30:00+00:00'
>>> dt = dt.set(tz='Europe/Paris')
>>> print(dt)
'2013-03-31T03:30:00+02:00'
>>> dt = dt.in_tz('Europe/Paris')
>>> print(dt)
'2013-03-31T04:30:00+02:00'
>>> dt = dt.set(tz='Europe/Paris').set(tz='UTC')
>>> print(dt)
'2013-03-31T03:30:00+00:00'
>>> dt = dt.in_tz('Europe/Paris').in_tz('UTC')
>>> print(dt)
'2013-03-31T02:30:00+00:00'
Форматирование в строку
Метод __str__ определён так, что экземпляры DateTime выводятся в читаемом виде в строковом контексте. По умолчанию используется тот же формат, что и у isoformat().
>>> import pendulum
>>> dt = pendulum.datetime(1975, 12, 25, 14, 15, 16)
>>> print(dt)
'1975-12-25T14:15:16+00:00'
>>> dt.to_date_string()
'1975-12-25'
>>> dt.to_formatted_date_string()
'Dec 25, 1975'
>>> dt.to_time_string()
'14:15:16'
>>> dt.to_datetime_string()
'1975-12-25 14:15:16'
>>> dt.to_day_datetime_string()
'Thu, Dec 25, 1975 2:15 PM'
# Можно использовать метод format()
>>> dt.format('dddd Do [of] MMMM YYYY HH:mm:ss A')
'Thursday 25th of December 1975 02:15:16 PM'
# Метод strftime по-прежнему доступен
>>> dt.strftime('%A %-d%t of %B %Y %I:%M:%S %p')
'Thursday 25th of December 1975 02:15:16 PM'
Note
Локализация описана в разделе «Локализация».
Распространённые форматы
Методы вывода в стандартных форматах:
>>> import pendulum
>>> dt = pendulum.now()
>>> dt.to_atom_string()
>>> dt.to_cookie_string()
>>> dt.to_iso8601_string()
>>> dt.to_rfc822_string()
>>> dt.to_rfc850_string()
>>> dt.to_rfc1036_string()
>>> dt.to_rfc1123_string()
>>> dt.to_rfc2822_string()
>>> dt.to_rfc3339_string()
>>> dt.to_rss_string()
>>> dt.to_w3c_string()
Formatter
При использовании метода format() Pendulum применяет собственный формат. Он интуитивнее, чем у strftime(), и поддерживает больше директив.
>>> import pendulum
>>> dt = pendulum.datetime(1975, 12, 25, 14, 15, 16)
>>> dt.format('YYYY-MM-DD HH:mm:ss')
'1975-12-25 14:15:16'
Токены
Поддерживаемые токены:
| Категория | Токен | Пример вывода |
|---|---|---|
| Год | YYYY | 2000, 2001 ... 2012, 2013 |
| YY | 00, 01 ... 12, 13 | |
| Y | 2000, 2001 ... 2012, 2013 | |
| Квартал | Q | 1 2 3 4 |
| Qo | 1st 2nd 3rd 4th | |
| Месяц | MMMM | January, February ... |
| MMM | Jan, Feb, Mar ... | |
| MM | 01, 02 ... 11, 12 | |
| M | 1, 2 ... 11, 12 | |
| Mo | 1st 2nd ... 11th 12th | |
| День года | DDDD | 001, 002 ... 364, 365 |
| DDD | 1, 2, 3 ... 364, 365 | |
| День месяца | DD | 01, 02 ... 30, 31 |
| D | 1, 2 ... 30, 31 | |
| Do | 1st, 2nd ... 30th, 31st | |
| День недели | dddd | Monday, Tuesday ... |
| ddd | Mon, Tue, Wed ... | |
| dd | Mo, Tu, We ... | |
| d | 0, 1, 2 ... 6 | |
| Дни недели ISO | E | 1, 2 ... 7 |
| Час | HH | 00, 01 ... 23 |
| H | 0, 1 ... 23 | |
| hh | 01, 02 ... 11, 12 | |
| h | 1, 2 ... 11, 12 | |
| Минута | mm | 00, 01 ... 58, 59 |
| m | 0, 1 ... 58, 59 | |
| Секунда | ss | 00, 01 ... 58, 59 |
| s | 0, 1 ... 58, 59 | |
| Доли секунды | S, SS, SSS, SSSS... | 0, 00, 000, 0000... |
| AM/PM | A | AM, PM |
| Часовой пояс | Z | -07:00 ... +07:00 |
| ZZ | -0700 ... +0700 | |
| z | Asia/Baku, Europe/Warsaw ... | |
| zz | EST CST ... MST PST | |
| Метка времени | X | секунды |
Локализованные форматы
| Токен | Пример |
|---|---|
| LT | 8:30 PM |
| LTS | 8:30:25 PM |
| L | 09/04/1986 |
| LL | September 4 1986 |
| LLL | September 4 1986 8:30 PM |
| LLLL | Thursday, September 4 1986 8:30 PM |
Экранирование
Символы в строках формата экранируются квадратными скобками.
>>> dt.format('[today] dddd')
'today Sunday'
Сравнение
Сравнение выполняется обычными операторами. Сравнение идёт в UTC, поэтому результат не всегда очевиден.
>>> first = pendulum.datetime(2012, 9, 5, 23, 26, 11, 0, tz='America/Toronto')
>>> second = pendulum.datetime(2012, 9, 5, 20, 26, 11, 0, tz='America/Vancouver')
>>> first == second
True
>>> first != second
False
>>> first > second
False
>>> first >= second
True
Есть вспомогательные методы для типичных случаев (например, сравнение с now(): is_today(), is_past(), is_leap_year(), is_birthday() и т.д.). Для методов, сравнивающих с now(), момент now() создаётся в том же часовом поясе, что и экземпляр.
Сложение и вычитание
Используйте методы add() и subtract(); каждый возвращает новый экземпляр DateTime.
>>> dt = pendulum.datetime(2012, 1, 31)
>>> dt = dt.add(years=5)
>>> dt = dt.add(months=1)
>>> dt = dt.subtract(days=29)
>>> dt = dt.add(weeks=3, hours=24, minutes=61, seconds=61)
>>> dt = dt.add(years=3, months=2, days=6, hours=12, minutes=31, seconds=43)
Note
В add() можно передавать отрицательные значения — это эквивалентно subtract().
Разница (Difference)
Метод diff() возвращает экземпляр Period — длительность между двумя DateTime. Эту длительность можно выразить в разных единицах. Методы интервала возвращают полную разницу в запрошенных единицах; значения обрезаются, без округления.
Первый параметр diff() — экземпляр DateTime для сравнения или None (сравнение с now()). Второй параметр — возвращать ли абсолютное значение или относительное (со знаком минус, если переданная дата меньше текущего экземпляра). По умолчанию True — абсолютное значение.
>>> dt_ottawa = pendulum.datetime(2000, 1, 1, tz='America/Toronto')
>>> dt_vancouver = pendulum.datetime(2000, 1, 1, tz='America/Vancouver')
>>> dt_ottawa.diff(dt_vancouver).in_hours()
3
>>> dt_vancouver.diff(dt_ottawa, False).in_hours()
-3
Разница «по-человечески» (diff_for_humans)
diff_for_humans() добавляет фразу после значения разницы. Варианты: «5 months ago», «1 hour from now», «5 months before», «1 hour after». Второй параметр True убирает модификаторы «ago», «from now» и т.п.
>>> pendulum.now().subtract(days=1).diff_for_humans()
'1 day ago'
>>> pendulum.now().add(seconds=5).diff_for_humans()
'5 seconds from now'
>>> pendulum.now().subtract(days=24).diff_for_humans(absolute=True)
'3 weeks'
Локаль задаётся глобально через pendulum.set_locale('fr') или аргументом locale в вызове.
Модификаторы
Методы start_of(), next() и previous() устанавливают время в 00:00:00, end_of() — в 23:59:59.999999. Метод average() возвращает среднюю дату между двумя экземплярами.
>>> dt.start_of('day')
>>> dt.end_of('day')
>>> dt.start_of('month'), dt.end_of('month')
>>> dt.start_of('year'), dt.end_of('year')
>>> dt.start_of('week'), dt.end_of('week') # ISO8601: понедельник — воскресенье
>>> dt.next(pendulum.WEDNESDAY)
>>> dt.previous(pendulum.WEDNESDAY)
>>> start.average(end)
Поддерживаются единицы: day, month, quarter, year, decade, century, week. Аналогично работают first_of(), last_of(), nth_of().
Часовые пояса
Часовые пояса — важная часть библиотеки; Pendulum стремится обрабатывать их корректно.
Note
Система поясов лучше всего работает внутри экосистемы Pendulum, но может использоваться и со стандартным datetime с ограничениями (см. «Using the timezone library directly»).
Нормализация
При создании DateTime библиотека нормализует момент для заданного пояса (переход на летнее/зимнее время).
>>> pendulum.datetime(2013, 3, 31, 2, 30, tz='Europe/Paris')
# 2:30 31 марта 2013 не существует — возвращается 3:30+02:00
'2013-03-31T03:30:00+02:00'
>>> pendulum.datetime(2013, 10, 27, 2, 30, tz='Europe/Paris')
# 2:30 встречается дважды — считается, что переход уже произошёл
'2013-10-27T02:30:00+01:00'
Поведение при нормализации задаётся параметром dst_rule: pendulum.PRE_TRANSITION, pendulum.TRANSITION_ERROR и т.д.
Сдвиг к моменту перехода
При добавлении времени к DateTime в момент перехода Pendulum учитывает контекст и применяет переход корректно (например, 01:59:59.999999 + 1 микросекунда → 03:00:00+02:00).
Смена часового пояса
Используйте in_timezone() или кратко in_tz().
>>> in_paris = pendulum.datetime(2016, 8, 7, 22, 24, 30, tz='Europe/Paris')
>>> in_paris.in_timezone('America/New_York')
>>> in_paris.in_tz('Asia/Tokyo')
Использование библиотеки часовых поясов напрямую
Warning
В Python < 3.6 использовать библиотеку поясов не рекомендуется: Pendulum опирается на атрибут fold, появившийся в 3.6.
С стандартным datetime можно использовать pendulum.timezone, но с ограничениями при сложении/вычитании времени вокруг переходов. По умолчанию используется атрибут fold; можно передать dst_rule в convert(). После арифметики с timedelta рекомендуется снова вызвать tz.convert(dt) для корректного результата.
Duration
Класс Duration наследуется от timedelta и расширяет его.
Note
Нормализация ведёт себя иначе, чем у нативного timedelta, чтобы поведение было более предсказуемым.
Создание: pendulum.duration(days=1177, seconds=7284, microseconds=1234). Поддерживаются также years и months (с приближением для нативной совместимости). Свойства: years, months, weeks, days, remaining_days, hours, minutes, seconds, remaining_seconds, microseconds. Методы: total_weeks(), total_days(), in_weeks(), in_days() и т.д., а также in_words() для текстового представления.
Interval
При вычитании двух DateTime или вызове diff() возвращается экземпляр Interval (наследуется от Duration, хранит ссылки на исходные экземпляры). Создание: pendulum.interval(start, end); можно передать absolute=True для положительного интервала при обратном порядке дат.
Метод range('days') (или range('days', 2) с шагом) позволяет итерировать по интервалу. Поддерживаются единицы: years, months, weeks, days, hours, minutes, seconds, microseconds. Проверка вхождения: dt in interval.
Warning
Большинство арифметических операций с Interval возвращают Duration, а не Interval.
Тестирование
Pendulum предоставляет помощники для управления временем в тестах (доступны при установке с опцией test).
Warning
В Pendulum 3 удалены set_test_now() и test() из версии 2.
- Относительное перемещение:
pendulum.travel(minutes=5)илиpendulum.travel(minutes=5, freeze=True)— время останавливается. - Абсолютное перемещение:
pendulum.travel_to(pendulum.yesterday())или сfreeze=True. - Возврат в настоящее:
pendulum.travel_back()или использование контекстного менеджера:with pendulum.travel(minutes=5, freeze=True): ...
Ограничения
DateTime наследуется от datetime, но в редких случаях не может его полностью заменить.
- sqlite3: зарегистрировать адаптер:
register_adapter(pendulum.DateTime, lambda val: val.isoformat(' ')). - mysqlclient / PyMySQL: прописать конвертеры в
MySQLdb.converters.conversionsиpymysql.converters.conversions. - Django:
isoformat()всегда возвращает смещение (timezone-aware), что может вызвать ошибку для MySQL; можно создать свойDateTimeFieldили использовать обход для MySQLdb (возвращатьvalue.format('YYYY-MM-DD HH:mm:ss')дляpendulum.DateTime).