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

Имам досие. В Python бих искал да взема времето за създаване и да го конвертирам в низ ISO time (ISO 8601) като се запазва фактът, че е създаден в източната часова зона (ET ).

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


person Joseph Turian    schedule 27.01.2010    source източник
comment
възможен дубликат на Как превеждам ли низ за дата и час ISO 8601 в обект за дата и час на Python?   -  person Nick Johnson    schedule 13.06.2010
comment
@Ник- Полезна връзка, но не е дубликат - той пита за конвертиране в другата посока.   -  person Yarin    schedule 19.12.2011
comment
@Joseph- Току-що попитах това във връзка с RFC 3999- трябва да работи за това - Генериране на RFC 3339 клеймо за време в Python   -  person Yarin    schedule 19.12.2011


Отговори (13)


Локално към 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 с информация за часовата зона (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 време. Това дава неправилен резултат:

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

За Python 2 вижте и използвайте pytz.

person estani    schedule 26.01.2015
comment
.isoformat() може да приеме параметър за разделител (в случай, че искате нещо различно от 'T'): .isoformat(' ') - person ThorSummoner; 25.08.2016
comment
@ThorSummoner добре е да знаете! Но внимавайте, че промяната на разделителя вече няма да отговаря на ISO-8601... което няма смисъл (освен това има по-добри начини за отпечатване на дати, но това не беше въпросът тук). RFC - person estani; 25.08.2016
comment
Пространството е разрешено като част от стандарта ISO-8601. It is permitted to omit the 'T' character by mutual agreement. - person raychi; 07.09.2016
comment
@raychi Винаги е позволено да се промени стандарт по взаимно съгласие (което в много случаи ще наруши стандарта, но на кого му пука дали е взаимно съгласие, нали?). Моят 2c: просто недейте, оставете го както е. - person estani; 08.09.2016
comment
Този отговор е грешен, защото datetime.datetime.now().isoformat() връща локален низ ISO 8601, без да го обозначава като локален. Трябва да имате datetime.timezone, представляващ местната часова зона, за да получите изоформат, за да направите правилното нещо. - person Sam Hartman; 01.05.2017
comment
Изглежда, че offset=utc_offset_sec трябва да се замени с offset=datetime.timedelta(seconds=-utc_offset_sec) - person imbolc; 06.04.2018
comment
Разделът Local to ISO-8601 with TimeZone info (python 3) може да бъде подобрен чрез използване на: datetime.datetime.now(datetime.timezone(datetime.timedelta(seconds=time.localtime().tm_gmtoff))).isoformat(). Няма нужда да заменяте tzinfo, когато можете да го предадете на now, а проблемът altzone се разрешава с помощта на tm_gmtoff. - person ToBeReplaced; 14.07.2018
comment
Как да получа формата на ISO-8601 в Python? Защото трябва да strptime низа. %Y-%m-%dT%H:%M:%S%z връща -HHMM или +HHMM, но не и -HH:MM. - person Simin Jie; 08.08.2018
comment
UTC към ISO-8601 с информация за часовата зона (използва pytz) datetime.datetime.now(tz=pytz.utc).isoformat() - person Christian Long; 06.09.2018
comment
но другото ми време за приложение на javascript е във формат 2019-02-23T04:01:55.360Z, Z за отместване на нула часа, няма ли опция за този формат? - person Miranda; 25.02.2019
comment
UTC към ISO-8601 с информация за часовата зона (Python 3, без pytz): datetime.datetime.now(tz=datetime.timezone.utc).isoformat() - person Vinod Kurup; 05.09.2019
comment
Пропускането на „T“ не променя стандарта, тъй като той е част от стандарта ISO 8601. - person tomsv; 23.11.2019
comment
Преминах през лоши моменти с datetime.replace(tzinfo)! Бих казал: избягвайте го! Добавя минути между реализациите. Използвайте pytz.localize() вместо това. Вижте повече тук. - person Renato Aloi; 17.06.2021

Ето какво използвам за преобразуване във формата за дата и час XSD:

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

Попаднах на този въпрос, когато търсех XSD формат за дата и час (xs:dateTime). Трябваше да премахна микросекундите от isoformat.

person radtek    schedule 30.11.2015
comment
Какво е XSD (в този контекст)? - person Peter Mortensen; 24.10.2018
comment
Вярвам, че има предвид xs:date от XSD / XML таблици със стилове. - person sventechie; 17.11.2018
comment
Това означава xs:dateTime - person radtek; 19.11.2018

ISO 8601 Представяне на времето

Международният стандарт ISO 8601 описва низово представяне за дати и часове. Два прости примера за този формат са

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

(и двете означават 16 декември 2010 г.), но форматът също така позволява разделителна способност под секунди и указване на часови зони. Този формат, разбира се, не е специфичен за Python, но е добър за съхраняване на дати и часове в преносим формат. Подробности за този формат можете да намерите в запис на Маркус Кун .

Препоръчвам използването на този формат за съхраняване на времена във файлове.

Един от начините да получите текущото време в това представяне е да използвате 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)

Референции

person Voislav Sauca    schedule 16.12.2010
comment
В какъв смисъл е по-здрав? - person Stéphane; 29.07.2017
comment
Дата: 2018-05-25 - person loxaxs; 25.05.2018
comment
Комбинирани дата и час в UTC: 2018-05-25T12:16:14+00:00 - person loxaxs; 25.05.2018
comment
Комбинирани дата и час в UTC: 2018-05-25T12:16:14Z - person loxaxs; 25.05.2018
comment
Комбинирани дата и час в UTC: 20180525T121614Z - person loxaxs; 25.05.2018
comment
как да създадете тази комбинирана дата и час в UTC: 2018-05-25T12:16:14Z @Ioxaxs - person Khan; 01.12.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'

Редактиране:

След като прочетете това още малко, препоръчвам ви да оставите препинателните знаци. RFC 3339 препоръчва този стил защото ако всички използват препинателни знаци, няма риск неща като множество низове ISO 8601 да бъдат сортирани в групи по тяхната пунктуация. Така че единият ред за съвместим низ ще бъде:

>>> datetime.datetime.now().strftime("%Y-%m-%dT%H:%M:%SZ")
'2018-09-05T14:09:03Z'
person Jim Hunziker    schedule 05.09.2018
comment
има ли начин да се ограничат цифрите от милисекунди до 3? т.е. другото ми javascript приложение ще произведе 2019-02-23T04:02:04.051Z с new Date().toISOString() - person Miranda; 25.02.2019
comment
Предупреждение: „Z“ в края е неправилно. Правилният начин за извеждане на часовата зона, включително символа 'Z', е '%z' или '%Z', което го прави 'datetime.datetime.now().strftime(%Y-%m-%dT%H: %M:%S%z)'. Прекарах 2 часа в опити да намеря грешка в моя код... - person Dr_Zaszuś; 31.07.2020
comment
@Dr_Zaszuś Това не е правилно. %z генерира отместване на часовата зона за вашето местно време, което не е това, което препоръчвам за времеви марки, особено ако разглеждате множество системи. Буквалът Z е ISO 8601 стенограма за UTC. - person Jim Hunziker; 03.08.2020
comment
@Miranda javascript като изход datetime.datetime.now(datetime.timezone.utc).isoformat()[:23]+Z - person seizu; 03.04.2021

Намерих 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'
person user2120810    schedule 28.02.2013

форматът за час 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 времето и местното време, което съответства на текущото време правила на зоната, използвани на вашата платформа. Може да се наложи да преизчислите местното време на друга платформа, ако има различни правила.

person jfs    schedule 28.11.2015

Ще трябва да използвате 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'
person Max Shawabkeh    schedule 27.01.2010
comment
Отчита ли часовата зона лятното часово време? Изглежда, че tz ще бъде същото, независимо от лятното часово време или не. - person Joseph Turian; 29.01.2010
comment
Това ще бъде каквото и да е компенсиране, което е в сила в момента. Ако лятното часово време е активно, то ще има различно отместване от това, когато лятното часово време не е. - person Max Shawabkeh; 29.01.2010

За тези, които търсят решение само за дати, това е:

import datetime

datetime.date.today().isoformat()
person Alexander Zinchuk    schedule 14.09.2020
comment
В крайна сметка го направих по този начин, за да избегна импортирането на повече от класа datetime: from datetime import datetime; datetime.now().isoformat()[:10] (за съжаление не мога да намеря кодовия фрагмент) - person David Elgstuen; 15.07.2021

Поправете ме, ако греша (не съм), но отместването спрямо UTC се променя с лятното часово време. Така че трябва да използвате

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

Аз също вярвам, че знакът трябва да е различен:

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

Може и да греша, но не мисля така.

person Jarek Przygódzki    schedule 08.06.2010

Съгласен съм с Jarek и освен това отбелязвам, че знакът за разделител на отместване на ISO е двоеточие, така че мисля, че крайният отговор трябва да бъде:

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

Добавяне на малка вариация към отличния отговор на estani

Локално към 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

person Sharpiro    schedule 06.11.2019

Стандартен RFC-3339 в милисекунди

Имах нужда от време в този формат за LoRa приложение, така че измислих това, надявам се да помогне:

from datetime import datetime
from time import strftime


# Get the current time in the format: 2021-03-20T16:51:23.644+01:00
def rfc3339_time_ms():
        datetime_now = datetime.utcnow()
        # Remove the microseconds
        datetime_now_ms = datetime_now.strftime("%Y-%m-%dT%H:%M:%S.%f")[:-3]
        # Add the timezone as "+/-HHMM", and the colon in "+/-HH:MM"
        datetime_now_ms_tz = datetime_now_ms + strftime("%z")
        rfc3339_ms_now = datetime_now_ms_tz[:-2] + ":" + datetime_now_ms_tz[-2:]
        # print(f"Current time in ms in RFC-3339 format: {rfc3339_ms_now}")
        return rfc3339_ms_now
person chronoclast    schedule 20.03.2021

Разработих тази функция:

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
person Andre Avilla    schedule 08.11.2016