Поиск…


замечания

Python предоставляет встроенные методы и внешние библиотеки для создания, модификации, разбора и управления датами и временем.

Разбор строки в объекте datetime, посвященном часовому поясу

Python 3.2+ поддерживает формат %z при разборе строки в объект datetime .

UTC в форме +HHMM или -HHMM (пустая строка, если объект наивен).

Python 3.x 3.2
import datetime
dt = datetime.datetime.strptime("2016-04-15T08:27:18-0500", "%Y-%m-%dT%H:%M:%S%z")

Для других версий Python вы можете использовать внешнюю библиотеку, такую ​​как dateutil , которая dateutil анализирует строку с dateutil в объект datetime .

import dateutil.parser
dt = dateutil.parser.parse("2016-04-15T08:27:18-0500")

Теперь переменная dt представляет собой объект datetime со следующим значением:

datetime.datetime(2016, 4, 15, 8, 27, 18, tzinfo=tzoffset(None, -18000))

Простая арифметика даты

Даты не существуют изолированно. Обычно вам нужно найти количество времени между датами или определить, какая дата будет завтра. Это может быть выполнено с использованием объектов timedelta

import datetime

today = datetime.date.today()
print('Today:', today)

yesterday = today - datetime.timedelta(days=1)
print('Yesterday:', yesterday)

tomorrow = today + datetime.timedelta(days=1)
print('Tomorrow:', tomorrow)

print('Time between tomorrow and yesterday:', tomorrow - yesterday)

Это приведет к результатам, аналогичным:

Today: 2016-04-15
Yesterday: 2016-04-14
Tomorrow: 2016-04-16
Difference between tomorrow and yesterday: 2 days, 0:00:00

Использование базовых объектов datetime

Модуль datetime содержит три основных типа объектов - дату, время и дату и время.

import datetime

# Date object
today = datetime.date.today()
new_year = datetime.date(2017, 01, 01) #datetime.date(2017, 1, 1)

# Time object
noon = datetime.time(12, 0, 0) #datetime.time(12, 0)

# Current datetime
now = datetime.datetime.now()

# Datetime object
millenium_turn = datetime.datetime(2000, 1, 1, 0, 0, 0) #datetime.datetime(2000, 1, 1, 0, 0)

Арифметические операции для этих объектов поддерживаются только внутри одного и того же типа данных, и выполнение простой арифметики с экземплярами разных типов приведет к типу TypeError.

# subtraction of noon from today
noon-today
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: unsupported operand type(s) for -: 'datetime.time' and 'datetime.date'
However, it is straightforward to convert between types.

# Do this instead
print('Time since the millenium at midnight: ',
      datetime.datetime(today.year, today.month, today.day) - millenium_turn)

# Or this
print('Time since the millenium at noon: ',
      datetime.datetime.combine(today, noon) - millenium_turn)

Итерация по датам

Иногда вы хотите перебирать диапазон дат от даты начала до некоторой даты окончания. Вы можете сделать это с использованием библиотеки datetime и объекта timedelta :

import datetime

# The size of each step in days
day_delta = datetime.timedelta(days=1)

start_date = datetime.date.today()
end_date = start_date + 7*day_delta

for i in range((end_date - start_date).days):
    print(start_date + i*day_delta)

Что производит:

2016-07-21
2016-07-22
2016-07-23
2016-07-24
2016-07-25
2016-07-26
2016-07-27

Разбор строки с коротким именем часового пояса в объекте datetime, относящемся к часовому поясу

Используя библиотеку dateutil как в предыдущем примере, при разборе временных меток времени , можно также разобрать временные метки с указанным «коротким» именем часового пояса.

Для дат, отформатированных с короткими названиями зон или аббревиатурами, которые обычно неоднозначны (например, КНТ, которая может быть Центральным стандартным временем, Стандартным временем в Китае, Стандартным временем Кубы и т. Д. - здесь можно найти) или не обязательно доступна в стандартной базе данных , необходимо указать отображение между аббревиатурой часового пояса и объектом tzinfo .

from dateutil import tz
from dateutil.parser import parse

ET = tz.gettz('US/Eastern')
CT = tz.gettz('US/Central')
MT = tz.gettz('US/Mountain')
PT = tz.gettz('US/Pacific')

us_tzinfos = {'CST': CT, 'CDT': CT,
              'EST': ET, 'EDT': ET,
              'MST': MT, 'MDT': MT,
              'PST': PT, 'PDT': PT}

dt_est = parse('2014-01-02 04:00:00 EST', tzinfos=us_tzinfos)
dt_pst = parse('2016-03-11 16:00:00 PST', tzinfos=us_tzinfos)

После выполнения этого:

dt_est
# datetime.datetime(2014, 1, 2, 4, 0, tzinfo=tzfile('/usr/share/zoneinfo/US/Eastern'))
dt_pst
# datetime.datetime(2016, 3, 11, 16, 0, tzinfo=tzfile('/usr/share/zoneinfo/US/Pacific'))

Стоит отметить, что при использовании часового пояса pytz с этим методом он не будет правильно локализован:

from dateutil.parser import parse
import pytz

EST = pytz.timezone('America/New_York')
dt = parse('2014-02-03 09:17:00 EST', tzinfos={'EST': EST})

Это просто привязывает часовой пояс pytz к дате и времени:

dt.tzinfo # Will be in Local Mean Time!
# <DstTzInfo 'America/New_York' LMT-1 day, 19:04:00 STD>

Если вы используете этот метод, вы, вероятно, должны повторно localize наивную часть даты и времени после разбора:

dt_fixed = dt.tzinfo.localize(dt.replace(tzinfo=None))
dt_fixed.tzinfo # Now it's EST.
# <DstTzInfo 'America/New_York' EST-1 day, 19:00:00 STD>)

Построение временных дат, относящихся к часовому поясу

По умолчанию все объекты datetime наивны. Чтобы они были осведомлены о часовом поясе, вы должны прикрепить объект tzinfo , который обеспечивает сокращение UTC и сокращение временной зоны как функцию даты и времени.

Исправлены смещенные временные зоны

Для часовых поясов, которые являются фиксированным смещением от UTC, в Python 3.2+, модуль datetime предоставляет класс timezone , конкретную реализацию tzinfo , которая принимает параметр timedelta и (необязательный) name:

Python 3.x 3.2
from datetime import datetime, timedelta, timezone
JST = timezone(timedelta(hours=+9))

dt = datetime(2015, 1, 1, 12, 0, 0, tzinfo=JST)
print(dt)
# 2015-01-01 12:00:00+09:00

print(dt.tzname())
# UTC+09:00

dt = datetime(2015, 1, 1, 12, 0, 0, tzinfo=timezone(timedelta(hours=9), 'JST'))
print(dt.tzname)
# 'JST'

Для версий Python до 3.2 необходимо использовать стороннюю библиотеку, такую ​​как dateutil . dateutil предоставляет эквивалентный класс tzoffset , который ( tzoffset с версии 2.5.3) принимает аргументы формы dateutil.tz.tzoffset(tzname, offset) , где offset указано в секундах:

Python 3.x 3.2
Python 2.x 2.7
from datetime import datetime, timedelta
from dateutil import tz

JST = tz.tzoffset('JST', 9 * 3600) # 3600 seconds per hour
dt = datetime(2015, 1, 1, 12, 0, tzinfo=JST)
print(dt)
# 2015-01-01 12:00:00+09:00
print(dt.tzname)
# 'JST'

Зоны с летним временем

Для зон с летним временем стандартные стандартные библиотеки python не предоставляют стандартный класс, поэтому необходимо использовать стороннюю библиотеку. pytz и dateutil популярные библиотеки , обеспечивающие классы часовых поясов.

Помимо статических часовых поясов, dateutil предоставляет классы часовых поясов, которые используют летнее время (см. Документацию для модуля tz ). Вы можете использовать метод tz.gettz() для получения объекта часового пояса, который затем может быть передан непосредственно конструктору datetime :

from datetime import datetime
from dateutil import tz
local = tz.gettz() # Local time
PT = tz.gettz('US/Pacific') # Pacific time

dt_l = datetime(2015, 1, 1, 12, tzinfo=local) # I am in EST
dt_pst = datetime(2015, 1, 1, 12, tzinfo=PT)
dt_pdt = datetime(2015, 7, 1, 12, tzinfo=PT) # DST is handled automatically
print(dt_l)
# 2015-01-01 12:00:00-05:00
print(dt_pst)
# 2015-01-01 12:00:00-08:00
print(dt_pdt)
# 2015-07-01 12:00:00-07:00

ПРЕДУПРЕЖДЕНИЕ . Начиная с версии 2.5.3, dateutil обрабатывает неоднозначные даты и всегда будет по умолчанию для более поздней даты. dateutil построить объект с dateutil представляющим, например, 2015-11-01 1:30 EDT-4 , так как это происходит во время перехода на летнее время.

При использовании pytz все обработанные края обрабатываются должным образом, но часовые пояса pytz не должны быть непосредственно привязаны к часовым поясам через конструктор. Вместо этого временная зона pytz должна быть присоединена с использованием метода localize часового пояса:

from datetime import datetime, timedelta
import pytz

PT = pytz.timezone('US/Pacific')
dt_pst = PT.localize(datetime(2015, 1, 1, 12))
dt_pdt = PT.localize(datetime(2015, 11, 1, 0, 30))
print(dt_pst)
# 2015-01-01 12:00:00-08:00
print(dt_pdt)
# 2015-11-01 00:30:00-07:00

Имейте в виду, что если вы выполняете арифметику datetime в часовом поясе pytz -aware, вы должны либо выполнить вычисления в формате UTC (если хотите абсолютное истекшее время), либо вы должны вызвать normalize() для результата:

dt_new = dt_pdt + timedelta(hours=3) # This should be 2:30 AM PST
print(dt_new)
# 2015-11-01 03:30:00-07:00
dt_corrected = PT.normalize(dt_new)
print(dt_corrected)
# 2015-11-01 02:30:00-08:00

Нечеткий анализ времени и времени (извлечение даты и времени из текста)

Можно извлечь дату из текста, используя синтаксический анализатор dateutil в режиме «нечеткого», в котором компоненты строки, не признанной как часть даты, игнорируются.

from dateutil.parser import parse

dt = parse("Today is January 1, 2047 at 8:21:00AM", fuzzy=True)
print(dt)

dt теперь является объектом datetime и вы увидите datetime.datetime(2047, 1, 1, 8, 21) .

Переключение между часовыми поясами

Чтобы переключаться между часовыми поясами, вам нужны объекты datetime, которые имеют информацию о часовом поясе.

from datetime import datetime
from dateutil import tz

utc = tz.tzutc()
local = tz.tzlocal()

utc_now = datetime.utcnow()
utc_now # Not timezone-aware.

utc_now = utc_now.replace(tzinfo=utc)
utc_now # Timezone-aware.

local_now = utc_now.astimezone(local)
local_now # Converted to local time.

Разбор произвольной временной метки ISO 8601 с минимальными библиотеками

Python имеет ограниченную поддержку для разбора временных меток ISO 8601. Для strptime вам нужно точно знать, в каком формате он находится. В качестве осложнения строкой datetime является временная метка ISO 8601 с пространством в качестве разделителя и 6-разрядной фракцией:

str(datetime.datetime(2016, 7, 22, 9, 25, 59, 555555))
# '2016-07-22 09:25:59.555555'

но если фракция равна 0, дробная часть не выводится

str(datetime.datetime(2016, 7, 22, 9, 25, 59, 0))
# '2016-07-22 09:25:59'

Но эти 2 формы нуждаются в другом формате для strptime . Кроме того, strptime' does not support at all parsing minute timezones that have a : in it, thus 2016-07-22 09: 25: 59 + 0300 can be parsed, but the standard format 2016-07-22 09:25:59 +03: 00` не может.

Существует библиотека с одним файлом, называемая iso8601 которая правильно анализирует временные метки ISO 8601 и только их.

Он поддерживает дроби и часовые пояса, а T разделитель - с одной функцией:

import iso8601
iso8601.parse_date('2016-07-22 09:25:59')
# datetime.datetime(2016, 7, 22, 9, 25, 59, tzinfo=<iso8601.Utc>)
iso8601.parse_date('2016-07-22 09:25:59+03:00')
# datetime.datetime(2016, 7, 22, 9, 25, 59, tzinfo=<FixedOffset '+03:00' ...>)
iso8601.parse_date('2016-07-22 09:25:59Z')
# datetime.datetime(2016, 7, 22, 9, 25, 59, tzinfo=<iso8601.Utc>)
iso8601.parse_date('2016-07-22T09:25:59.000111+03:00')
# datetime.datetime(2016, 7, 22, 9, 25, 59, 111, tzinfo=<FixedOffset '+03:00' ...>)

Если часовой пояс не установлен, значение iso8601.parse_date соответствует UTC. Зона по умолчанию может быть изменена с помощью аргумента ключевого слова default_zone . Примечательно, что если вместо значения по умолчанию выбрано значение « None , тогда те временные метки, которые не имеют явного часового пояса, возвращаются вместо наивных datetimes:

iso8601.parse_date('2016-07-22T09:25:59', default_timezone=None)
# datetime.datetime(2016, 7, 22, 9, 25, 59)
iso8601.parse_date('2016-07-22T09:25:59Z', default_timezone=None)
# datetime.datetime(2016, 7, 22, 9, 25, 59, tzinfo=<iso8601.Utc>)

Преобразование временной метки в дату и время

Модуль datetime может преобразовать timestamp POSIX в объект datetime ИТЦ.

Эпоха - 1 января 1970 года в полночь.

import time
from datetime import datetime
seconds_since_epoch=time.time()  #1469182681.709

utc_date=datetime.utcfromtimestamp(seconds_since_epoch) #datetime.datetime(2016, 7, 22, 10, 18, 1, 709000)

Вычитание месяцев с даты точно

Использование модуля calendar

import calendar
from datetime import date

def monthdelta(date, delta):
    m, y = (date.month+delta) % 12, date.year + ((date.month)+delta-1) // 12
    if not m: m = 12
    d = min(date.day, calendar.monthrange(y, m)[1])
    return date.replace(day=d,month=m, year=y)

next_month = monthdelta(date.today(), 1) #datetime.date(2016, 10, 23)

Использование модуля dateutils

import datetime
import dateutil.relativedelta

d = datetime.datetime.strptime("2013-03-31", "%Y-%m-%d")
d2 = d - dateutil.relativedelta.relativedelta(months=1)  #datetime.datetime(2013, 2, 28, 0, 0)

Вычисление временных разниц

модуль timedelta пригодится для вычисления различий между временами:

from datetime import datetime, timedelta
now = datetime.now()
then = datetime(2016, 5, 23)     # datetime.datetime(2016, 05, 23, 0, 0, 0)

Указание времени является необязательным при создании нового объекта datetime

delta = now-then

delta имеет тип timedelta

print(delta.days)
# 60
print(delta.seconds)
# 40826

Чтобы получить n день после и n дней до даты, мы могли бы использовать:

n день после даты:

def get_n_days_after_date(date_format="%d %B %Y", add_days=120):

    date_n_days_after = datetime.datetime.now() + timedelta(days=add_days)
    return date_n_days_after.strftime(date_format)

n день до даты:

 def get_n_days_before_date(self, date_format="%d %B %Y", days_before=120):

        date_n_days_ago = datetime.datetime.now() - timedelta(days=days_before)
        return date_n_days_ago.strftime(date_format)

Получить временную метку ISO 8601

Без часовой пояс с микросекундами

from datetime import datetime

datetime.now().isoformat()
# Out: '2016-07-31T23:08:20.886783'

С часовым поясом, с микросекундами

from datetime import datetime
from dateutil.tz import tzlocal

datetime.now(tzlocal()).isoformat()
# Out: '2016-07-31T23:09:43.535074-07:00'

С часовым поясом, без микросекунд

from datetime import datetime
from dateutil.tz import tzlocal

datetime.now(tzlocal()).replace(microsecond=0).isoformat()
# Out: '2016-07-31T23:10:30-07:00'

См. ISO 8601 для получения дополнительной информации о формате ISO 8601.



Modified text is an extract of the original Stack Overflow Documentation
Лицензировано согласно CC BY-SA 3.0
Не связан с Stack Overflow