Работа с датой и временем в Python

Введение

Примеры

  • 7

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

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

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

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

    Для других версий Python, вы можете использовать внешнюю библиотеку , такие как dateutil , что делает разбор строки с временной зоной в datetime и 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))
    
     
  • 1

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

    Даты не существуют в изоляции. Как правило, вам нужно будет определить количество времени между датами или определить, какая дата будет завтра. Это может быть осуществлено с использованием 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
    
    
    
    
     
  • 2

    Основное использование объектов даты и времени

    Модуль datetime содержит три основных типа объектов - date, time и 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) 
  • 0

    Итерировать по датам

    Иногда вы хотите перебрать диапазон дат от даты начала до даты окончания. Вы можете сделать это с помощью 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 
  • 0

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

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

    Для дат , отформатированных с именами зон короткое время или сокращений, которые , как правило , неоднозначны (например , CST, которые могут быть Central Standard Time, Китай Стандартное время, Куба Стандартное время и т.д. - больше можно найти здесь ) или не обязательно имеется в стандартной базе данных , необходимо указать соответствие между временной зоной и аббревиатурой 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 часовой пояс на DateTime:

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

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

     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>) 
  • 3

    Построение даты / времени с учетом часового пояса

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

    Фиксированное смещение часовых поясов

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

    из datetime импорт datetime, timedelta, timezone JST = часовой пояс (timedelta (часы = + 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 , который (в версии 2.5.3) принимает аргументы вида dateutil.tz.tzoffset(tzname, offset) , где offset задается в секундах:

    из datetime импорт datetime, timedelta из dateutil import tz JST = tz.tzoffset ('JST', 9 * 3600) # 3600 секунд в час dt = datetime (2015, 1, 1, 12, 0, tzinfo = JST) печать (dt ) # 2015-01-01 12: 00: 00 + 09: 00 print (dt.tzname) # 'JST'

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

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

    В дополнении к статическим часовым поясам, dateutil обеспечивает классы часовых поясов , которые используют летнее время (см документации для tz модуля ). Вы можете использовать tz.gettz() метод , чтобы получить объект часового пояса, который затем может быть передан непосредственно к datetime и 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 не обрабатывает неоднозначные DateTimes правильно, и всегда будет по умолчанию на более поздний срок. Там нет никакого способа построить объект с 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 
  • 0

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

    Можно извлечь дату из текста , используя 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) печатается.

  • 1

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

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

     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. 
  • 0

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

    В Python ограничена поддержка парсинга меток времени ISO 8601. Для strptime вы должны точно знать , в каком формате это в качестве осложнения stringification из. 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 can be parsed, but the standard format 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 9: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>) 
  • 1

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

    datetime модуль может преобразовать POSIX timestamp к ITC datetime и 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) 
  • 1

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

    Использование 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) 
  • 2

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

    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)
    
     

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

      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) 
  • 0

    Получите метку времени 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.

Синтаксис

Параметры

Примечания