Час ISO (ISO 8601) у Python


340

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

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



11
@ Nick - Корисне посилання, але не дублікат - він запитує про перетворення іншим способом.
Ярін

1
@ Джозеф. Я щойно запитав це стосовно RFC 3999-, чи варто працювати на це - Створіть мітку часу RFC 3339 на Python
Ярін

Відповіді:


560

Місцеве значення ISO 8601:

import datetime
datetime.datetime.now().isoformat()
>>> 2020-03-20T14:28:23.382748

UTC до ISO 8601:

import datetime
datetime.datetime.utcnow().isoformat()
>>> 2020-03-20T01:30:08.180856

Місцеве значення ISO 8601 без мікросекунди:

import datetime
datetime.datetime.now().replace(microsecond=0).isoformat()
>>> 2020-03-20T14:30:43

UTC до ISO 8601 з інформацією про TimeZone (Python 3):

import datetime
datetime.datetime.utcnow().replace(tzinfo=datetime.timezone.utc).isoformat()
>>> 2020-03-20T01:31:12.467113+00:00

UTC до ISO 8601 з інформацією про локальну часову зону без мікросекунди (Python 3):

import datetime
datetime.datetime.now().astimezone().replace(microsecond=0).isoformat()
>>> 2020-03-20T14:31:43+13:00

Місцеве значення ISO 8601 з інформацією про TimeZone (Python 3):

import datetime
datetime.datetime.now().astimezone().isoformat()
>>> 2020-03-20T14:32:16.458361+13:00

Зауважте, що під час використання astimezone()utc time використовується помилка . Це дає неправильний результат:

datetime.datetime.utcnow().astimezone().isoformat() #Incorrect result

Для Python 2 див. Та використовуй pytz .


17
.isoformat()Ви можете взяти параметр роздільника, (Якщо ви хочете щось, крім 'T'):.isoformat(' ')
ThorSummoner

5
@ThorSummoner корисно знати! Але слідкуйте за тим, щоб зміна сепаратора більше не відповідала ISO-8601 ... що мало сенсу (до того ж, існують кращі способи друкувати дати, але тут питання не в цьому). RFC
estani

4
Місце допускається як частина стандарту ISO-8601. It is permitted to omit the 'T' character by mutual agreement.
райчі

4
@raychi Завжди дозволяється змінювати стандарт за взаємною згодою (що в багатьох випадках порушить стандарт, але кого це хвилює, якщо це взаємна згода, правда?). Мій 2с: просто не варто, залишайте це як є.
Естані

14
Ця відповідь неправильна, оскільки datetime.datetime.now (). Isoformat () повертає локальну рядок ISO 8601, не позначаючи її як локальну. Потрібно мати datetime.timezone, що представляє локальний часовий пояс, щоб отримати ізоформат, щоб зробити все правильно.
Сем Хартман

66

Ось що я використовую для перетворення у формат дати XSD:

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

Я зіткнувся з цим питанням, шукаючи формат часу XSD дати ( xs:dateTime). Мені потрібно було зняти мікросекунди з isoformat.


4
Що таке "XSD" (у цьому контексті)?
Пітер Мортенсен

1
Я вважаю, що він має на увазі xs:dateз таблиць стилів XSD / XML.
sventechie

1
Це означаєxs:dateTime
radtek

56

Час представлення ISO 8601

Міжнародний стандарт ISO 8601 описує рядкове подання для дат і часу. Два простих приклади цього формату

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

(який обидва виступають на 16 грудня 2010 р.), але формат також дозволяє передбачити час роздільної здатності на другої секунди та вказати часові пояси. Цей формат, звичайно, не стосується Python, але він хороший для зберігання дат і часів у портативному форматі. Докладніше про цей формат можна знайти у статті Маркуса Куна .

Я рекомендую використовувати цей формат для зберігання разів у файлах.

Один із способів отримати поточний час у цьому поданні - це використовувати стропіл з модуля часу в стандартній бібліотеці 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)

Список літератури


2
У якому сенсі він "надійніший"?
Стефан

Дата:2018-05-25
loxaxs

Об’єднана дата та час у UTC:2018-05-25T12:16:14+00:00
loxaxs

2
Об’єднана дата та час у UTC:2018-05-25T12:16:14Z
loxaxs

Об’єднана дата та час у UTC:20180525T121614Z
loxaxs

49

Я знайшов 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'

30

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'

Редагувати:

Ознайомившись із цим питанням, я рекомендую залишити пунктуацію. RFC 3339 рекомендує цей стиль, оскільки якщо всі використовують пунктуацію, немає ризику, щоб речі, наприклад, кілька рядків ISO 8601, були відсортовані за групами за їх пунктуацією. Отже, один вкладиш для сумісної рядка буде:

>>> datetime.datetime.now().strftime("%Y-%m-%dT%H:%M%SZ")
'2018-09-05T14:09:03Z'

3
чи є спосіб обмежити цифри мілісекунд до 3? тобто мій інший додаток Javascript буде виробляти 2019-02-23T04:02:04.051Zзnew Date().toISOString()
Міранда,

19

Формат часу 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 та місцевий час, що відповідає поточним правилам часового поясу, які використовуються на вашій платформі . Можливо, вам доведеться перерахувати місцевий час на іншій платформі, якщо він має різні правила.


14

Вам потрібно буде використовувати 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'

Чи враховує часовий пояс літній час? Здається, що tz буде однаково незалежно від літнього часу чи ні.
Йосиф Туріан

2
Це буде будь-яке зміщення, що діє на даний момент. Якщо DST активний, воно буде відрізнятися від того, коли DST не є.
Макс Шавабке

4

Виправте мене, якщо я помиляюся (я не так), але зміщення від UTC змінюється з літнім часом. Тож вам слід користуватися

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

Я також вважаю, що знак повинен бути іншим:

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

Я можу помилитися, але не думаю.


2

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

isodate.datetime_isoformat(datetime.datetime.now()) + str.format('{0:+06.2f}', -float(time.timezone) / 3600).replace('.', ':')

2

Додавши невелику варіацію до відмінної відповіді Естані

Місцеве значення ISO 8601 з TimeZone та відсутністю інформації про мікросекунди (Python 3):

import datetime, 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(microsecond=0, tzinfo=datetime.timezone(offset=utc_offset)).isoformat()

Вибірка зразка:

'2019-11-06T12:12:06-08:00'

Випробувано, що цей вихід може бути проаналізований як Javascript, так Dateі C # DateTime/DateTimeOffset


1

Я розробив цю функцію:

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

-6
import datetime, time    
def convert_enddate_to_seconds(self, ts):
    """Takes ISO 8601 format(string) and converts into epoch time."""
     dt = datetime.datetime.strptime(ts[:-7],'%Y-%m-%dT%H:%M:%S.%f')+\
                datetime.timedelta(hours=int(ts[-5:-3]),
                minutes=int(ts[-2:]))*int(ts[-6:-5]+'1')
    seconds = time.mktime(dt.timetuple()) + dt.microsecond/1000000.0
    return seconds 

>>> import datetime, time
>>> ts = '2012-09-30T15:31:50.262-08:00'
>>> dt = datetime.datetime.strptime(ts[:-7],'%Y-%m-%dT%H:%M:%S.%f')+ datetime.timedelta(hours=int(ts[-5:-3]), minutes=int(ts[-2:]))*int(ts[-6:-5]+'1')
>>> seconds = time.mktime(dt.timetuple()) + dt.microsecond/1000000.0
>>> seconds
1348990310.26
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.