Apa yang harus saya lakukan
Saya memiliki objek waktu-waktu tidak sadar zona waktu, yang saya perlu menambahkan zona waktu agar dapat membandingkannya dengan objek waktu-waktu sadar-waktu-zona waktu lainnya. Saya tidak ingin mengonversi seluruh aplikasi saya ke zona waktu tanpa mengetahui untuk kasus warisan yang satu ini.
Apa yang saya coba
Pertama, untuk menunjukkan masalahnya:
Python 2.6.1 (r261:67515, Jun 24 2010, 21:47:49)
[GCC 4.2.1 (Apple Inc. build 5646)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> import datetime
>>> import pytz
>>> unaware = datetime.datetime(2011,8,15,8,15,12,0)
>>> unaware
datetime.datetime(2011, 8, 15, 8, 15, 12)
>>> aware = datetime.datetime(2011,8,15,8,15,12,0,pytz.UTC)
>>> aware
datetime.datetime(2011, 8, 15, 8, 15, 12, tzinfo=<UTC>)
>>> aware == unaware
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: can't compare offset-naive and offset-aware datetimes
Pertama, saya mencoba astimezone:
>>> unaware.astimezone(pytz.UTC)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ValueError: astimezone() cannot be applied to a naive datetime
>>>
Tidak terlalu mengejutkan bahwa ini gagal, karena sebenarnya mencoba melakukan konversi. Ganti sepertinya pilihan yang lebih baik (sesuai Python: Cara mendapatkan nilai datetime.today () yaitu "timezone aware"? ):
>>> unaware.replace(tzinfo=pytz.UTC)
datetime.datetime(2011, 8, 15, 8, 15, 12, tzinfo=<UTC>)
>>> unaware == aware
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: can't compare offset-naive and offset-aware datetimes
>>>
Tapi seperti yang Anda lihat, ganti tampaknya mengatur tzinfo, tetapi tidak membuat objek sadar. Saya sedang bersiap-siap untuk kembali ke doctoring string input untuk memiliki zona waktu sebelum parsing (saya menggunakan dateutil untuk parsing, jika itu penting), tapi itu tampaknya sangat muram.
Juga, saya sudah mencoba ini di kedua python 2.6 dan python 2.7, dengan hasil yang sama.
Konteks
Saya menulis parser untuk beberapa file data. Ada format lama yang saya perlukan untuk mendukung di mana string tanggal tidak memiliki indikator zona waktu. Saya sudah memperbaiki sumber data, tetapi saya masih perlu mendukung format data lawas. Konversi satu kali data legacy bukan pilihan untuk berbagai alasan BS bisnis. Sementara secara umum, saya tidak suka gagasan hard-coding zona waktu default, dalam hal ini sepertinya pilihan terbaik. Saya tahu dengan keyakinan yang masuk akal bahwa semua data lawas yang dimaksud adalah dalam UTC, jadi saya siap untuk menerima risiko gagal bayar itu dalam hal ini.
unaware.replace()
akan kembaliNone
jika itu memodifikasiunaware
objek di tempat. REPL menunjukkan bahwa.replace()
mengembalikandatetime
objek baru di sini.import datetime; datetime.datetime.now(datetime.timezone.utc)
tz
arg agar lebih mudah dibaca:datetime.datetime.now(tz=datetime.timezone.utc)
Jawaban:
Secara umum, untuk membuat zona waktu sadar-naif yang naif, gunakan metode pelokalan :
Untuk zona waktu UTC, itu tidak perlu digunakan
localize
karena tidak ada perhitungan waktu musim panas untuk menangani:bekerja. (
.replace
mengembalikan datetime baru; tidak diubahunaware
.)sumber
aware = datetime(..., tz)
gunakan.localize()
saja.tz.localize(..., is_dst=None)
menegaskan bahwa itu bukan.Semua contoh ini menggunakan modul eksternal, tetapi Anda dapat mencapai hasil yang sama hanya menggunakan modul datetime, seperti juga disajikan dalam jawaban SO ini :
Lebih sedikit ketergantungan dan tidak ada masalah pytz.
CATATAN: Jika Anda ingin menggunakan ini dengan python3 dan python2, Anda dapat menggunakan ini juga untuk impor zona waktu (hardcode untuk UTC):
sumber
pytz
masalah, saya senang saya gulir ke bawah sedikit! Memang tidak ingin menangani denganpytz
server jauh saya :)from datetime import timezone
bekerja di py3 tetapi tidak py2.7.dt.replace(tzinfo=timezone.utc)
mengembalikan datetime baru, itu tidak berubahdt
pada tempatnya. (Saya akan mengedit untuk menunjukkan ini).tz = pytz.timezone('America/Chicago')
Saya telah menggunakan dari dt_aware ke dt_unaware
dan dt_unware ke dt_aware
tetapi jawaban sebelumnya juga merupakan solusi yang baik.
sumber
localtz.localize(dt_unware, is_dst=None)
untuk mengajukan pengecualian jikadt_unware
mewakili waktu lokal yang tidak ada atau ambigu (catatan: tidak ada masalah seperti itu dalam revisi sebelumnya atas jawaban Anda di manalocaltz
UTC karena UTC tidak memiliki transisi DSTSaya menggunakan pernyataan ini di Django untuk mengubah waktu yang tidak disadari menjadi sadar:
sumber
Saya setuju dengan jawaban sebelumnya, dan tidak masalah jika Anda baik-baik saja memulai di UTC. Tetapi saya pikir ini juga merupakan skenario umum bagi orang untuk bekerja dengan nilai sadar yang memiliki waktu yang memiliki zona waktu lokal non UTC.
Jika Anda hanya pergi dengan nama, seseorang mungkin akan menyimpulkan ganti () akan berlaku dan menghasilkan objek sadar datetime yang tepat. Ini bukan kasusnya.
ganti (tzinfo = ...) tampaknya acak dalam perilakunya . Karena itu tidak berguna. Jangan gunakan ini!
pelokalan adalah fungsi yang benar untuk digunakan. Contoh:
Atau contoh yang lebih lengkap:
memberi saya nilai data waktu sadar zona waktu saat ini:
sumber
replace(tzinfo=...)
di zona waktu selain UTC akan merusak waktu Anda. Saya mendapatkan-07:53
bukannya-08:00
misalnya. Lihat stackoverflow.com/a/13994611/1224827replace(tzinfo=...)
perilaku yang tidak terduga?Gunakan
dateutil.tz.tzlocal()
untuk mendapatkan zona waktu dalam penggunaandatetime.datetime.now()
dandatetime.datetime.astimezone()
:Perhatikan bahwa
datetime.astimezone
pertama-tama akan mengonversidatetime
objek Anda ke UTC kemudian menjadi zona waktu, yang sama dengan menelepondatetime.replace
dengan informasi zona waktu yang asliNone
.sumber
.replace(tzinfo=dateutil.tz.UTC)
.replace(tzinfo=datetime.timezone.utc)
Ini mengkodifikasikan jawaban @ Sérgio dan @ unutbu . Ini akan "hanya bekerja" dengan
pytz.timezone
objek atau string Zona Waktu IANA .Ini terlihat seperti apa yang
datetime.localize()
(atau.inform()
atau.awarify()
) harus dilakukan, menerima objek string dan zona waktu untuk argumen tz dan default ke UTC jika tidak ada zona waktu yang ditentukan.sumber
Python 3.9 menambahkan
zoneinfo
modul jadi sekarang hanya perpustakaan standar yang diperlukan!Lampirkan zona waktu:
Pasang zona waktu lokal sistem:
Selanjutnya dikonversi dengan benar ke zona waktu lain:
Daftar zona waktu Wikipedia yang tersedia
Ada backport yang memungkinkan penggunaan dalam Python 3.6 hingga 3.8 :
Kemudian:
sumber
pip install tzdata
Dalam format jawaban unutbu; Saya membuat modul utilitas yang menangani hal-hal seperti ini, dengan sintaks yang lebih intuitif. Dapat diinstal dengan pip.
sumber
bagi mereka yang hanya ingin membuat waktu sadar zona waktu
sumber
cukup baru untuk Python dan saya mengalami masalah yang sama. Saya menemukan solusi ini cukup sederhana dan bagi saya itu berfungsi dengan baik (Python 3.6):
sumber
Berganti di antara zona waktu
sumber