Baru-baru ini, saya mengerjakan tugas untuk menambahkan fitur zona waktu ke Kalender TOAST UI, pustaka kalender JavaScript yang dikelola oleh tim saya. Saya cukup tahu bahwa dukungan zona waktu dalam JavaScript cukup buruk, tetapi berharap mengabstraksi objek data yang ada akan dengan mudah menyelesaikan banyak masalah
Namun, harapan saya salah, dan saya merasa sangat sulit untuk menangani zona waktu dalam JavaScript saat saya semakin berkembang. Menerapkan fitur zona waktu di luar pemformatan waktu yang sederhana dan menghitung data waktu dengan operasi yang kompleks [mis. g. kalender] adalah tugas yang benar-benar menakutkan. Untuk alasan ini, saya memiliki pengalaman yang berharga dan mendebarkan dalam memecahkan masalah yang menyebabkan lebih banyak masalah
Tujuan dari artikel ini adalah untuk membahas masalah dan solusi terkait penerapan fitur zona waktu menggunakan JavaScript. Ketika saya sedang menulis artikel yang agak panjang ini, saya tiba-tiba menyadari bahwa akar masalah saya terletak pada pemahaman saya yang buruk tentang domain zona waktu. Dalam hal ini, saya pertama-tama akan membahas definisi dan standar yang terkait dengan zona waktu secara detail, dan kemudian berbicara tentang JavaScript
Apa itu zona waktu?Zona waktu adalah wilayah yang mengikuti waktu lokal seragam yang dinyatakan secara hukum oleh negara. Sudah umum bagi banyak negara untuk memiliki zona waktu yang unik, dan beberapa negara besar, seperti AS atau Kanada, bahkan memiliki beberapa zona waktu. Menariknya, meskipun China cukup besar untuk memiliki banyak zona waktu, dia hanya menggunakan satu zona waktu. Ini terkadang menghasilkan situasi yang canggung di mana matahari terbit sekitar pukul 10. 00 AM di bagian barat Cina
GMT, UTC, dan Offsetwaktu Greenwich
Waktu lokal Korea biasanya
const d1 = new Date[1489199400000];
d1.toString[]; // Sat Mar 11 2017 11:30:00 GMT+0900 [KST]
1. GMT adalah singkatan dari Greenwich Mean Time, yang merupakan waktu jam di Royal Observatory di Greenwich, U. K. terletak di garis bujur 0. Sistem GMT mulai menyebar pada Februari. 5, 1925 dan menjadi standar waktu dunia sampai Jan. 1, 1972UTC
Banyak yang menganggap GMT dan UTC adalah hal yang sama, dan keduanya digunakan secara bergantian dalam banyak kasus, tetapi sebenarnya berbeda. UTC didirikan pada tahun 1972 untuk mengkompensasi masalah perlambatan rotasi Bumi. Sistem waktu ini didasarkan pada Waktu Atom Internasional, yang menggunakan frekuensi atom cesium untuk menetapkan standar waktu. Dengan kata lain, UTC adalah sistem pengganti GMT yang lebih akurat. Meskipun perbedaan waktu sebenarnya antara keduanya kecil, UTC adalah pilihan yang lebih akurat untuk pengembang perangkat lunak
Ketika sistem masih dalam pengembangan, anglophones ingin menamai sistem CUT [Coordinated Universal Time] dan francophones ingin menamainya TUC [Temps Universal Coordonn]. Namun, tidak satu pun dari kedua belah pihak memenangkan pertarungan, jadi mereka mencapai kesepakatan untuk menggunakan UTC sebagai gantinya, karena itu berisi semua huruf penting [C, T, dan U]
Mengimbangi
const d1 = new Date[1489199400000];
d1.toString[]; // Sat Mar 11 2017 11:30:00 GMT+0900 [KST]
2 di const d1 = new Date[1489199400000];
d1.toString[]; // Sat Mar 11 2017 11:30:00 GMT+0900 [KST]
3 berarti waktu setempat lebih cepat 9 jam dari waktu standar UTC. Ini berarti bahwa itu adalah 09. 00 PM di Korea saat itu jam 12. 00 PM di wilayah UTC. Perbedaan waktu antara waktu standar UTC dan waktu setempat disebut "offset", yang dinyatakan dengan cara ini. const d1 = new Date[1489199400000];
d1.toString[]; // Sat Mar 11 2017 11:30:00 GMT+0900 [KST]
2, const d1 = new Date[1489199400000];
d1.toString[]; // Sat Mar 11 2017 11:30:00 GMT+0900 [KST]
5, dllBiasanya negara memberi nama zona waktu mereka menggunakan nama unik mereka sendiri. Misalnya, zona waktu Korea disebut KST [Waktu Standar Korea], dan memiliki nilai offset tertentu yang dinyatakan sebagai
const d1 = new Date[1489199400000];
d1.toString[]; // Sat Mar 11 2017 11:30:00 GMT+0900 [KST]
6. Namun, offset const d1 = new Date[1489199400000];
d1.toString[]; // Sat Mar 11 2017 11:30:00 GMT+0900 [KST]
_2 juga digunakan tidak hanya oleh Korea tetapi juga Jepang, Indonesia, dan banyak lainnya, yang berarti hubungan antara offset dan nama zona waktu tidak 1. 1 tapi 1. N. Daftar negara dalam offset const d1 = new Date[1489199400000];
d1.toString[]; // Sat Mar 11 2017 11:30:00 GMT+0900 [KST]
_2 dapat ditemukan di UTC+09. 00Beberapa penyeimbangan tidak secara ketat berdasarkan jam. Misalnya, Korea Utara menggunakan
const d1 = new Date[1489199400000];
d1.toString[]; // Sat Mar 11 2017 11:30:00 GMT+0900 [KST]
_9 sebagai waktu standar mereka sementara Australia menggunakan const d1 = new Date['2017-03-11T11:30:00'];
const d2 = new Date['2017-03-11T11:30:00Z'];
d1.toString[]; // "Sat Mar 11 11:30:00 UTC+0900 2017"
d2.toString[]; // "Sat Mar 11 20:30:00 UTC+0900 2017"
0 atau const d1 = new Date['2017-03-11T11:30:00'];
const d2 = new Date['2017-03-11T11:30:00Z'];
d1.toString[]; // "Sat Mar 11 11:30:00 UTC+0900 2017"
d2.toString[]; // "Sat Mar 11 20:30:00 UTC+0900 2017"
1bergantung pada wilayahZona waktu. == mengimbangi?Seluruh daftar offset UTC dan namanya dapat ditemukan di Daftar offset Waktu UTC
Seperti yang saya sebutkan sebelumnya, kita menggunakan nama zona waktu [KST, JST] secara bergantian dengan offset tanpa membedakannya. Tetapi tidak tepat untuk memperlakukan waktu dan offset wilayah tertentu dengan alasan yang sama karena alasan berikut
Waktu Musim Panas [DST]
Meskipun istilah ini mungkin asing di beberapa negara, banyak negara di dunia mengadopsi waktu musim panas. "Waktu musim panas" adalah istilah yang banyak digunakan di AS. K. dan negara Eropa lainnya. Internasional, biasanya disebut Daylight Saving Time [DST]. Ini berarti memajukan jam menjadi satu jam lebih awal dari waktu standar selama waktu musim panas
Misalnya, California di AS menggunakan PST [Waktu Standar Pasifik] selama musim dingin dan menggunakan PDT [Waktu Musim Panas Pasifik,
const d1 = new Date['2017-03-11T11:30:00'];
const d2 = new Date['2017-03-11T11:30:00Z'];
d1.toString[]; // "Sat Mar 11 11:30:00 UTC+0900 2017"
d2.toString[]; // "Sat Mar 11 20:30:00 UTC+0900 2017"
2] selama musim panas. Wilayah yang menggunakan dua zona waktu secara kolektif disebut Waktu Pasifik [PT], dan nama ini diadopsi oleh banyak wilayah di AS dan KanadaKemudian pertanyaan selanjutnya adalah kapan tepatnya musim panas dimulai dan berakhir. Faktanya, tanggal awal dan akhir DST semuanya berbeda, berbeda di setiap negara. Misalnya, di U. S. A dan Kanada, DST dulu dari Minggu pertama bulan April pukul 02. 00 pagi hingga hari Minggu terakhir bulan Oktober pukul 12. 00 AM sampai tahun 2006, namun sejak tahun 2007, DST dimulai pada hari Minggu kedua bulan Maret pukul 02. 00 pagi hingga hari Minggu pertama bulan November pukul 02. 00 pagi. Di Eropa, waktu musim panas diterapkan secara seragam di seluruh negara, sedangkan DST diterapkan secara bertahap ke setiap zona waktu di negara bagian
Apakah Zona Waktu Berubah?
Seperti yang saya sebutkan secara singkat sebelumnya, setiap negara memiliki haknya sendiri untuk menentukan zona waktu mana yang akan digunakan, yang berarti zona waktunya dapat diubah karena alasan politik dan/atau ekonomi apa pun. Misalnya, di negara bagian, periode DST diubah pada tahun 2007 karena Presiden George Bush menandatangani kebijakan energi pada tahun 2005. Mesir dan Rusia dulu menggunakan DST, tetapi mereka berhenti menggunakannya sejak 2011
Dalam beberapa kasus, suatu negara tidak hanya dapat mengubah DST-nya tetapi juga waktu standarnya. Misalnya, Samoa dulu menggunakan offset
const d1 = new Date['2017-03-11T11:30:00'];
const d2 = new Date['2017-03-11T11:30:00Z'];
d1.toString[]; // "Sat Mar 11 11:30:00 UTC+0900 2017"
d2.toString[]; // "Sat Mar 11 20:30:00 UTC+0900 2017"
3, tetapi kemudian diubah menjadi offset const d1 = new Date['2017-03-11T11:30:00'];
const d2 = new Date['2017-03-11T11:30:00Z'];
d1.toString[]; // "Sat Mar 11 11:30:00 UTC+0900 2017"
d2.toString[]; // "Sat Mar 11 20:30:00 UTC+0900 2017"
4 untuk mengurangi kerugian dalam perdagangan yang disebabkan oleh perbedaan waktu antara Samoa dan Australia & Selandia Baru. Keputusan ini menyebabkan negara tersebut melewatkan sepanjang hari di bulan Desember. 30, 2011 dan dibuat untuk surat kabar di seluruh duniaBelanda dulu menggunakan offset
const d1 = new Date['2017-03-11T11:30:00'];
const d2 = new Date['2017-03-11T11:30:00Z'];
d1.toString[]; // "Sat Mar 11 11:30:00 UTC+0900 2017"
d2.toString[]; // "Sat Mar 11 20:30:00 UTC+0900 2017"
5, yang tidak perlu akurat sejak tahun 1909, tetapi mengubahnya menjadi offset const d1 = new Date['2017-03-11T11:30:00'];
const d2 = new Date['2017-03-11T11:30:00Z'];
d1.toString[]; // "Sat Mar 11 11:30:00 UTC+0900 2017"
d2.toString[]; // "Sat Mar 11 20:30:00 UTC+0900 2017"
6 pada tahun 1937, dan kemudian diubah lagi menjadi offset const d1 = new Date['2017-03-11T11:30:00'];
const d2 = new Date['2017-03-11T11:30:00Z'];
d1.toString[]; // "Sat Mar 11 11:30:00 UTC+0900 2017"
d2.toString[]; // "Sat Mar 11 20:30:00 UTC+0900 2017"
7 pada tahun 1940, tetap menggunakannya sampai sekarangZona Waktu 1. mengimbangi NSingkatnya, zona waktu dapat memiliki satu atau beberapa offset. Offset mana yang akan digunakan suatu negara sebagai waktu standarnya pada saat tertentu dapat bervariasi karena alasan politik dan/atau ekonomi
Ini bukan masalah besar dalam kehidupan sehari-hari, tetapi ketika mencoba mensistematisasikannya berdasarkan aturan. Bayangkan Anda ingin menyetel waktu standar untuk ponsel cerdas Anda menggunakan offset. Jika Anda tinggal di wilayah yang menerapkan DST, waktu ponsel cerdas Anda harus disesuaikan setiap kali DST dimulai dan diakhiri. Dalam hal ini, Anda memerlukan konsep yang menyatukan waktu standar dan DST ke dalam satu zona waktu [mis. g. Waktu Pasifik]
Tapi ini tidak bisa diimplementasikan hanya dengan beberapa aturan sederhana. Misalnya, karena negara mengubah tanggal DST mulai dan berakhir pada tahun 2007, 31 Mei 2006 harus menggunakan PDT [
const d1 = new Date['2017-03-11T11:30:00'];
const d2 = new Date['2017-03-11T11:30:00Z'];
d1.toString[]; // "Sat Mar 11 11:30:00 UTC+0900 2017"
d2.toString[]; // "Sat Mar 11 20:30:00 UTC+0900 2017"
8] sebagai waktu standar sedangkan 31 Maret 2007 harus menggunakan PST [const d1 = new Date['2017-03-11T11:30:00'];
const d2 = new Date['2017-03-11T11:30:00Z'];
d1.toString[]; // "Sat Mar 11 11:30:00 UTC+0900 2017"
d2.toString[]; // "Sat Mar 11 20:30:00 UTC+0900 2017"
9] sebagai waktu standar. Ini berarti bahwa untuk merujuk ke zona waktu tertentu, Anda harus mengetahui semua data historis dari zona waktu standar atau titik waktu ketika aturan DST diubahAnda tidak bisa hanya mengatakan, “Zona waktu New York adalah PST [
const d1 = new Date['2017-03-11T11:30:00'];
const d2 = new Date['2017-03-11T11:30:00Z'];
d1.toString[]; // "Sat Mar 11 11:30:00 UTC+0900 2017"
d2.toString[]; // "Sat Mar 11 20:30:00 UTC+0900 2017"
9]. Anda harus lebih spesifik dengan mengatakan, misalnya, “Zona waktu New York saat ini adalah PST. ” Namun, kami membutuhkan ekspresi yang lebih akurat demi implementasi sistem. Lupakan kata "zona waktu". Anda perlu mengatakan, "New York saat ini menggunakan PST sebagai waktu standarnya"Lalu apa yang harus kita gunakan selain offset untuk menentukan zona waktu wilayah tertentu? . Untuk lebih spesifik, Anda harus mengelompokkan wilayah tempat perubahan dalam DST atau zona waktu standar telah diterapkan secara seragam ke dalam satu zona waktu dan merujuknya sebagaimana mestinya. Anda mungkin dapat menggunakan nama seperti PT [Waktu Pasifik], tetapi istilah tersebut hanya menggabungkan waktu standar saat ini dan DST-nya, belum tentu semua perubahan historis. Selain itu, karena PT saat ini hanya digunakan di AS dan Kanada, Anda memerlukan standar yang lebih baik dari organisasi tepercaya untuk menggunakan perangkat lunak secara universal
Basis Data Zona Waktu IANASejujurnya, zona waktu lebih merupakan database daripada kumpulan aturan karena harus berisi semua perubahan historis yang relevan. Ada beberapa database standar yang dirancang untuk menangani masalah zona waktu, dan yang paling sering digunakan adalah Database Zona Waktu IANA. Biasanya disebut tz database [atau tzdata], IANA Timezone Database berisi data historis waktu standar lokal di seluruh dunia dan perubahan DST. Basis data ini diatur untuk memuat semua data historis yang saat ini dapat diverifikasi untuk memastikan keakuratan waktu sejak waktu Unix [
const d1 = new Date[2017, 2, 11, 11, 30];
d1.getTime[]; // 1489199400000
1]. Meski juga memiliki data sebelum tahun 1970, keakuratannya tidak terjaminKonvensi penamaan mengikuti aturan Area/Lokasi. Area biasanya merujuk pada nama benua atau samudra [Asia, Amerika, Pasifik] sedangkan Lokasi merujuk pada nama kota besar seperti Seoul dan New York daripada nama negara [Hal ini karena umur suatu negara jauh lebih pendek . Misalnya, zona waktu Korea adalah ________20______2 dan Jepang adalah
const d1 = new Date[2017, 2, 11, 11, 30];
d1.getTime[]; // 1489199400000
3. Meskipun kedua negara berbagi const d1 = new Date[1489199400000];
d1.toString[]; // Sat Mar 11 2017 11:30:00 GMT+0900 [KST]
_3 yang sama, kedua negara memiliki sejarah yang berbeda mengenai zona waktu. Itu sebabnya kedua negara ditangani menggunakan zona waktu yang terpisahBasis Data Zona Waktu IANA dikelola oleh banyak komunitas pengembang dan sejarawan. Fakta sejarah yang baru ditemukan dan kebijakan pemerintah segera diperbarui ke database, menjadikannya sumber yang paling dapat diandalkan. Selain itu, banyak OS berbasis UNIX, termasuk Linux dan macOS, dan bahasa pemrograman populer, termasuk Java dan PHP, secara internal menggunakan database ini.
Perhatikan bahwa Windows tidak ada dalam daftar dukungan di atas. Itu karena Windows menggunakan databasenya sendiri yang disebut Microsoft Time Zone Database. Namun, database ini tidak mencerminkan perubahan historis secara akurat dan hanya dikelola oleh Microsoft. Oleh karena itu, kurang akurat dan dapat diandalkan dibandingkan IANA
Database Zona Waktu JavaScript dan IANA
Seperti yang saya sebutkan secara singkat sebelumnya, fitur zona waktu JavaScript cukup buruk. Karena mengikuti zona waktu wilayah secara default [untuk lebih spesifik, zona waktu yang dipilih pada saat penginstalan OS], tidak ada cara untuk mengubahnya ke zona waktu baru. Juga, spesifikasinya untuk standar database bahkan tidak jelas, yang akan Anda perhatikan jika Anda melihat lebih dekat spesifikasi untuk ES2015. Hanya beberapa pernyataan tidak jelas yang dinyatakan terkait zona waktu lokal dan ketersediaan DST. Misalnya, DST didefinisikan sebagai berikut.
Algoritma yang bergantung pada implementasi menggunakan informasi terbaik yang tersedia pada zona waktu untuk menentukan penyesuaian waktu musim panas setempat DaylightSavingTA[t], diukur dalam milidetik. Implementasi ECMAScript diharapkan melakukan upaya terbaiknya untuk menentukan penyesuaian waktu musim panas lokal
Sepertinya itu hanya mengatakan, “Hei, teman-teman, cobalah dan lakukan yang terbaik untuk membuatnya berhasil. ” Ini meninggalkan masalah kompatibilitas di seluruh vendor browser juga. Anda mungkin berpikir, “Itu ceroboh. ”, tetapi kemudian Anda akan melihat baris lain tepat di bawah
CATATAN. Direkomendasikan agar implementasi menggunakan informasi zona waktu dari IANA Time Zone Database http. // www. iana. org/zona waktu/
Ya. Spesifikasi ECMA melemparkan bola kepada Anda dengan rekomendasi sederhana ini untuk Database Zona Waktu IANA, dan JavaScript tidak memiliki database standar khusus yang disiapkan untuk Anda. Akibatnya, browser yang berbeda menggunakan operasi zona waktu mereka sendiri untuk penghitungan zona waktu, dan seringkali tidak kompatibel satu sama lain. Spesifikasi ECMA kemudian menambahkan opsi untuk menggunakan zona waktu IANA di ECMA-402
const d1 = new Date[2017, 2, 11, 11, 30];
d1.getTime[]; // 1489199400000
5 untuk API internasional. Namun, opsi ini masih kurang dapat diandalkan dibandingkan dengan bahasa pemrograman lainnyaZona Waktu di Lingkungan Server-KlienKami akan mengasumsikan skenario sederhana di mana zona waktu harus dipertimbangkan. Katakanlah kita akan mengembangkan aplikasi kalender sederhana yang akan menangani informasi waktu. Saat pengguna memasukkan tanggal dan waktu di lapangan pada halaman daftar di lingkungan klien, data ditransfer ke server dan disimpan di DB. Kemudian klien menerima data jadwal terdaftar dari server untuk menampilkannya di layar
Ada sesuatu yang perlu dipertimbangkan di sini. Bagaimana jika beberapa klien yang mengakses server berada di zona waktu yang berbeda? . 30 AM di Seoul harus ditampilkan sebagai Mar 10, 2017 09. 30 PM saat jadwal dicari di New York. Agar server dapat mendukung klien dari berbagai zona waktu, jadwal yang disimpan di server harus memiliki nilai absolut yang tidak terpengaruh oleh zona waktu. Setiap server memiliki cara berbeda untuk menyimpan nilai absolut, dan itu di luar cakupan artikel ini karena semuanya berbeda bergantung pada server atau lingkungan basis data. Namun agar ini berfungsi, tanggal dan waktu yang ditransfer dari klien ke server harus berupa nilai berdasarkan offset yang sama [biasanya UTC] atau nilai yang juga menyertakan data zona waktu dari lingkungan klien
Merupakan praktik umum bahwa jenis data ini ditransfer dalam bentuk waktu Unix berdasarkan UTC atau ISO-8601 yang berisi informasi offset. Pada contoh di atas, jika 11. 30 AM pada 11 Mar 2017 di Seoul akan diubah menjadi waktu Unix, ini akan menjadi tipe bilangan bulat yang nilainya
const d1 = new Date[2017, 2, 11, 11, 30];
d1.getTime[]; // 1489199400000
6. Di bawah ISO-8601, itu akan menjadi tipe string yang nilainya const d1 = new Date[2017, 2, 11, 11, 30];
d1.getTime[]; // 1489199400000
7Jika Anda bekerja dengan ini menggunakan JavaScript di lingkungan browser, Anda harus mengonversi nilai yang dimasukkan seperti yang dijelaskan di atas, lalu mengonversinya kembali agar sesuai dengan zona waktu pengguna. Kedua tugas ini harus dipertimbangkan. Dalam pengertian bahasa pemrograman, yang pertama disebut "parsing" dan yang terakhir "format". Sekarang mari cari tahu bagaimana ini ditangani dalam JavaScript
Objek Tanggal dalam JavaScriptBahkan saat Anda bekerja dengan JavaScript di lingkungan server menggunakan Node. js, Anda mungkin harus mengurai data yang diambil dari klien tergantung pada kasusnya. Namun karena server biasanya menyinkronkan zona waktunya ke database dan tugas pemformatan biasanya diserahkan kepada klien, Anda memiliki lebih sedikit faktor untuk dipertimbangkan daripada di lingkungan browser. Pada artikel ini, penjelasan saya akan didasarkan pada lingkungan browser
Dalam JavaScript, tugas yang melibatkan tanggal atau waktu ditangani menggunakan objek
const d1 = new Date[2017, 2, 11, 11, 30];
d1.getTime[]; // 1489199400000
8. Ini adalah objek asli yang didefinisikan dalam ECMAScript, seperti const d1 = new Date[2017, 2, 11, 11, 30];
d1.getTime[]; // 1489199400000
9 atau const d1 = new Date[2017, 2, 11, 11, 30];
d1.toISOString[]; // "2017-03-11T02:30:00.000Z"
d1.toJSON[]; // "2017-03-11T02:30:00.000Z"
const d2 = new Date['Hello'];
d2.toISOString[]; // Error: Invalid Date
d2.toJSON[]; // null
0. yang sebagian besar diimplementasikan dalam kode asli seperti C++. API-nya dijelaskan dengan baik dalam Dokumen MDN. Hal ini sangat dipengaruhi oleh java java. utilitas. Kelas tanggal. Akibatnya, ia mewarisi beberapa sifat yang tidak diinginkan, seperti karakteristik data yang dapat diubah dan const d1 = new Date[2017, 2, 11, 11, 30];
d1.toISOString[]; // "2017-03-11T02:30:00.000Z"
d1.toJSON[]; // "2017-03-11T02:30:00.000Z"
const d2 = new Date['Hello'];
d2.toISOString[]; // Error: Invalid Date
d2.toJSON[]; // null
1 dimulai dengan 0Objek
const d1 = new Date[2017, 2, 11, 11, 30];
d1.getTime[]; // 1489199400000
8 JavaScript secara internal mengelola data waktu menggunakan nilai absolut, seperti waktu Unix. Namun, konstruktor dan metode seperti const d1 = new Date[2017, 2, 11, 11, 30];
d1.toISOString[]; // "2017-03-11T02:30:00.000Z"
d1.toJSON[]; // "2017-03-11T02:30:00.000Z"
const d2 = new Date['Hello'];
d2.toISOString[]; // Error: Invalid Date
d2.toJSON[]; // null
_3fungsi, const d1 = new Date[2017, 2, 11, 11, 30];
d1.toISOString[]; // "2017-03-11T02:30:00.000Z"
d1.toJSON[]; // "2017-03-11T02:30:00.000Z"
const d2 = new Date['Hello'];
d2.toISOString[]; // Error: Invalid Date
d2.toJSON[]; // null
4, const d1 = new Date[2017, 2, 11, 11, 30];
d1.toISOString[]; // "2017-03-11T02:30:00.000Z"
d1.toJSON[]; // "2017-03-11T02:30:00.000Z"
const d2 = new Date['Hello'];
d2.toISOString[]; // Error: Invalid Date
d2.toJSON[]; // null
5, dll. dipengaruhi oleh zona waktu lokal klien [tepatnya, zona waktu OS yang menjalankan browser]. Oleh karena itu, jika Anda membuat objek const d1 = new Date[2017, 2, 11, 11, 30];
d1.getTime[]; // 1489199400000
_8 secara langsung menggunakan data input pengguna, data tersebut akan langsung mencerminkan zona waktu lokal klienMembuat Objek Tanggal dengan Input PenggunaSeperti yang saya sebutkan sebelumnya, JavaScript tidak menyediakan cara sewenang-wenang untuk mengubah zona waktu. Oleh karena itu, saya akan mengasumsikan situasi di sini di mana pengaturan zona waktu browser dapat langsung digunakan
Mari kita kembali ke contoh pertama. Asumsikan bahwa pengguna memasukkan 11. 30 AM, 11 Mar 2017 di perangkat yang mengikuti zona waktu Seoul. Data ini disimpan dalam 5 bilangan bulat 2017, 2, 11, 11, dan 30 — masing-masing mewakili tahun, bulan, hari, jam, dan menit. [Karena bulan dimulai dengan 0, nilainya harus 3–1=2. ] Dengan konstruktor, Anda dapat dengan mudah membuat objek Tanggal menggunakan nilai numerik
const d1 = new Date[2017, 2, 11, 11, 30];
d1.toString[]; // Sat Mar 11 2017 11:30:00 GMT+0900 [KST]
Jika Anda melihat nilai yang dikembalikan oleh
const d1 = new Date[2017, 2, 11, 11, 30];
d1.toISOString[]; // "2017-03-11T02:30:00.000Z"
d1.toJSON[]; // "2017-03-11T02:30:00.000Z"
const d2 = new Date['Hello'];
d2.toISOString[]; // Error: Invalid Date
d2.toJSON[]; // null
7, maka Anda akan tahu bahwa nilai absolut objek yang dibuat adalah 11. 30 AM, 11 Mar 2017 berdasarkan offset const d1 = new Date[1489199400000];
d1.toString[]; // Sat Mar 11 2017 11:30:00 GMT+0900 [KST]
2 [KST]Anda juga dapat menggunakan konstruktor bersama dengan data string. Jika Anda menggunakan nilai string ke objek
const d1 = new Date[2017, 2, 11, 11, 30];
d1.getTime[]; // 1489199400000
_8, objek tersebut secara internal memanggil const seoul = new Date[1489199400000];
seoul.getTimeZoneOffset[]; // -540
0 dan menghitung nilai yang sesuai. Fungsi ini mendukung spesifikasi dan spesifikasi ISO-8601. Namun, seperti yang dijelaskan dalam Tanggal MDN. parse[] Document, nilai pengembalian metode ini bervariasi dari satu browser ke browser lainnya, dan format tipe string dapat memengaruhi prediksi nilai eksak. Oleh karena itu, disarankan untuk tidak menggunakan metode iniMisalnya, string seperti
const seoul = new Date[1489199400000];
seoul.getTimeZoneOffset[]; // -540
_1 mengembalikan const seoul = new Date[1489199400000];
seoul.getTimeZoneOffset[]; // -540
2 di Safari dan Internet Explorer sementara string yang sama mengembalikan zona waktu lokal di Chrome dan Firefox. Dalam beberapa kasus, ini mengembalikan nilai berdasarkan standar UTCMembuat Objek Tanggal Menggunakan Data ServerSekarang anggaplah Anda akan menerima data dari server. Jika data berupa nilai waktu Unix numerik, Anda cukup menggunakan konstruktor untuk membuat objek
const d1 = new Date[2017, 2, 11, 11, 30];
d1.getTime[]; // 1489199400000
8. Meskipun saya melewatkan penjelasan sebelumnya, ketika konstruktor const d1 = new Date[2017, 2, 11, 11, 30];
d1.getTime[]; // 1489199400000
8 menerima satu nilai sebagai satu-satunya parameter, itu dikenali sebagai nilai waktu Unix dalam milidetik. [Hati-hati. JavaScript menangani waktu Unix dalam milidetik. Artinya, nilai kedua harus dikalikan dengan 1.000. ] Jika Anda melihat contoh di bawah ini, nilai yang dihasilkan sama dengan contoh sebelumnyaconst d1 = new Date[1489199400000];
d1.toString[]; // Sat Mar 11 2017 11:30:00 GMT+0900 [KST]
Lalu bagaimana jika tipe string seperti ISO-8601 digunakan sebagai pengganti waktu Unix? . Namun karena ECMAScript 5 atau versi yang lebih baru menentukan dukungan ISO-8601, Anda dapat menggunakan string dalam format yang ditentukan oleh ISO-8601 untuk konstruktor
const d1 = new Date[2017, 2, 11, 11, 30];
d1.getTime[]; // 1489199400000
8 di Internet Explorer 9. 0 atau lebih tinggi yang mendukung ECMAScript 5 jika digunakan dengan hati-hatiJika Anda menggunakan browser bukan versi terbaru, pastikan untuk menyimpan
const seoul = new Date[1489199400000];
seoul.getTimeZoneOffset[]; // -540
7 huruf di bagian akhir. Tanpanya, browser lama Anda terkadang mengartikannya berdasarkan waktu lokal Anda, bukan UTC. Di bawah ini adalah contoh menjalankannya di Internet Explorer 10const d1 = new Date['2017-03-11T11:30:00'];
const d2 = new Date['2017-03-11T11:30:00Z'];
d1.toString[]; // "Sat Mar 11 11:30:00 UTC+0900 2017"
d2.toString[]; // "Sat Mar 11 20:30:00 UTC+0900 2017"
_Menurut spesifikasi, nilai yang dihasilkan dari kedua kasus harus sama. Namun, seperti yang Anda lihat, nilai yang dihasilkan berbeda dengan
const d1 = new Date[2017, 2, 11, 11, 30];
d1.toISOString[]; // "2017-03-11T02:30:00.000Z"
d1.toJSON[]; // "2017-03-11T02:30:00.000Z"
const d2 = new Date['Hello'];
d2.toISOString[]; // Error: Invalid Date
d2.toJSON[]; // null
7dan const seoul = new Date[1489199400000];
seoul.getTimeZoneOffset[]; // -540
9. Di browser terbaru, kedua nilai ini akan sama. Untuk mencegah masalah versi seperti ini, Anda harus selalu menambahkan const seoul = new Date[1489199400000];
seoul.getTimeZoneOffset[]; // -540
7 di akhir string jika tidak ada data zona waktuMembuat Data untuk Ditransfer ke ServerSekarang gunakan objek
const d1 = new Date[2017, 2, 11, 11, 30];
d1.getTime[]; // 1489199400000
_8 yang dibuat sebelumnya, dan Anda dapat dengan bebas menambah atau mengurangi waktu berdasarkan zona waktu lokal. Tapi jangan lupa untuk mengonversi data Anda kembali ke format sebelumnya di akhir pemrosesan sebelum mentransfernya kembali ke serverJika ini saatnya Unix, Anda cukup menggunakan metode
function formatDate[date] {
return date.getFullYear[] + '/' +
[date.getMonth[] + 1] + '/' +
date.getDate[] + ' ' +
date.getHours[] + ':' +
date.getMinutes[];
}
const seoul = new Date[1489199400000];
const ny = new Date[1489199400000 - [840 * 60 * 1000]];
formatDate[seoul]; // 2017/3/11 11:30
formatDate[ny]; // 2017/3/10 21:30
2 untuk melakukan ini. [Perhatikan penggunaan milidetik. ]const d1 = new Date[2017, 2, 11, 11, 30];
d1.getTime[]; // 1489199400000
Bagaimana dengan string format ISO-8601? . 0 atau lebih tinggi yang mendukung ECMAScript 5 atau lebih tinggi mendukung format ISO-8601. Anda dapat membuat string format ISO-8601 menggunakan metode
function formatDate[date] {
return date.getFullYear[] + '/' +
[date.getMonth[] + 1] + '/' +
date.getDate[] + ' ' +
date.getHours[] + ':' +
date.getMinutes[];
}
const seoul = new Date[1489199400000];
const ny = new Date[1489199400000 - [840 * 60 * 1000]];
formatDate[seoul]; // 2017/3/11 11:30
formatDate[ny]; // 2017/3/10 21:30
3 atau function formatDate[date] {
return date.getFullYear[] + '/' +
[date.getMonth[] + 1] + '/' +
date.getDate[] + ' ' +
date.getHours[] + ':' +
date.getMinutes[];
}
const seoul = new Date[1489199400000];
const ny = new Date[1489199400000 - [840 * 60 * 1000]];
formatDate[seoul]; // 2017/3/11 11:30
formatDate[ny]; // 2017/3/10 21:30
4. [function formatDate[date] {
return date.getFullYear[] + '/' +
[date.getMonth[] + 1] + '/' +
date.getDate[] + ' ' +
date.getHours[] + ':' +
date.getMinutes[];
}
const seoul = new Date[1489199400000];
const ny = new Date[1489199400000 - [840 * 60 * 1000]];
formatDate[seoul]; // 2017/3/11 11:30
formatDate[ny]; // 2017/3/10 21:30
_4 dapat digunakan untuk panggilan rekursif dengan function formatDate[date] {
return date.getFullYear[] + '/' +
[date.getMonth[] + 1] + '/' +
date.getDate[] + ' ' +
date.getHours[] + ':' +
date.getMinutes[];
}
const seoul = new Date[1489199400000];
const ny = new Date[1489199400000 - [840 * 60 * 1000]];
formatDate[seoul]; // 2017/3/11 11:30
formatDate[ny]; // 2017/3/10 21:30
6 atau lainnya. ] Kedua metode menghasilkan hasil yang sama, kecuali untuk kasus di mana ia menangani data yang tidak validconst d1 = new Date[2017, 2, 11, 11, 30];
d1.toISOString[]; // "2017-03-11T02:30:00.000Z"
d1.toJSON[]; // "2017-03-11T02:30:00.000Z"
const d2 = new Date['Hello'];
d2.toISOString[]; // Error: Invalid Date
d2.toJSON[]; // null
Anda juga dapat menggunakan metode
function formatDate[date] {
return date.getFullYear[] + '/' +
[date.getMonth[] + 1] + '/' +
date.getDate[] + ' ' +
date.getHours[] + ':' +
date.getMinutes[];
}
const seoul = new Date[1489199400000];
const ny = new Date[1489199400000 - [840 * 60 * 1000]];
formatDate[seoul]; // 2017/3/11 11:30
formatDate[ny]; // 2017/3/10 21:30
_7 atau function formatDate[date] {
return date.getFullYear[] + '/' +
[date.getMonth[] + 1] + '/' +
date.getDate[] + ' ' +
date.getHours[] + ':' +
date.getMinutes[];
}
const seoul = new Date[1489199400000];
const ny = new Date[1489199400000 - [840 * 60 * 1000]];
formatDate[seoul]; // 2017/3/11 11:30
formatDate[ny]; // 2017/3/10 21:30
8 untuk membuat string dalam UTC. Saat mereka mengembalikan string yang memenuhi standar RFC-1123, Anda dapat memanfaatkannya sesuai kebutuhanObjek tanggal termasuk
function formatDate[date] {
return date.getFullYear[] + '/' +
[date.getMonth[] + 1] + '/' +
date.getDate[] + ' ' +
date.getHours[] + ':' +
date.getMinutes[];
}
const seoul = new Date[1489199400000];
const ny = new Date[1489199400000 - [840 * 60 * 1000]];
formatDate[seoul]; // 2017/3/11 11:30
formatDate[ny]; // 2017/3/10 21:30
9, ny.setDate[15];
formatDate[ny]; // 2017/3/15 21:30
0, dan metode ekstensinya. Namun, karena ini terutama digunakan untuk mengembalikan string berdasarkan zona waktu lokal, dan mengembalikan nilai yang bervariasi tergantung pada browser dan OS yang digunakan, mereka tidak terlalu berguna.Mengubah Zona Waktu LokalAnda dapat melihat sekarang bahwa JavaScript menyediakan sedikit dukungan untuk zona waktu. Bagaimana jika Anda ingin mengubah pengaturan zona waktu lokal dalam aplikasi Anda tanpa mengikuti pengaturan zona waktu OS Anda? . Satu-satunya solusi untuk ini adalah menambah atau menghapus nilai offset dari tanggal asalkan Anda sudah mengetahui nilai offset zona waktu. Jangan frustrasi dulu. Mari kita lihat apakah ada solusi untuk menghindari ini
Mari lanjutkan dengan contoh sebelumnya, dengan asumsi zona waktu browser diatur ke Seoul. Pengguna memasukkan 11. 30 AM, 11 Mar 2017 berdasarkan waktu Seoul dan ingin melihatnya dalam waktu lokal New York. Server mentransfer data waktu Unix dalam milidetik dan memberi tahu bahwa nilai offset New York adalah
ny.setDate[15];
formatDate[ny]; // 2017/3/15 21:30
1. Kemudian Anda dapat mengonversi data jika Anda hanya mengetahui offset zona waktu lokalDalam skenario ini, Anda dapat menggunakan metode
ny.setDate[15];
formatDate[ny]; // 2017/3/15 21:30
2. Metode ini adalah satu-satunya API dalam JavaScript yang dapat digunakan untuk mendapatkan informasi zona waktu lokal. Ini mengembalikan nilai offset zona waktu saat ini dalam hitungan menitconst seoul = new Date[1489199400000];
seoul.getTimeZoneOffset[]; // -540
Nilai pengembalian
ny.setDate[15];
formatDate[ny]; // 2017/3/15 21:30
_3 berarti zona waktu lebih cepat 540 menit dari target. Berhati-hatilah karena tanda minus di depan nilai berlawanan dengan tanda tambah Seoul [const d1 = new Date[1489199400000];
d1.toString[]; // Sat Mar 11 2017 11:30:00 GMT+0900 [KST]
2]. Saya tidak tahu mengapa, tapi begitulah tampilannya. Jika kita menghitung offset New York menggunakan metode ini, kita akan mendapatkan ny.setDate[15];
formatDate[ny]; // 2017/3/15 21:30
5. Ubah perbedaan ny.setDate[15];
formatDate[ny]; // 2017/3/15 21:30
_6 menjadi milidetik dan buat objek Tanggal baru. Kemudian Anda dapat menggunakan metode ________64______7 objek itu untuk mengonversi nilai menjadi format pilihan Anda. Mari buat fungsi formatter sederhana untuk membandingkan hasilnyafunction formatDate[date] {
return date.getFullYear[] + '/' +
[date.getMonth[] + 1] + '/' +
date.getDate[] + ' ' +
date.getHours[] + ':' +
date.getMinutes[];
}
const seoul = new Date[1489199400000];
const ny = new Date[1489199400000 - [840 * 60 * 1000]];
formatDate[seoul]; // 2017/3/11 11:30
formatDate[ny]; // 2017/3/10 21:30
ny.setDate[15];
formatDate[ny]; // 2017/3/15 21:30
_8 menunjukkan tanggal dan waktu yang benar sesuai dengan perbedaan zona waktu antara Seoul dan New York. Sepertinya kami menemukan solusi sederhana. Lalu bisakah kita mengubahnya menjadi zona waktu lokal jika kita mengetahui offset wilayah tersebut? . Ingat apa yang saya katakan sebelumnya? Masalah Konversi Zona Waktu LokalJika Anda terus bekerja dengan contoh di atas sedikit lagi, Anda akan segera menghadapi masalah. Pengguna ingin memeriksa waktu dalam waktu lokal New York dan kemudian mengubah tanggal dari tanggal 10 menjadi tanggal 15. Jika Anda menggunakan metode objek Tanggal
ny.setDate[15];
formatDate[ny]; // 2017/3/15 21:30
_9, Anda dapat mengubah tanggal sambil membiarkan nilai lainnya tidak berubahny.setDate[15];
formatDate[ny]; // 2017/3/15 21:30
Kelihatannya cukup sederhana, tapi ada jebakan tersembunyi di sini. Apa yang akan Anda lakukan jika Anda harus mentransfer data ini kembali ke server? . Oleh karena itu, Anda harus mengembalikan konversi sebelum mengirimkannya kembali ke server
const time = ny.getTime[] + [840 * 60 * 1000]; // 1489631400000
Beberapa dari Anda mungkin bertanya-tanya mengapa saya menambahkan menggunakan data yang dikonversi ketika saya harus mengubahnya kembali sebelum kembali. Sepertinya saya bisa memprosesnya tanpa konversi dan untuk sementara membuat objek Tanggal yang dikonversi hanya saat saya memformat. Namun, tidak seperti yang terlihat. Jika Anda mengubah tanggal objek
const d1 = new Date[2017, 2, 11, 11, 30];
8 berdasarkan waktu Seoul dari tanggal 11 ke 15, 4 hari ditambahkan [
d1.getTime[]; // 1489199400000const time = ny.getTime[] + [840 * 60 * 1000]; // 1489631400000
3]. Namun, dalam waktu setempat New York, karena tanggal telah diubah dari tanggal 10 menjadi tanggal 15, hasilnya adalah 5 hari telah ditambahkan [const time = ny.getTime[] + [840 * 60 * 1000]; // 1489631400000
4]. Ini berarti Anda harus menghitung tanggal berdasarkan offset lokal untuk mendapatkan hasil yang tepat
Masalahnya tidak berhenti di sini. Ada masalah lain yang menunggu di mana Anda tidak akan mendapatkan nilai yang diinginkan hanya dengan menambah atau mengurangi offset. Karena 12 Maret adalah tanggal mulai DST dalam waktu lokal New York, offset 15 Maret 2017 seharusnya
const time = ny.getTime[] + [840 * 60 * 1000]; // 1489631400000
5 bukan ny.setDate[15];
formatDate[ny]; // 2017/3/15 21:30
1. Jadi, saat Anda mengembalikan konversi, Anda harus menambahkan 780 menit, yaitu 60 menit lebih sedikit dari sebelumnyaconst time = ny.getTime[] + [780 * 60 * 1000]; // 1489627800000
Sebaliknya, jika zona waktu lokal pengguna adalah New York dan ingin mengetahui waktu di Seoul, DST tidak perlu diterapkan, menyebabkan masalah lain
Sederhananya, Anda tidak dapat menggunakan offset yang diperoleh sendirian untuk melakukan operasi yang tepat berdasarkan zona waktu pilihan Anda. Jika Anda mengingat kembali apa yang telah kita diskusikan di bagian awal dokumen ini, Anda akan dengan mudah mengetahui bahwa masih ada lubang dalam konversi ini jika Anda mengetahui aturan waktu musim panas. Untuk mendapatkan nilai yang tepat, Anda memerlukan database yang berisi seluruh riwayat perubahan offset, seperti Database zona waktu IANA
Untuk mengatasi masalah ini, seseorang harus menyimpan seluruh basis data zona waktu dan setiap kali data tanggal atau waktu diambil dari objek
const d1 = new Date[2017, 2, 11, 11, 30];
d1.getTime[]; // 1489199400000
8, temukan tanggal dan offset yang sesuai, lalu konversi nilainya menggunakan proses di atas. Secara teori, ini mungkin. Namun pada kenyataannya, ini membutuhkan terlalu banyak usaha dan menguji integritas data yang dikonversi juga akan sulit. Tapi jangan kecewa dulu. Sampai saat ini, kita sudah membahas beberapa masalah JavaScript dan cara mengatasinya. Sekarang kami siap menggunakan perpustakaan yang dibangun dengan baikZona Waktu MomenMomen adalah pustaka JavaScript mapan yang hampir menjadi standar untuk memproses tanggal. Menyediakan berbagai API tanggal dan pemformatan, belakangan ini diakui oleh begitu banyak pengguna sebagai stabil dan andal. Dan ada Zona Waktu Momen, modul ekstensi, yang menyelesaikan semua masalah yang dibahas di atas. Modul ekstensi ini berisi data IANA Time Zone Database untuk menghitung offset secara akurat, dan menyediakan berbagai API yang dapat digunakan untuk mengubah dan memformat zona waktu
Pada artikel ini, saya tidak akan membahas cara menggunakan library atau struktur library secara detail. Saya hanya akan menunjukkan kepada Anda betapa sederhananya menyelesaikan masalah yang telah saya bahas sebelumnya. Jika ada yang tertarik, lihat Dokumen Zona Waktu Momen
Mari selesaikan masalah yang ditunjukkan pada gambar dengan menggunakan Zona Waktu Momen
const d1 = new Date[1489199400000];
d1.toString[]; // Sat Mar 11 2017 11:30:00 GMT+0900 [KST]
0Jika Anda melihat hasilnya, offset ________ 78 _______ 8 tetap sama sedangkan offset
const time = ny.getTime[] + [840 * 60 * 1000]; // 1489631400000
9 telah diubah dari ny.setDate[15];
formatDate[ny]; // 2017/3/15 21:30
1 menjadi const time = ny.getTime[] + [840 * 60 * 1000]; // 1489631400000
5. Dan jika Anda menggunakan fungsi const time = ny.getTime[] + [780 * 60 * 1000]; // 1489627800000
_2, Anda bisa mendapatkan string dalam format ISO-8601 yang menerapkan offset secara akurat. Anda akan melihat betapa sederhananya dibandingkan dengan apa yang saya jelaskan sebelumnyaKesimpulanSejauh ini, kami telah membahas API zona waktu yang didukung oleh JavaScript dan masalahnya. Jika Anda tidak perlu mengubah zona waktu lokal secara manual, Anda dapat mengimplementasikan fitur yang diperlukan bahkan dengan API dasar asalkan Anda menggunakan Internet Explorer 9 atau lebih tinggi. Namun, jika Anda perlu mengubah zona waktu lokal secara manual, segalanya menjadi sangat rumit. Di wilayah di mana tidak ada waktu musim panas dan kebijakan zona waktu hampir tidak berubah, Anda dapat menerapkannya sebagian menggunakan
const time = ny.getTime[] + [780 * 60 * 1000]; // 1489627800000
3 untuk mengonversi data. Namun jika Anda menginginkan dukungan zona waktu penuh, jangan menerapkannya dari awal. Alih-alih menggunakan perpustakaan seperti Zona Waktu MomenSaya mencoba menerapkan zona waktu sendiri, tetapi gagal, yang tidak terlalu mengejutkan. Kesimpulan di sini setelah beberapa kegagalan adalah lebih baik “menggunakan perpustakaan. ” Ketika saya pertama kali mulai menulis artikel ini, saya tidak tahu kesimpulan apa yang akan saya tulis, tapi ini dia. Sebagai kesimpulan, saya akan mengatakan bahwa ini bukan pendekatan yang disarankan untuk menggunakan pustaka eksternal secara membabi buta tanpa mengetahui fitur apa yang mereka dukung dalam JavaScript dan masalah apa yang mereka miliki. Seperti biasa, penting untuk memilih alat yang tepat untuk situasi Anda sendiri. Saya harap artikel ini membantu Anda dalam menentukan keputusan yang tepat untuk Anda sendiri