- Menyoroti ketidaklengkapan dan inkonsistensi objek
Date di JavaScript, serta memperkenalkan Temporal API sebagai penggantinya
Date bekerja sebagai objek yang dapat diubah (mutable object) sehingga tidak selaras dengan konsep tanggal yang sebenarnya, dan memiliki masalah struktural seperti error parsing serta keterbatasan penanganan zona waktu
Temporal menyediakan model penanganan tanggal dan waktu baru berbasis immutable, dengan kelas-kelas yang lebih terperinci seperti PlainDate, ZonedDateTime, Duration
- Metode-metode di Temporal tidak memodifikasi objek yang ada, melainkan mengembalikan objek baru, sehingga memungkinkan operasi chaining yang jelas dan aman
- Temporal saat ini berada pada tahap standardisasi 3 (Stage 3) dan didukung secara eksperimental di browser modern seperti Chrome dan Firefox
Masalah pada objek Date di JavaScript
- Konstruktor
Date menimbulkan kebingungan karena aturan parsing yang tidak konsisten dan pengindeksan yang tidak intuitif
- Contoh: bulan (month) dimulai dari 0, tetapi hari (day) dan tahun (year) dimulai dari 1
- String
"99" ditafsirkan sebagai tahun 1999, sedangkan "100" ditafsirkan sebagai tahun 0100, menunjukkan kurangnya konsistensi
Date dirancang dengan fokus pada waktu (time) dan disimpan secara internal sebagai Unix timestamp (dalam milidetik)
- Dukungan zona waktu (time zone) terbatas, serta tidak mengenali daylight saving time (DST) maupun kalender non-Gregorian
- Karena keterbatasan ini, ketergantungan pada pustaka pihak ketiga besar seperti Moment.js dan date-fns menjadi hal umum, yang dapat berujung pada penurunan performa
Benturan antara immutability dan konsep referensi
- Nilai primitif (primitive) di JavaScript bersifat immutable dan disimpan sebagai nilai itu sendiri, sedangkan objek (object) disimpan sebagai referensi dan dapat diubah
Date adalah objek yang dibuat melalui constructor, sehingga bersifat mutable
- Contoh: saat
setMonth() atau setDate() dipanggil, objek asli akan langsung berubah
- Akibatnya, dapat terjadi perubahan nilai tak terduga antar-variabel yang mereferensikan objek yang sama
- Contoh: jika fungsi menerima
today sebagai argumen lalu mengubah tanggal di dalamnya, maka today asli juga ikut berubah
Temporal: API tanggal dan waktu yang baru
Temporal adalah namespace object, bukan constructor, dengan struktur yang mirip Math
- Komponen utama:
PlainDate, PlainDateTime, PlainTime, ZonedDateTime, Duration, Now, dan lainnya
Temporal.Now mengembalikan berbagai bentuk waktu saat ini
plainDateISO() → tanggal dalam format ISO
zonedDateTimeISO() → waktu dengan zona waktu
- Objek Temporal menyediakan sistem metode yang jelas
- Operasi satuan eksplisit dapat dilakukan dengan
add({ days: 1 }), subtract({ years: 2 }), dan sebagainya
- Objek lama tidak dimodifikasi, melainkan mengembalikan objek baru, sehingga immutability tetap terjaga
Cara kerja dan keunggulan Temporal
- Objek Temporal tetap bertipe objek, tetapi mengikuti pola penggunaan immutable yang memang dirancang demikian
- Contoh:
today.add({ days: 1 }) mengembalikan objek tanggal baru, sementara today asli tidak berubah
- Menyediakan sintaks yang lebih ringkas dan jelas dibanding
Date
- Sesuai dengan kebutuhan modern seperti penentuan zona waktu, perhitungan durasi, dan pemeliharaan format ISO
- Melalui method chaining seperti
add, subtract, since, dan until, perhitungan tanggal yang kompleks dapat diekspresikan dengan ringkas
Status standardisasi dan prospek ke depan
Temporal telah mencapai ECMAScript proposal Stage 3, yaitu tahap ketika implementasi di browser sudah direkomendasikan
- Dukungan eksperimental sudah dimulai di Chrome dan Firefox, dan browser lain diperkirakan akan menyusul
- Developer sudah bisa berpartisipasi dalam penyempurnaan spesifikasi mulai sekarang melalui pengujian dan pemberian feedback
Date akan tetap ada, tetapi ke depannya Temporal diperkirakan menjadi cara default untuk menangani tanggal
- Artikel ditutup dengan kalimat bahwa “ini seharusnya sudah diganti pada 1995, tetapi setidaknya sekarang adalah waktu yang tepat untuk Temporal.Now”
1 komentar
Opini Hacker News
Artikel ini membahas berbagai perilaku aneh dari konstruktor Date di JavaScript
Secara khusus dijelaskan bahwa format
'YYYY-MM-DD'ditafsirkan sebagai tengah malam UTC, sehingga di zona waktu lokal bisa bergeser satu hariAwalnya, dalam ISO 8601 jika zona waktu tidak ditentukan maka seharusnya dianggap sebagai waktu lokal, tetapi karena kesalahan saat penulisan spesifikasi ES5, format ini diperlakukan sebagai “Z” (UTC)
Setelah itu sempat ingin diperbaiki di ES2015, namun karena sangat banyak situs web bergantung pada perilaku lama yang salah tersebut, perubahan itu dibatalkan demi kompatibilitas web
Untuk detail lebih lanjut, lihat bagian Broken Parser
'strict datetime'seperti'use strict'Dengan begitu, perilaku yang benar bisa diterapkan secara opsional tanpa menimbulkan masalah inkompatibilitas dengan kode lama
Atau bisa juga lewat pendekatan seperti
import Date from 'browser:date', yaitu memanggil objek global yang telah diperbaiki lewat modul internalUntuk nilai seperti ulang tahun yang hanya bermakna sebagai tanggal, tidak masuk akal jika berubah hanya karena zona waktu
Dulu Outlook pernah menyimpan ulang tahun beserta zona waktunya, jadi setiap kali pindah negara, tanggal ulang tahunnya ikut bergeser satu hari
Tapi adakah alternatifnya? Memaksa percabangan berdasarkan versi browser seperti era IE5 terdengar malah lebih buruk
Saya benar-benar iri dengan cara Rails dan Ruby menangani waktu
API seperti
Time.current.in_time_zone('America/Los_Angeles') + 3.days - 4.months + 1.hourterasa intuitif dan kuatRuby melakukan overload pada objek Time sebagai satu objek yang konsisten, sehingga hampir tidak perlu memikirkan konversi atau casting
Di JS, alangkah enaknya jika bisa menulis sesederhana
new Date().add({ days: 1 })Selain itu, pendekatan overload pada pustaka inti juga masih bisa diperdebatkan apakah benar-benar ide yang baik
Sayang sekali Safari masih belum mendukung Temporal API
Semoga tahun depan sudah ada dukungannya
JavaScript Date memang punya banyak masalah, tetapi fakta bahwa ia adalah sebuah objek sendiri menurut saya bukan masalah besar
Akan lebih baik kalau objeknya immutable, tetapi objek yang mutable lalu berubah bukan sesuatu yang mengejutkan
Bahaya sesungguhnya dari mutabilitas muncul dari perubahan non-lokal, bukan perubahan lokal
Cukup merepotkan bahwa Temporal API sama sekali tidak menangani informasi leap second
Saya ingin membuat alat JS untuk perhitungan astronomi, tetapi konversi UTC membutuhkan data leap second
Ada solusi memutar seperti
temporal-tai, tetapi itu merepotkan karena harus memelihara berkas leap second di sisi klienKarena SOP (kebijakan CORS), berkas itu juga tidak bisa langsung diambil dari situs lain
Browser diperbarui secara berkala, jadi terasa aneh mengapa informasi leap second tidak dibundel sejak awal
Jika server mengatur header
Access-Control-Allow-Originatau menyediakannya dalam bentuk berkas JS, maka itu bisa dilakukanNamun membundel dan memelihara data leap second langsung di browser sendiri memang bisa menjadi pekerjaan yang mahal
UTC pada dasarnya memang mencakup leap second, jadi yang sebenarnya ditangani hanyalah waktu POSIX
Pada contoh kode, seharusnya bukan
"33"melainkan"50"yang diperlakukan sebagai tahun 1900-an — ini hanya koreksi typoSaya sedang memakai Temporal polyfill, dan sejauh ini sangat puas
Untuk server atau aplikasi besar mungkin tidak masalah, tetapi untuk aplikasi kecil bisa terasa berat
Anehnya, artikel ini sama sekali tidak menyinggung
Date.now()Jika ingin membandingkannya dengan Temporal, seharusnya penjelasan dimulai dari
Date.now()Fungsi ini mengembalikan waktu yang telah berlalu dalam milidetik sejak 1 Januari 1970
Temporal memang punya API yang lebih ramah, tetapi pada dasarnya tujuan utamanya tetap untuk merepresentasikan jarak relatif waktu
Kalau begitu, muncul pertanyaan bagaimana cara mengubahnya ke format yang diinginkan tanpa melewati Date
Ada koreksi kecil tapi penting bahwa yang benar adalah “daylight saving time”, bukan “daylight savings time”
Sampai sekarang saya tidak tahu bahwa JS Date ternyata sebegitu berantakannya
Andai saat itu sedikit lebih berhati-hati, begitu banyak developer tidak perlu jatuh ke jebakan seperti ini