Waktu ISO (ISO 8601) dengan Python

Saya punya file. Dengan Python, saya ingin mengambil waktu pembuatannya, dan mengonversinya menjadi string waktu ISO (ISO 8601) sambil menjaga fakta bahwa itu dibuat di Zona Waktu Timur (ET ).

Bagaimana cara mengambil waktu file dan mengonversinya menjadi string waktu ISO yang menunjukkan Zona Waktu Timur (dan memperhitungkan waktu musim panas, jika perlu)?


person Joseph Turian    schedule 27.01.2010    source sumber
comment
kemungkinan duplikat How cara menerjemahkan string datetime ISO 8601 menjadi objek datetime Python?   -  person Nick Johnson    schedule 13.06.2010
comment
@Nick- Tautan yang berguna, tetapi bukan duplikat- dia bertanya tentang konversi dengan cara lain.   -  person Yarin    schedule 19.12.2011
comment
@ Joseph- Saya baru saja menanyakan hal ini sehubungan dengan RFC 3999- seharusnya berfungsi untuk ini - Buat stempel waktu RFC 3339 dengan Python   -  person Yarin    schedule 19.12.2011


Jawaban (13)


Lokal pada ISO 8601:

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

UTC ke ISO 8601:

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

Lokal ke ISO 8601 tanpa mikrodetik:

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

UTC ke ISO 8601 dengan informasi TimeZone (Python 3):

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

UTC hingga ISO 8601 dengan informasi Zona Waktu Lokal tanpa mikrodetik (Python 3):

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

Lokal ke ISO 8601 dengan informasi TimeZone (Python 3):

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

Perhatikan ada bug saat menggunakan astimezone() pada waktu utc. Ini memberikan hasil yang salah:

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

Untuk Python 2, lihat dan gunakan pytz.

person estani    schedule 26.01.2015
comment
.isoformat() dapat mengambil parameter pemisah, (Jika Anda menginginkan sesuatu selain 'T'): .isoformat(' ') - person ThorSummoner; 25.08.2016
comment
@ThorSummoner senang mengetahuinya! Namun berhati-hatilah karena mengganti pemisah tidak akan lagi mematuhi ISO-8601... yang tidak masuk akal (selain itu, ada cara yang lebih baik untuk mencetak tanggal tetapi bukan itu pertanyaannya di sini). RFC - person estani; 25.08.2016
comment
Ruang diperbolehkan sebagai bagian dari standar ISO-8601. It is permitted to omit the 'T' character by mutual agreement. - person raychi; 07.09.2016
comment
@raychi Selalu diizinkan untuk mengubah standar berdasarkan kesepakatan bersama (yang dalam banyak kasus akan melanggar standar, tapi siapa yang peduli jika itu kesepakatan bersama, bukan?). 2c saya: jangan, biarkan apa adanya. - person estani; 08.09.2016
comment
Jawaban ini salah karena datetime.datetime.now().isoformat() mengembalikan string ISO 8601 lokal tanpa memberi label sebagai lokal. Anda harus memiliki datetime.timezone yang mewakili zona waktu lokal agar isoformat dapat melakukan hal yang benar. - person Sam Hartman; 01.05.2017
comment
Sepertinya offset=utc_offset_sec harus diganti dengan offset=datetime.timedelta(seconds=-utc_offset_sec) - person imbolc; 06.04.2018
comment
Bagian Lokal ke ISO-8601 dengan info TimeZone (python 3) dapat ditingkatkan dengan menggunakan: datetime.datetime.now(datetime.timezone(datetime.timedelta(seconds=time.localtime().tm_gmtoff))).isoformat(). Tidak perlu mengganti tzinfo ketika Anda dapat meneruskannya ke now, dan masalah altzone diselesaikan dengan menggunakan tm_gmtoff. - person ToBeReplaced; 14.07.2018
comment
Bagaimana cara mendapatkan format ISO-8601 dengan Python? Karena kita perlu strptime stringnya. %Y-%m-%dT%H:%M:%S%z mengembalikan -HHMM atau +HHMM tetapi tidak -HH:MM. - person Simin Jie; 08.08.2018
comment
UTC hingga ISO-8601 dengan info zona waktu (menggunakan pytz) datetime.datetime.now(tz=pytz.utc).isoformat() - person Christian Long; 06.09.2018
comment
tetapi waktu aplikasi javascript saya yang lain dalam format 2019-02-23T04:01:55.360Z, Z untuk offset nol jam, apakah tidak ada opsi untuk format ini? - person Miranda; 25.02.2019
comment
UTC hingga ISO-8601 dengan info zona waktu (Python 3, tanpa pytz): datetime.datetime.now(tz=datetime.timezone.utc).isoformat() - person Vinod Kurup; 05.09.2019
comment
Menghilangkan 'T' tidak mengubah standar karena ini adalah bagian dari standar ISO 8601. - person tomsv; 23.11.2019
comment
Saya melewati masa-masa buruk menggunakan datetime.replace(tzinfo)! Saya akan mengatakan: hindari! Ini menambah menit di antara konversi. Gunakan pytz.localize() sebagai gantinya. Lihat selengkapnya di sini. - person Renato Aloi; 17.06.2021

Inilah yang saya gunakan untuk mengonversi ke format datetime XSD:

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

Saya menemukan pertanyaan ini ketika mencari format waktu tanggal XSD (xs:dateTime). Saya perlu menghapus mikrodetik dari isoformat.

person radtek    schedule 30.11.2015
comment
Apa itu XSD (dalam konteks ini)? - person Peter Mortensen; 24.10.2018
comment
Saya yakin maksudnya xs:date dari stylesheet XSD/XML. - person sventechie; 17.11.2018
comment
Artinya xs:dateTime - person radtek; 19.11.2018

Representasi Waktu ISO 8601

Standar internasional ISO 8601 menjelaskan representasi string untuk tanggal dan waktu. Dua contoh sederhana dari format ini adalah

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

(yang keduanya berarti 16 Desember 2010), namun formatnya juga memungkinkan waktu resolusi sub-detik dan menentukan zona waktu. Format ini tentu saja tidak khusus untuk Python, tetapi bagus untuk menyimpan tanggal dan waktu dalam format portabel. Detail tentang format ini dapat ditemukan di entri Markus Kuhn .

Saya merekomendasikan penggunaan format ini untuk menyimpan waktu dalam file.

Salah satu cara untuk mendapatkan waktu saat ini dalam representasi ini adalah dengan menggunakan strftime dari modul time di pustaka standar Python:

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

Anda dapat menggunakan konstruktor strptime dari kelas 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)

Yang paling tangguh adalah modul 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)

Referensi

person Voislav Sauca    schedule 16.12.2010
comment
Dalam hal apa ini lebih kuat? - person Stéphane; 29.07.2017
comment
Tanggal: 2018-05-25 - person loxaxs; 25.05.2018
comment
Gabungan tanggal dan waktu dalam UTC: 2018-05-25T12:16:14+00:00 - person loxaxs; 25.05.2018
comment
Gabungan tanggal dan waktu dalam UTC: 2018-05-25T12:16:14Z - person loxaxs; 25.05.2018
comment
Gabungan tanggal dan waktu dalam UTC: 20180525T121614Z - person loxaxs; 25.05.2018
comment
cara membuat tanggal dan waktu Gabungan ini dalam UTC: 25-05-2018T12:16:14Z @Ioxaxs - person Khan; 01.12.2018

ISO 8601 memungkinkan representasi ringkas tanpa pemisah kecuali T, jadi saya suka menggunakan satu kalimat ini untuk mendapatkan string stempel waktu cepat:

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

Jika Anda tidak memerlukan mikrodetik, tinggalkan saja bagian .%f:

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

Untuk waktu setempat:

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

Sunting:

Setelah membaca lebih lanjut tentang ini, saya sarankan Anda membiarkan tanda bacanya. RFC 3339 merekomendasikan gaya tersebut karena jika semua orang menggunakan tanda baca, tidak ada risiko hal-hal seperti beberapa string ISO 8601 diurutkan dalam kelompok berdasarkan tanda bacanya. Jadi satu liner untuk string yang sesuai adalah:

>>> datetime.datetime.now().strftime("%Y-%m-%dT%H:%M:%SZ")
'2018-09-05T14:09:03Z'
person Jim Hunziker    schedule 05.09.2018
comment
apakah ada cara untuk membatasi angka milidetik menjadi 3? yaitu aplikasi javascript saya yang lain akan menghasilkan 2019-02-23T04:02:04.051Z dengan new Date().toISOString() - person Miranda; 25.02.2019
comment
Peringatan: 'Z' di akhir salah. Cara yang benar untuk menampilkan zona waktu termasuk simbol 'Z' adalah '%z' atau '%Z', yang menjadikannya 'datetime.datetime.now().strftime(%Y-%m-%dT%H: %M:%S%z)'. Saya telah menghabiskan 2 jam mencoba menemukan bug dalam kode saya… - person Dr_Zaszuś; 31.07.2020
comment
@Dr_Zaszuś Itu tidak benar. %z menghasilkan offset zona waktu untuk waktu lokal Anda, yang bukan merupakan rekomendasi saya untuk stempel waktu, terutama jika Anda melihat beberapa sistem. Z literal adalah singkatan ISO 8601 untuk UTC. - person Jim Hunziker; 03.08.2020
comment
@Miranda javascript seperti keluaran datetime.datetime.now(datetime.timezone.utc).isoformat()[:23]+Z - person seizu; 03.04.2021

Saya menemukan format datetime.iso di dokumentasi. Tampaknya melakukan apa yang Anda inginkan:

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

Format waktu ISO 8601 tidak menyimpan nama zona waktu, hanya UTC yang sesuai offset dipertahankan.

Untuk mengonversi file ctime ke string waktu ISO 8601 sambil mempertahankan offset UTC dengan 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'

Kode ini mengasumsikan bahwa zona waktu lokal Anda adalah Zona Waktu Timur (ET) dan sistem Anda menyediakan zona waktu yang benar Offset UTC untuk stempel waktu POSIX tertentu (ts), yaitu, Python memiliki akses ke database zona waktu historis di sistem Anda atau zona waktu memiliki aturan yang sama pada tanggal tertentu.

Jika Anda memerlukan solusi portabel; gunakan modul pytz yang menyediakan akses ke basis data 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'

Hasilnya sama dalam kasus ini.

Jika Anda memerlukan nama zona waktu/singkatan/id zona, simpanlah secara terpisah.

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

Catatan: tidak, : dalam offset UTC dan singkatan zona waktu EST bukan bagian dari format waktu ISO 8601. Itu tidak unik.

Pustaka yang berbeda/versi berbeda dari pustaka yang sama mungkin menggunakan aturan zona waktu yang berbeda untuk tanggal/zona waktu yang sama. Jika ini adalah tanggal yang akan datang maka peraturannya mungkin belum diketahui. Dengan kata lain, waktu UTC yang sama mungkin sesuai dengan waktu lokal yang berbeda tergantung pada aturan yang Anda gunakan -- menyimpan waktu dalam format ISO 8601 akan mempertahankan waktu UTC dan waktu lokal yang sesuai dengan waktu saat ini aturan zona yang digunakan pada platform Anda. Anda mungkin perlu menghitung ulang waktu setempat di platform lain jika memiliki aturan berbeda.

person jfs    schedule 28.11.2015

Anda harus menggunakan os.stat untuk mendapatkan waktu pembuatan file dan kombinasi time.strftime dan time.timezone untuk pemformatan:

>>> 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
Apakah zona waktu memperhitungkan waktu musim panas? Sepertinya tz akan tetap sama terlepas dari waktu musim panas atau tidak. - person Joseph Turian; 29.01.2010
comment
Ini akan menjadi offset apa pun yang berlaku saat ini. Jika DST aktif maka akan memiliki offset yang berbeda dengan saat DST tidak aktif. - person Max Shawabkeh; 29.01.2010

Bagi mereka yang mencari solusi kencan saja, ini adalah:

import datetime

datetime.date.today().isoformat()
person Alexander Zinchuk    schedule 14.09.2020
comment
Saya akhirnya melakukannya dengan cara ini untuk menghindari mengimpor lebih dari kelas datetime: from datetime import datetime; datetime.now().isoformat()[:10] (maaf tidak dapat menemukan cuplikan kodenya) - person David Elgstuen; 15.07.2021

Koreksi saya jika saya salah (saya tidak), tetapi offset dari UTC berubah seiring waktu musim panas. Jadi sebaiknya Anda gunakan

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

Saya juga percaya bahwa tandanya harus berbeda:

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

Saya bisa saja salah, tapi menurut saya tidak.

person Jarek Przygódzki    schedule 08.06.2010

Saya setuju dengan Jarek, dan saya selanjutnya mencatat bahwa karakter pemisah offset ISO adalah titik dua, jadi menurut saya jawaban akhirnya adalah:

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

Menambahkan sedikit variasi pada jawaban luar biasa estani

Lokal pada ISO 8601 dengan TimeZone dan info mikrodetik tidak (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()

Contoh Keluaran:

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

Diuji bahwa keluaran ini dapat diurai oleh Javascript Date dan C# DateTime/DateTimeOffset

person Sharpiro    schedule 06.11.2019

Standar RFC-3339 dalam milidetik

Saya memerlukan waktu dalam format ini untuk aplikasi LoRa jadi saya membuat ini, semoga membantu:

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

Saya telah mengembangkan fungsi ini:

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