Saya memiliki timestamptz
bidang sadar zona waktu di PostgreSQL. Ketika saya menarik data dari tabel, saya kemudian ingin mengurangi waktu sekarang sehingga saya bisa mendapatkan usianya.
Masalah yang saya alami adalah keduanya datetime.datetime.now()
dan datetime.datetime.utcnow()
sepertinya mengembalikan cap waktu yang tidak disadari zona waktu, yang mengakibatkan saya mendapatkan kesalahan ini:
TypeError: can't subtract offset-naive and offset-aware datetimes
Apakah ada cara untuk menghindari ini (sebaiknya tanpa menggunakan modul pihak ketiga).
EDIT: Terima kasih atas sarannya, namun mencoba menyesuaikan zona waktu sepertinya memberi saya kesalahan .. jadi saya hanya akan menggunakan cap waktu yang tidak disadari zona waktu di PG dan selalu menyisipkan menggunakan:
NOW() AT TIME ZONE 'UTC'
Dengan begitu semua stempel waktu saya adalah UTC secara default (meskipun lebih menjengkelkan untuk melakukan ini).
datetime.timezone.utc
ataupytz.utc
. Sebagai contoh,1970-01-01 00:00:00
adalah ambigu dan Anda harus menambahkan zona waktu untuk disambiguate:1970-01-01 00:00:00 UTC
. Anda lihat, Anda harus menambahkan informasi baru; stempel waktu dengan sendirinya ambigu.utcnow
seharusnya tidak mengembalikan objek naif atau stempel waktu tanpa zona waktu. Dari dokumen, "Objek sadar digunakan untuk mewakili momen spesifik dalam waktu yang tidak terbuka untuk interpretasi". Kapan saja di UTC memenuhi kriteria ini, menurut definisi.Solusi yang benar adalah dengan menambahkan info zona waktu misalnya, untuk mendapatkan waktu saat ini sebagai objek datetime sadar di Python 3:
Pada versi Python yang lebih lama, Anda bisa mendefinisikan
utc
sendiri objek tzinfo (contoh dari datetime docs):kemudian:
sumber
Saya tahu beberapa orang menggunakan Django khusus sebagai antarmuka untuk abstrak interaksi database jenis ini. Django menyediakan utilitas yang dapat digunakan untuk ini:
Anda perlu mengatur infrastruktur pengaturan Django dasar, bahkan jika Anda hanya menggunakan jenis antarmuka ini (dalam pengaturan, Anda harus memasukkan
USE_TZ=True
untuk mendapatkan datetime sadar).Dengan sendirinya, ini mungkin tidak cukup dekat untuk memotivasi Anda untuk menggunakan Django sebagai antarmuka, tetapi ada banyak fasilitas lainnya. Di sisi lain, jika Anda tersandung di sini karena Anda membuat aplikasi Django Anda (seperti yang saya lakukan), maka mungkin ini membantu ...
sumber
USE_TZ=True
, untuk mendapatkan datetime sadar di sini.+ timedelta(hours=5, minutes=30)
untuk ISTIni adalah solusi yang sangat sederhana dan jelas.
Dua baris kode
Kesimpulan: Anda harus mengubah variabel datetime Anda dengan info waktu yang sama
sumber
diff = datetime.now(timezone.utc) - your_timezone_aware_variable
berfungsi (dan(a - b)
rumus di atas adalah penjelasan mengapa(a - b)
bisa bekerja meskipuna.tzinfo
tidakb.tzinfo
).Modul psycopg2 memiliki definisi zona waktu sendiri, jadi saya akhirnya menulis pembungkus saya sendiri di sekitar utcnow:
dan gunakan saja
pg_utcnow
kapan pun Anda membutuhkan waktu saat ini untuk membandingkannya dengan PostgreSQLtimestamptz
sumber
Saya juga menghadapi masalah yang sama. Lalu saya menemukan solusi setelah banyak mencari.
Masalahnya adalah bahwa ketika kita mendapatkan objek datetime dari model atau bentuk itu diimbangi sadar dan jika kita mendapatkan waktu dengan sistem itu diimbangi naif .
Jadi yang saya lakukan adalah saya mendapatkan waktu saat ini menggunakan timezone.now () dan mengimpor zona waktu dengan dari django.utils mengimpor zona waktu dan meletakkan USE_TZ = True dalam file pengaturan proyek Anda.
sumber
Saya datang dengan solusi ultra-sederhana:
Ia bekerja dengan nilai-nilai datetime yang sadar zona waktu dan naif zona waktu. Dan tidak ada perpustakaan tambahan atau solusi pangkalan data yang diperlukan.
sumber
Saya temukan
timezone.make_aware(datetime.datetime.now())
sangat membantu dalam Django (Saya ada di 1.9.1). Sayangnya Anda tidak bisa begitu saja membuatdatetime
objek sadar-offset, lalutimetz()
benda itu. Anda harus membuatdatetime
dan membuat perbandingan berdasarkan itu.sumber
Apakah ada alasan yang mendesak mengapa Anda tidak bisa menangani perhitungan umur di PostgreSQL itu sendiri? Sesuatu seperti
sumber
Saya tahu ini sudah tua, tetapi saya pikir saya akan menambahkan solusi saya kalau-kalau ada orang yang berguna.
Saya ingin membandingkan datetime naif lokal dengan datetime sadar dari timeserver. Saya pada dasarnya membuat objek datetime naif baru menggunakan objek datetime sadar. Ini sedikit hack dan tidak terlihat sangat cantik tetapi menyelesaikan pekerjaan.
... inilah fudge ...
sumber
utc_to_local()
dari jawaban saya mengembalikan waktu lokal sebagai objek datetime sadar (Ini adalah kode Python 3.3+)delta = response.tx_time - time.time()
.