Время ISO (ISO 8601) в Python - PullRequest
       54

Время ISO (ISO 8601) в Python

220 голосов
/ 28 января 2010

У меня есть файл. В Python я хотел бы взять время его создания и преобразовать его в ISO time (ISO 8601) строку , сохранив тот факт, что он был создан в Восточном часовом поясе (ET) .

Как мне взять ctime файла и преобразовать его в строку времени ISO, которая указывает восточный часовой пояс (и учитывает летнее время, если необходимо)?

Ответы [ 11 ]

338 голосов
/ 26 января 2015

Локально по ISO 8601:

import datetime
datetime.datetime.now().isoformat()

UTC по ISO 8601:

import datetime
datetime.datetime.utcnow().isoformat()

Локально по ISO 8601 без микросекунды:

import datetime
datetime.datetime.now().replace(microsecond=0).isoformat()

UTC по ISO 8601 с информацией о часовом поясе (Python 3):

import datetime
datetime.datetime.utcnow().replace(tzinfo=datetime.timezone.utc).isoformat()

Локально по ISO 8601 с информацией о часовом поясе (Python 3):

import datetime, time

# Calculate the offset taking into account daylight saving time
utc_offset_sec = time.altzone if time.localtime().tm_isdst else time.timezone
utc_offset = datetime.timedelta(seconds=-utc_offset_sec)
datetime.datetime.now().replace(tzinfo=datetime.timezone(offset=utc_offset)).isoformat()

Для Python 2 см. И используйте pytz .

48 голосов
/ 28 февраля 2013

Я нашел datetime.isoformat в документации . Кажется, делать то, что вы хотите:

datetime.isoformat([sep])

Return a string representing the date and time in ISO 8601 format, YYYY-MM-DDTHH:MM:SS.mmmmmm or, if microsecond is 0, YYYY-MM-DDTHH:MM:SS

If utcoffset() does not return None, a 6-character string is appended, giving the UTC offset in (signed) hours and minutes: YYYY-MM-DDTHH:MM:SS.mmmmmm+HH:MM or, if microsecond is 0 YYYY-MM-DDTHH:MM:SS+HH:MM

The optional argument sep (default 'T') is a one-character separator, placed between the date and time portions of the result. For example,
>>>

>>> from datetime import tzinfo, timedelta, datetime
>>> class TZ(tzinfo):
...     def utcoffset(self, dt): return timedelta(minutes=-399)
...
>>> datetime(2002, 12, 25, tzinfo=TZ()).isoformat(' ')
'2002-12-25 00:00:00-06:39'
46 голосов
/ 16 декабря 2010

Представление времени ISO 8601

Международный стандарт ISO 8601 описывает строковое представление для даты и времени. Два простых примера этого формата:

2010-12-16 17:22:15
20101216T172215

(оба обозначают 16 декабря 2010 г.), но формат также допускает время разрешения менее секунды и указывает часовые пояса. Этот формат, конечно, не специфичен для Python, но подходит для хранения даты и времени в переносимом формате. Подробности об этом формате можно найти в записи Markus Kuhn .

Я рекомендую использовать этот формат для хранения времени в файлах.

Один из способов получить текущее время в этом представлении - использовать strftime из модуля времени в стандартной библиотеке Python:

>>> from time import strftime
>>> strftime("%Y-%m-%d %H:%M:%S")
'2010-03-03 21:16:45'

Вы можете использовать конструктор strptime класса datetime:

>>> from datetime import datetime
>>> datetime.strptime("2010-06-04 21:08:12", "%Y-%m-%d %H:%M:%S")
datetime.datetime(2010, 6, 4, 21, 8, 12)

Самым надежным является модуль Egenix mxDateTime:

>>> from mx.DateTime.ISO import ParseDateTimeUTC
>>> from datetime import datetime
>>> x = ParseDateTimeUTC("2010-06-04 21:08:12")
>>> datetime.fromtimestamp(x)
datetime.datetime(2010, 3, 6, 21, 8, 12)

Ссылки

45 голосов
/ 30 ноября 2015

Вот что я использую для преобразования в формат даты и времени XSD:

from datetime import datetime
datetime.now().replace(microsecond=0).isoformat()
# You get your ISO string

Я сталкивался с этим вопросом, когда искал формат даты и времени XSD (xs:dateTime). Мне нужно было удалить микросекунды с isoformat.

16 голосов
/ 28 ноября 2015

В формате времени ISO 8601 не хранится имя часового пояса, сохраняется только соответствующее смещение UTC.

Чтобы преобразовать файл ctime в строку времени ISO 8601 с сохранением смещения UTC в Python 3:

>>> import os
>>> from datetime import datetime, timezone
>>> ts = os.path.getctime(some_file)
>>> dt = datetime.fromtimestamp(ts, timezone.utc)
>>> dt.astimezone().isoformat()
'2015-11-27T00:29:06.839600-05:00'

Код предполагает, что ваш местный часовой пояс равен Восточный часовой пояс (ET) и что ваша система предоставляет правильное смещение UTC для данной временной метки POSIX (ts), т. Е. Python имеет доступ к База данных исторического часового пояса в вашей системе или часовой пояс имели те же правила на указанную дату.

Если вам нужно портативное решение; использовать pytz модуль , который обеспечивает доступ к базе данных tz :

>>> import os
>>> from datetime import datetime
>>> import pytz  # pip install pytz
>>> ts = os.path.getctime(some_file)
>>> dt = datetime.fromtimestamp(ts, pytz.timezone('America/New_York'))
>>> dt.isoformat()
'2015-11-27T00:29:06.839600-05:00'

Результат в этом случае тот же.

Если вам нужно название / аббревиатура / идентификатор часового пояса, сохраните его отдельно.

>>> dt.astimezone().strftime('%Y-%m-%d %H:%M:%S%z (%Z)')
'2015-11-27 00:29:06-0500 (EST)'

Примечание: нет, : в смещении UTC и EST сокращение часового пояса не является частью формата времени ISO 8601. Это не уникальный.

Разные библиотеки / разные версии одной и той же библиотеки могут использовать разные правила часового пояса для одной и той же даты / часового пояса. Если это будущая дата, то правила могут быть еще неизвестны. Другими словами, одно и то же время UTC может соответствовать разному местному времени, в зависимости от того, какие правила вы используете - сохранение времени в формате ISO 8601 сохраняет время UTC и местное время, которое соответствует часовому поясу current правила, используемые на вашей платформе. Возможно, вам придется пересчитать местное время на другой платформе, если у нее другие правила.

13 голосов
/ 28 января 2010

Вам нужно будет использовать os.stat для получения времени создания файла и комбинацию time.strftime и time.timezone для форматирования:

>>> import time
>>> import os
>>> t = os.stat('C:/Path/To/File.txt').st_ctime
>>> t = time.localtime(t)
>>> formatted = time.strftime('%Y-%m-%d %H:%M:%S', t)
>>> tz = str.format('{0:+06.2f}', float(time.timezone) / 3600)
>>> final = formatted + tz
>>> 
>>> final
'2008-11-24 14:46:08-02.00'
9 голосов
/ 05 сентября 2018

ISO 8601 допускает компактное представление без разделителей, кроме T, поэтому я хотел бы использовать этот однострочный для получения быстрой строки метки времени:

>>> datetime.datetime.utcnow().strftime("%Y%m%dT%H%M%S.%fZ")
'20180905T140903.591680Z'

Если вам не нужны микросекунды, просто пропустите .%f часть:

>>> datetime.datetime.utcnow().strftime("%Y%m%dT%H%M%SZ")
'20180905T140903Z'

По местному времени:

>>> datetime.datetime.now().strftime("%Y%m%dT%H%M%S")
'20180905T140903'
4 голосов
/ 08 июня 2010

Поправьте меня, если я ошибаюсь (я не ошибаюсь), но смещение от UTC меняется с переходом на летнее время. Поэтому вы должны использовать

tz = str.format('{0:+06.2f}', float(time.altzone) / 3600)

Я также считаю, что знак должен быть другим:

tz = str.format('{0:+06.2f}', -float(time.altzone) / 3600)

Я могу ошибаться, но я так не думаю.

2 голосов
/ 27 октября 2010

Я согласен с Яреком и, кроме того, отмечаю, что символ разделителя смещения ISO является двоеточием, поэтому я думаю, что окончательный ответ должен быть:

isodate.datetime_isoformat(datetime.datetime.now()) + str.format('{0:+06.2f}', -float(time.timezone) / 3600).replace('.', ':')
0 голосов
/ 08 ноября 2016

Я разработал эту функцию:

def iso_8601_format(dt):
    """YYYY-MM-DDThh:mm:ssTZD (1997-07-16T19:20:30-03:00)"""

    if dt is None:
        return ""

    fmt_datetime = dt.strftime('%Y-%m-%dT%H:%M:%S')
    tz = dt.utcoffset()
    if tz is None:
        fmt_timezone = "+00:00"
    else:
        fmt_timezone = str.format('{0:+06.2f}', float(tz.total_seconds() / 3600))

    return fmt_datetime + fmt_timezone
...