Python'da ISO zamanı (ISO 8601)


340

Bir dosyam var. Python'da, Doğu Saat Dilimi'nde (ET) yaratıldığı gerçeği korurken , oluşturma zamanını almak ve ISO zamanına (ISO 8601) dönüştürmek istiyorum .

Dosyanın saatini nasıl alıp Doğu Saat Dilimi'ni gösteren bir ISO saat dizesine nasıl dönüştürebilirim (ve gerekirse gün ışığından yararlanma saatini dikkate alır)?



11
@ Nick- Yararlı bağlantı, ama bir kopya değil- diğer yolu dönüştürmek istiyor.
Yarin

1
@ Joseph- Ben sadece RFC 3999 ile ilgili olarak sordum-bunun için çalışması gerekir - Python RFC 3339 zaman damgası
Yarin

Yanıtlar:


560

ISO 8601'e göre yerel:

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

Mikrosaniye olmadan ISO 8601'e yerel:

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

UTC ile TimeZone bilgilerini içeren ISO 8601 (Python 3):

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

UTC, mikro saniye olmadan Yerel TimeZone bilgileriyle ISO 8601'e (Python 3):

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

TimeZone bilgileriyle (Python 3) ISO 8601'e yerel:

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

astimezone()Utc zamanında kullanırken bir hata olduğuna dikkat edin . Bu yanlış bir sonuç verir:

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

Python 2 için, bkz . Pytz .


17
.isoformat()ayırıcı parametresi alabilir, ('T' dışında bir şey istiyorsanız):.isoformat(' ')
ThorSummoner

5
@ThorSummoner bilmek güzel! Ancak ayırıcıyı değiştirmenin artık ISO-8601 ile uyumlu olmayacağına dikkat edin ... bu çok az mantıklıdır (ayrıca, tarih yazdırmanın daha iyi yolları vardır, ancak buradaki soru bu değildi). RFC
estani

4
ISO-8601 standardının bir parçası olarak alana izin verilir. It is permitted to omit the 'T' character by mutual agreement.
raychi

4
@raychi Bir standardı karşılıklı anlaşma ile değiştirmeye her zaman izin verilir (çoğu durumda standardı kıracaktır, ancak karşılıklı anlaşma olup olmadığını kimin umurunda?). Benim 2c: sadece yapma, olduğu gibi bırak.
estani

14
Bu cevap yanlıştır, çünkü datetime.datetime.now (). İsoformat (), yerel olarak etiketlenmeden yerel bir ISO 8601 dizesi döndürür. Doğru şeyi yapmak için izoformat almak için yerel saat dilimini temsil eden bir datetime.timezone'a sahip olmanız gerekir.
Sam Hartman

66

İşte XSD datetime biçimine dönüştürmek için kullandığım şey:

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

XSD tarih saat biçimini ( xs:dateTime) ararken bu soruyla karşılaştım . Mikrosaniyeleri kaldırmam gerekiyordu isoformat.


4
"XSD" nedir (bu bağlamda)?
Peter Mortensen

1
Ben onun xs:dateXSD / XML stil sayfalarından demek istediğine inanıyorum .
sventechie

1
Bunun anlamıxs:dateTime
radtek

56

ISO 8601 Zaman Gösterimi

Uluslararası ISO 8601 standardı, tarihler ve saatler için bir dize temsilini açıklar. Bu formatın iki basit örneği:

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

(her ikisi de 16 Aralık 2010 anlamına gelir), ancak biçim aynı zamanda ikinci saniyenin altında çözüm sürelerine ve saat dilimlerinin belirlenmesine de olanak tanır. Bu biçim elbette Python'a özgü değildir, ancak tarihleri ​​ve saatleri taşınabilir bir biçimde saklamak için iyidir. Bu formatla ilgili ayrıntılar Markus Kuhn girişinde bulunabilir. .

Dosyalarda zaman saklamak için bu formatın kullanılmasını öneririm.

Bu gösterimde geçerli saati almanın bir yolu, Python standart kitaplığındaki zaman modülünden strftime kullanmaktır:

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

Datetime sınıfının strptime yapıcısını kullanabilirsiniz:

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

En sağlam Egenix mxDateTime modülü:

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

Referanslar


2
Hangi anlamda "daha sağlam"?
Stéphane

Date:2018-05-25
loxaxs

UTC'de birleştirilmiş tarih ve saat:2018-05-25T12:16:14+00:00
loxaxs

2
UTC'de birleştirilmiş tarih ve saat:2018-05-25T12:16:14Z
loxaxs

UTC'de birleştirilmiş tarih ve saat:20180525T121614Z
loxaxs

49

Belgede datetime.isoformat dosyasını buldum . İstediğinizi yapıyor gibi görünüyor:

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 dışında hiçbir ayırıcı ile kompakt bir temsil sağlar T, bu yüzden hızlı bir zaman damgası dize almak için bu tek astar kullanmak istiyorum:

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

Mikrosaniyeye ihtiyacınız yoksa, sadece .%fparçayı dışarıda bırakın :

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

Yerel saat için:

>>> datetime.datetime.now().strftime("%Y%m%dT%H%M%S")
'20180905T140903'

Düzenle:

Bunu biraz daha okuduktan sonra, noktalama işaretlerini bırakmanızı öneririm. RFC 3339 bu stili önerir çünkü herkes noktalama işareti kullanıyorsa, noktalama işaretlerinde gruplar halinde sıralanan birden fazla ISO 8601 dizesi gibi şeyler riski yoktur. Dolayısıyla, uyumlu bir dize için tek astar:

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

3
milisaniye rakamlarını 3 ile sınırlamanın bir yolu var mı? yani benim diğer javascript uygulaması 2019-02-23T04:02:04.051Zile üreteceknew Date().toISOString()
Miranda

19

ISO 8601 saat biçimi bir zaman dilimi adını saklamaz, sadece karşılık gelen UTC korunur ofset.

Python 3'teki UTC ofsetini korurken bir dosya ctime değerini ISO 8601 zaman dizesine dönüştürmek için:

>>> 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'

Kod, yerel saat diliminizin Doğu Saat Dilimi (ET) olduğunu ve sisteminizin belirtilen POSIX zaman damgası (ts ) yani, Python'un sisteminizdeki veya saat dilimindeki geçmiş bir saat dilimi veritabanına erişimi vardır. belirli bir tarihte aynı kurallar.

Taşınabilir bir çözüme ihtiyacınız varsa; tz veritabanına erişim sağlayan modülü kullanınpytz :

>>> 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'

Bu durumda sonuç aynıdır.

Saat dilimi adına / kısaltması / bölge kimliğine ihtiyacınız varsa, ayrı olarak saklayın.

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

Not: hayır, :UTC ofseti ve ESTsaat dilimi kısaltması ISO 8601 saat biçiminin bir parçası değildir. Benzersiz değil.

Aynı kitaplığın farklı kitaplıkları / farklı sürümleri aynı tarih / saat dilimi için farklı saat dilimi kuralları kullanabilir. Gelecek bir tarihse, kurallar henüz bilinmiyor olabilir. Başka bir deyişle, kullandığınız kurallara bağlı olarak aynı UTC saati farklı bir yerel saate karşılık gelebilir - ISO 8601 biçiminde bir zaman kaydetmek UTC saatini ve platformunuzda kullanılan geçerli saat dilimi kurallarına karşılık gelen yerel saati korur . Farklı kuralları varsa, yerel saati farklı bir platformda yeniden hesaplamanız gerekebilir.


14

os.statDosya oluşturma zamanını ve biçimlendirme için time.strftimeve bunların bir kombinasyonunu almak için kullanmanız gerekir 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'

Saat dilimi yaz saatini hesaba katıyor mu? Gün ışığından yararlanma zamanından bağımsız olarak tz aynı olacak gibi görünüyor.
Joseph Turian

2
Şu anda geçerli olan ofset olacaktır. DST etkinse, DST olmadığından farklı bir ofsete sahip olacaktır.
Max Shawabkeh

4

Yanılıyorsam beni düzeltin (değilim), ancak UTC'nin ofseti gün ışığından yararlanma saati ile değişir. Yani kullanmalısın

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

Ayrıca işaretin farklı olması gerektiğine inanıyorum:

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

Yanlış olabilirdim, ama sanmıyorum.


2

Jarek ile aynı fikirdeyim ve ayrıca ISO ofset ayırıcı karakterinin iki nokta üst üste olduğunu unutmayın, bu yüzden son cevabın şöyle olması gerektiğini düşünüyorum:

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

2

Estani'nin mükemmel cevabına küçük bir varyasyon eklemek

Mikrosaniye bilgisi olmadan ve TimeZone ile ISO 8601 için yerel (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()

Örnek Çıktı:

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

Bu çıktının hem Javascript hem de DateC # DateTime/ tarafından ayrıştırılabileceği test edildiDateTimeOffset


1

Bu işlevi geliştirdim:

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
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.