Saya mencoba mengurangi satu nilai tanggal dari nilai datetime.today()
untuk menghitung berapa lama sesuatu itu terjadi. Tapi itu mengeluh:
TypeError: can't subtract offset-naive and offset-aware datetimes
Nilai datetime.today()
tampaknya tidak "sadar zona waktu", sedangkan nilai tanggal saya yang lain adalah. Bagaimana cara saya mendapatkan nilai datetime.today()
yang diketahui oleh zona waktu?
Saat ini, ini memberi saya waktu dalam waktu lokal, yang kebetulan adalah PST, yaitu UTC - 8 jam. Kasus terburuk, adakah cara saya bisa secara manual memasukkan nilai zona waktu ke datetime
objek yang dikembalikan oleh datetime.today()
dan mengaturnya ke UTC-8?
Tentu saja, solusi ideal adalah dengan mengetahui zona waktu secara otomatis.
datetime.now().astimezone()
sejak Python 3.6Jawaban:
Di perpustakaan standar, tidak ada cara lintas platform untuk membuat zona waktu sadar tanpa membuat kelas zona waktu Anda sendiri.
Di Windows, ada
win32timezone.utcnow()
, tapi itu bagian dari pywin32. Saya lebih suka menyarankan untuk menggunakan pytz library , yang memiliki basis data yang diperbarui secara konstan di sebagian besar zona waktu.Bekerja dengan zona waktu lokal bisa sangat rumit (lihat tautan "Bacaan lebih lanjut" di bawah), jadi Anda mungkin ingin menggunakan UTC di seluruh aplikasi Anda, terutama untuk operasi aritmatika seperti menghitung perbedaan antara dua titik waktu.
Anda bisa mendapatkan tanggal / waktu saat ini seperti:
Pikirkan itu
datetime.today()
dandatetime.now()
kembalikan waktu setempat , bukan waktu UTC, jadi melamar.replace(tzinfo=pytz.utc)
mereka tidak akan benar.Cara lain yang baik untuk melakukannya adalah:
yang sedikit lebih pendek dan melakukan hal yang sama.
Bacaan lebih lanjut / menonton mengapa lebih suka UTC dalam banyak kasus:
sumber
datetime.now(pytz.utc)
bukandatetime.utcnow().replace(tzinfo = pytz.utc)
?now(utc)
tidak kembali hari ini (kecuali tengah malam di UTC), itu mengembalikan waktu saat ini dalam UTC. Anda juga perlu.replace(hour=0, minute=0, ...)
mendapatkan awal hari (sepertidatetime.today()
)today()
pengembalian waktu saat ini, tidak tengah malam. Jika ada kasus penggunaan di mana tengah malam diperlukan, ya, penggantian harus dilakukan sesuai. Karena pertanyaan aslinya adalah tentang perbedaan waktu, saya tidak berpikir bahwa tengah malam diperlukan.datetime.today()
adalahcombine(date.today(), time())
.datetime
memiliki keduanya.now()
dan.today()
metode yang (seperti yang Anda tunjukkan dengan benar) mengembalikan (hampir) hal yang sama. Tidak adadate.now()
metode.date
dandatetime
objek tidak bisa saling dipertukarkan. Menggunakan objek datetime alih-alihdate
objek dapat menghasilkan bug halus; Saya tidak melihat alasan untukdatetime.today()
ada jika itu adalah duplikat dekatdatetime.now()
.timezone.now()
bukandatetime.now()
karena akan menggunakan UTC secara otomatis jikaUSE_TZ = True
.timezone
mencari didjango.utils.timezone
, dokumentasi: docs.djangoproject.com/en/1.11/topics/i18n/timezonesDapatkan waktu saat ini, di zona waktu tertentu:
sumber
datetime.datetime(2016, 11, 5, 9, 43, 45, tzinfo=pytz.timezone('US/Pacific'))
dan lihat apakah itu yang Anda harapkanDalam Python 3, perpustakaan standar membuatnya lebih mudah untuk menentukan UTC sebagai zona waktu:
Jika Anda menginginkan solusi yang hanya menggunakan pustaka standar dan yang berfungsi di Python 2 dan Python 3, lihat jawaban jfs .
Jika Anda membutuhkan zona waktu lokal, bukan UTC, lihat jawaban Mihai Capotă
sumber
Inilah solusi stdlib yang bekerja pada Python 2 dan 3:
di mana
today
instance datetime sadar mewakili awal hari (tengah malam) dalam UTC danutc
merupakan objek tzinfo ( contoh dari dokumentasi ):Terkait: perbandingan kinerja beberapa cara untuk mendapatkan tengah malam (awal hari) untuk waktu UTC yang diberikan . Catatan: lebih kompleks, untuk mendapatkan tengah malam untuk zona waktu dengan offset UTC yang tidak tetap .
sumber
Metode lain untuk membangun objek datetime sadar zona waktu mewakili waktu saat ini:
sumber
pytz.utc
danpytz.UTC
keduanya didefinisikan (dan sama)replace()
ing zona waktu umumnya rawan kesalahan dalam sebagian besar penggunaan lainnya, sementaralocalize()
ing adalah cara yang lebih disukai untuk menetapkan zona waktu untuk cap waktu naif..localize()
metode gagal untuk waktu lokal yang ambigu (input non-utc). @ philfreo yang menggunakan jawaban.now(pytz_timezone)
terus bekerja dalam kasus seperti itu..now(pytz_timezone)
melakukan persis samalocalize(utcnow)
- pertama menghasilkan waktu saat ini dalam UTC, kemudian menetapkannya zona waktu: "<...> dalam hal ini hasilnya setara dengantz.fromutc(datetime.utcnow().replace(tzinfo=tz))
". Kedua jawaban itu benar dan selalu berfungsi.pytz
melalui OLSON db seharusnya tahu cara mengubahnya ke zona waktu mana pun di dunia. Membuat sadar zona waktu naif (non-utc) lainnya sulit karena ambiguitas selama shift siang hari. Itu bukan masalah.localize
(memberinyais_dst
nilai membuatnya berfungsi untuk tanggal apa pun). Itu masalah yang melekat pada praktik penghematan siang hari.Satu-liner hanya menggunakan karya perpustakaan standar dimulai dengan Python 3.3. Anda bisa mendapatkan
datetime
objek sadar zona waktu menggunakanastimezone
(seperti yang disarankan oleh johnchen902 ):sumber
datetime.now()
dapat dipanggil tanpa argumen dan mengembalikan hasil lokal yang benar (naifdatetime
s dianggap berada di zona waktu lokal).Jika Anda menggunakan Django , Anda dapat mengatur tanggal tanpa kesadaran (hanya UTC ).
Komentari baris berikut di settings.py:
sumber
pytz adalah pustaka Python yang memungkinkan perhitungan zona waktu yang akurat dan lintas platform menggunakan Python 2.3 atau lebih tinggi.
Dengan stdlib, ini tidak mungkin.
Lihat pertanyaan serupa di SO .
sumber
Ini adalah salah satu cara untuk membuatnya dengan stdlib:
date akan menyimpan tanggal lokal dan offset dari UTC , bukan tanggal di zona waktu UTC, jadi Anda dapat menggunakan solusi ini jika Anda perlu mengidentifikasi zona waktu tempat tanggal dihasilkan . Dalam contoh ini dan di zona waktu lokal saya:
Kuncinya adalah menambahkan
%z
arahan ke FORMAT representasi, untuk menunjukkan offset UTC dari struct waktu yang dihasilkan. Format representasi lainnya dapat dikonsultasikan dalam modul datetime dokumenJika Anda memerlukan tanggal di zona waktu UTC, Anda dapat mengganti time.localtime () dengan time.gmtime ()
Edit
Ini hanya berfungsi pada python3 . Arahan z tidak tersedia pada kode python 2 _strptime.py
sumber
Gunakan dateutil seperti yang dijelaskan dalam Python datetime.datetime.now () yang sadar zona waktu :
sumber
tzlocal()
Fungsi masih merupakan salah satu solusi yang paling sederhana dan pasti harus disebutkan di sini.Mendapatkan tanggal sadar
utc
zona waktu di zona waktu sudah cukup untuk pengurangan tanggal untuk bekerja.Tetapi jika Anda menginginkan tanggal yang diketahui zona waktu di zona waktu Anda saat ini,
tzlocal
adalah caranya:PS
dateutil
memiliki fungsi serupa (dateutil.tz.tzlocal
). Tetapi meskipun berbagi nama itu memiliki basis kode yang sama sekali berbeda, yang seperti dicatat oleh JF Sebastian dapat memberikan hasil yang salah.sumber
Berikut adalah solusi menggunakan zona waktu yang dapat dibaca dan berfungsi dengan hari ini ():
Anda dapat membuat daftar semua zona waktu sebagai berikut:
sumber
Khusus untuk zona waktu non-UTC:
Satu-satunya zona waktu yang memiliki metode sendiri adalah
timezone.utc
, tetapi Anda dapat memalsukan zona waktu dengan offset UTC apa pun jika Anda perlu menggunakantimedelta
&timezone
, dan memaksanya menggunakan.replace
.Menggunakan
timezone(timedelta(hours=n))
sebagai zona waktu adalah peluru perak asli di sini, dan memiliki banyak aplikasi berguna lainnya.sumber
Jika Anda mendapatkan waktu dan tanggal saat ini di python maka impor tanggal dan waktu, paket pytz di python setelah Anda akan mendapatkan tanggal dan waktu saat ini seperti ..
sumber
Alternatif lain, menurut saya yang lebih baik, adalah menggunakan
Pendulum
daripadapytz
. Pertimbangkan kode sederhana berikut ini:Untuk menginstal Pendulum dan melihat dokumentasinya, buka di sini . Ini memiliki banyak pilihan (seperti ISO8601 sederhana, RFC3339 dan banyak lainnya mendukung format), kinerja yang lebih baik dan cenderung menghasilkan kode yang lebih sederhana.
sumber
Gunakan zona waktu seperti yang ditunjukkan di bawah ini untuk waktu tanggal sadar zona waktu. Standarnya adalah UTC:
sumber
Tyler dari 'howchoo' membuat artikel yang sangat bagus yang membantu saya mendapatkan ide yang lebih baik tentang Datetime Objects, tautan di bawah ini
Bekerja dengan Datetime
intinya, saya baru saja menambahkan yang berikut ke akhir dari kedua objek datetime saya
Contoh:
sumber
coba pnp_datetime , semua waktu telah digunakan dan dikembalikan adalah dengan zona waktu, dan tidak akan menyebabkan masalah naive dan offset-aware.
sumber
Harus ditekankan bahwa sejak Python 3.6, Anda hanya perlu lib standar untuk mendapatkan objek sadar waktu zona waktu yang mewakili waktu lokal (pengaturan OS Anda). Menggunakan astimezone ()
(lihat komentar @ johnchen902).
sumber