Dapatkan zona waktu dari DateTime

103

Apakah DateTime .Net berisi informasi tentang zona waktu tempat dibuat?

Saya memiliki pustaka yang mengurai DateTime dari format yang memiliki "+ zz" di bagian akhir, dan sementara itu mem-parsing dengan benar dan menyesuaikan waktu lokal, saya perlu mengetahui zona waktu tertentu dari objek DateTime.

Apakah ini mungkin? Yang bisa saya lihat adalah DateTime.Kind, yang menentukan apakah waktunya lokal atau UTC.

dbkk
sumber
Lihat catatan tentang dokumentasi DateTime.Parse untuk menangani zona waktu dan DateTimeStyles. Tetapi tidak, apa yang Anda inginkan sebenarnya tidak mungkin.
yoyo

Jawaban:

136

DateTime sendiri tidak berisi informasi zona waktu nyata. Ini mungkin tahu apakah itu UTC atau lokal, tetapi bukan apa arti lokal sebenarnya.

DateTimeOffset agak lebih baik - pada dasarnya itu adalah waktu UTC dan offset. Namun, itu masih belum cukup untuk menentukan zona waktu, karena banyak zona waktu yang berbeda dapat memiliki offset yang sama pada satu titik waktu. Ini kedengarannya mungkin cukup baik untuk Anda, karena semua yang harus Anda kerjakan saat mengurai tanggal / waktu adalah offsetnya.

Dukungan untuk zona waktu mulai .NET 3.5 jauh lebih baik daripada sebelumnya, tetapi saya benar-benar ingin melihat "ZonedDateTime" standar atau sesuatu seperti itu - waktu UTC dan zona waktu aktual. Mudah untuk membuat sendiri, tetapi akan menyenangkan melihatnya di pustaka standar.

EDIT: Hampir empat tahun kemudian, saya sekarang menyarankan untuk menggunakan Noda Time yang memiliki jenis tanggal / waktu yang lebih kaya. Saya bias, sebagai penulis utama Noda Time :)

Jon Skeet
sumber
2
Proyek PublicDomain di CodePlex melakukan ini untuk Anda.
Cheeso
Enum TimeZone di BCL akan menyenangkan jika zona waktu dunia statis dan tidak berubah.
Jeff LaFay
1
@jlafay: Namun, mereka berubah - lebih banyak zona waktu ditambahkan ke Windows tahun lalu, misalnya.
Jon Skeet
Proyek ini tidak lagi dikelola oleh penulis; publicdomain.codeplex.com Sepertinya mungkin yang satu ini bisa membantu, tergantung pada penggunaannya, seseorang harus mengaturnya sebelum menggunakannya; timezone.codeplex.com
AnneTheAgile
3
@AnneTheAgile: Secara pribadi saya akan merekomendasikan menggunakan perpustakaan Waktu Noda saya sendiri, tentu saja :)
Jon Skeet
36

Tidak.

Pengembang bertanggung jawab untuk melacak informasi zona waktu yang terkait dengan nilai DateTime melalui beberapa mekanisme eksternal.

Kutipan dari artikel yang sangat bagus di sini . A harus membaca untuk setiap pengembang .Net.

Jadi saran saya adalah menulis kelas pembungkus kecil yang sesuai dengan kebutuhan Anda.

Gerrie Schenck
sumber
2

Anda dapat menggunakan kelas TimeZoneInfo

Kelas TimeZone mengenali zona waktu lokal, dan dapat mengonversi waktu antara Waktu Universal Terkoordinasi (UTC) dan waktu lokal. Objek TimeZoneInfo dapat mewakili zona waktu apa pun, dan metode kelas TimeZoneInfo dapat digunakan untuk mengonversi waktu dalam satu zona waktu ke waktu yang sesuai di zona waktu lain. Anggota kelas TimeZoneInfo mendukung operasi berikut:

  1. Mengambil zona waktu yang sudah ditentukan oleh sistem operasi.

  2. Menghitung zona waktu yang tersedia di sistem.

  3. Mengonversi waktu antara zona waktu yang berbeda.

  4. Membuat zona waktu baru yang belum ditentukan oleh sistem operasi.

    Serialisasi zona waktu untuk pengambilan nanti.

Shekhar
sumber
1
... tapi, mengingat DateTime, masih belum ada cara untuk menggunakan TimeZoneInfo untuk menentukan TimeZone DateTime, sepengetahuan saya.
Remi Despres-Smyth
@ RemiDespres-Smyth Saya baru saja menyimpan TimeZoneInfo bersama dengan DateTime dalam 1 kelas.
Konrad
0

Umumnya praktiknya adalah meneruskan data sebagai DateTime dengan "zona waktu" UTC dan kemudian meneruskan objek TimeZoneInfo dan ketika Anda siap untuk menampilkan data, Anda menggunakan objek TimeZoneInfo untuk mengonversi DateTime UTC.

Pilihan lainnya adalah untuk mengatur DateTime dengan zona waktu saat ini, dan kemudian memastikan "zona waktu" tidak diketahui untuk objek DateTime, kemudian pastikan DateTime lagi diteruskan dengan TimeZoneInfo yang menunjukkan TimeZone dari DateTime berlalu.

Seperti yang telah ditunjukkan orang lain di sini, alangkah baiknya jika Microsoft mengatasi ini dan membuat satu objek bagus untuk melakukan semuanya, tetapi untuk saat ini Anda harus berurusan dengan dua objek.

rampok
sumber
0

DateTime tidak mengetahui perbedaan zona waktunya. Tidak ada metode bawaan untuk mengembalikan offset atau nama zona waktu (mis. EAT, CEST, EST, dll).

Seperti yang disarankan oleh orang lain, Anda dapat mengubah tanggal Anda menjadi UTC:

DateTime localtime = new DateTime.Now;
var utctime = localtime.ToUniversalTime();

dan kemudian hanya menghitung perbedaannya:

TimeSpan difference = localtime - utctime;

Anda juga dapat mengonversi satu waktu ke waktu lainnya dengan menggunakan DateTimeOffset:

DateTimeOffset targetTime = DateTimeOffset.Now.ToOffset(new TimeSpan(5, 30, 0));

Tapi ini semacam kompresi lossy - offset saja tidak dapat memberi tahu Anda zona waktunya karena dua negara yang berbeda mungkin berada dalam zona waktu yang berbeda dan memiliki waktu yang sama hanya untuk sebagian tahun (mis. Afrika Selatan dan Eropa). Selain itu, ketahuilah bahwa waktu musim panas mungkin berlaku pada tanggal yang berbeda (EST vs CET - perbedaan 3 minggu).

Anda bisa mendapatkan nama zona waktu sistem lokal Anda menggunakan kelas TimeZoneInfo:

TimeZoneInfo localZone = TimeZoneInfo.Local;
localZone.IsDaylightSavingTime(localtime) ? localZone.DaylightName : localZone.StandardName

Saya setuju dengan Gerrie Schenck, silakan baca artikel yang dia sarankan.

henryalligator
sumber