2 poin oleh GN⁺ 2024-07-23 | 1 komentar | Bagikan ke WhatsApp
  • Jiff adalah pustaka tanggal dan waktu untuk Rust yang menargetkan tipe dasar tanggal dan waktu tingkat tinggi yang sulit disalahgunakan serta performa yang masuk akal
  • Fitur intinya mencakup integrasi otomatis dengan Time Zone Database, aritmetika dan pembulatan yang sadar DST, pemformatan dan parsing lossless untuk tanggal dan waktu dengan zona waktu, serta dukungan Serde opsional
  • Desain API-nya sangat dipengaruhi oleh Temporal, proposal TC39 untuk memperbaiki penanganan tanggal dan waktu di JavaScript
  • Jiff 1.0 semula ditargetkan rilis pada musim panas 2025, tetapi per April 2026 jadwalnya mundur, dan saat ini tidak ada linimasa rilis 1.0
  • Performa adalah tujuan penting, tetapi keterpahaman API dan akurasi diprioritaskan; di Unix, Jiff mengikuti kebijakan dependensi konservatif yang sengaja mempertahankan 0 dependensi

Model tanggal dan waktu yang disediakan Jiff

  • Jiff adalah pustaka untuk menangani tanggal dan waktu di Rust, dengan fokus menyediakan tipe dasar tingkat tinggi yang sulit digunakan secara keliru
  • Fitur utama yang didukung
    • Integrasi otomatis dan mulus dengan Time Zone Database
    • Aritmetika dan pembulatan yang sadar DST
    • Pemformatan dan parsing lossless untuk tanggal dan waktu dengan zona waktu
    • Dukungan serde opsional
  • Desain API-nya sangat dipengaruhi oleh Temporal, proposal TC39 untuk memperbaiki penanganan tanggal dan waktu di JavaScript
  • Lisensinya adalah lisensi ganda MIT atau UNLICENSE

Dokumentasi dan contoh penggunaan

  • Dokumentasi dan materi terkait
    • Dokumentasi API di docs.rs
    • Dokumen perbandingan dengan chrono, time, hifitime, icu
    • Dokumen alasan desain API Jiff
    • Dokumen dukungan platform
    • Changelog
  • Contoh dasar mem-parse string waktu RFC 3339, lalu mengubahnya menjadi tanggal dan waktu dengan zona waktu, menambahkan durasi, kemudian mencetaknya sebagai string lossless
    • Mem-parse "2024-07-11T01:14:00Z" sebagai Timestamp
    • Mengonversi ke zona waktu America/New_York
    • Menambahkan 1.month().hours(2)
    • String hasilnya adalah "2024-08-10T23:14:00-04:00[America/New_York]"
    • Waktu UTC dalam format RFC 3339 adalah "2024-08-11T03:14:00Z"

Instalasi dan alur eksekusi dasar

  • Jiff tersedia di crates.io, dan dapat digunakan dengan menambahkan jiff ke dependensi Cargo.toml di proyek Rust
  • Perintah sederhana untuk menambahkannya adalah cargo add jiff
  • Alur contoh lengkap di README
    • Membuat proyek baru dengan cargo new jiff-example
    • Menambahkan dependensi dengan cargo add jiff
    • Di src/main.rs, membulatkan waktu saat ini ke satuan detik dengan Zoned::now().round(Unit::Second)?
    • Menjalankannya dengan cargo run
  • Contoh output menampilkan bentuk yang menyertakan zona waktu, yaitu 2024-07-10T19:54:20-04:00[America/New_York]
  • Pada eksekusi pertama, output kompilasi akan lebih banyak, tetapi pada eksekusi berikutnya dependensi tidak perlu dikompilasi ulang

Feature flag dan rencana 1.0

  • Jiff menyediakan beberapa crate feature untuk mengatur dukungan pustaka standar Rust, dukungan serde, dan apakah Time Zone Database disematkan ke dalam binary
  • Daftar lengkap feature flag yang didukung ada di bagian “crate features” dalam dokumentasi
  • Rencana rilis awal Jiff 1.0 adalah musim panas 2025, tetapi per April 2026 jadwalnya sudah mundur dan saat ini tidak ada linimasa rilis
  • Setelah rilis 1.0, API direncanakan dipertahankan tanpa batas waktu, dengan tujuan agar pengguna dapat memakai Jiff sebagai fondasi stabil untuk API publik
  • Setelah Jiff 1.0 dirilis, Jiff 0.2 tetap direncanakan menerima pembaruan perbaikan bug penting selama 1 tahun
    • Tidak ada pengembangan fitur aktif
    • Karena sudah banyak pengguna yang memakai Jiff 0.2, rencananya adalah menyediakan masa tenggang untuk migrasi

Performa dan jalur pemformatan tingkat lanjut

  • Tujuan desain paling penting adalah menjadi pustaka tanggal dan waktu tingkat tinggi yang sulit disalahgunakan
  • Performa adalah tujuan kedua; Jiff mengejar performa yang masuk akal, tetapi mungkin masih ada area yang dapat ditingkatkan
  • Benchmark berada di direktori bench
  • Sebagian area sudah dioptimalkan, tetapi masih banyak area yang belum dioptimalkan
  • Peningkatan performa adalah tujuan, tetapi secara umum keterpahaman API dan akurasi diprioritaskan di atas performa
  • Submodul Jiff, terutama jiff::fmt, berfungsi sebagai escape hatch untuk API yang lebih kompleks ketika diperlukan kontrol lebih besar

Penanganan zona waktu per platform

  • Masalah dukungan platform pada pustaka tanggal dan waktu terutama berkaitan dengan dukungan zona waktu
  • Interaksi platform yang ditangani Jiff
    • Cara menemukan data transisi untuk identifier zona waktu IANA seperti Antarctica/Troll
    • Cara menemukan zona waktu default sistem saat ini
  • Data transisi zona waktu bergantung pada IANA Time Zone Database
  • Di Unix, biasanya /usr/share/zoneinfo digunakan, dan pengaturan variabel lingkungan TZDIR juga diikuti
  • Di Windows, salinan Time Zone Database secara otomatis disematkan ke pustaka yang dikompilasi
  • Cara deteksi zona waktu sistem
    • Di Unix, membaca /etc/localtime
    • Di Windows, membaca identifier zona waktu khusus Windows dengan GetDynamicTimeZoneInformation, lalu memetakannya ke identifier zona waktu IANA melalui CLDR XML data dari Unicode
  • Dukungan untuk platform lain diperkirakan akan bertambah seiring waktu, tetapi platform langka yang sulit diuji kemungkinan besar akan bergantung pada pull request dari kontributor

Kebijakan dependensi dan MSRV

  • Jiff yang memiliki 0 dependensi di Unix adalah desain yang disengaja
  • Kriteria untuk menambahkan dependensi baru ke Jiff sebagai crate ekosistem bersifat konservatif
    • Jika benar-benar diperlukan untuk berinteraksi dengan platform
    • Jika diperlukan untuk interoperabilitas, misalnya serde
  • Dependensi untuk tujuan interoperabilitas juga diperlakukan secara konservatif; umumnya Jiff berusaha hanya bergantung pada proyek yang memiliki lebih sedikit rilis breaking change dibanding Jiff
  • Memecah Jiff menjadi beberapa crate dapat menimbulkan dependensi baru, tetapi saat ini tidak ada rencana untuk itu
  • Arahnya adalah menjaga jumlah crate tetap kecil, dengan pengalaman bahwa mengelola banyak batas API semver menimbulkan overhead pemeliharaan yang besar
  • Versi minimum Rust compiler yang didukung Jiff adalah MSRV 1.70.0
  • Jiff sendiri dan dependensi Jiff di dalam repositori tidak menggunakan versi Rust yang menuntut compiler Rust yang dirilis dalam 1 tahun terakhir
  • Crate di dalam repositori yang bergantung pada Jiff, seperti jiff-icu, dapat menggunakan MSRV yang lebih baru, tetapi tidak akan menuntut MSRV yang lebih baru daripada crate target integrasinya
  • MSRV dependensi eksternal seperti windows-sys dan portable-atomic tidak dapat dikendalikan oleh Jiff
  • Sesuai konvensi ekosistem Rust, Jiff tidak menganggap kenaikan MSRV sebagai perubahan yang tidak kompatibel secara semver, tetapi kenaikan MSRV dibatasi pada pembaruan minor version

1 komentar

 
GN⁺ 2024-07-23
Opini Hacker News
  • Secara keseluruhan terlihat bagus, tetapi saya agak tersandung pada sintaks ToSpan
    let span = 5.days().hours(8).minutes(1);
    Rasanya agak canggung karena hanya angka pertama yang muncul di depan, sementara sisanya masuk sebagai argumen fungsi
    Kalau tidak suka, bisa menulisnya seperti let span = Span::new().days(5).hours(8).minutes(1);, dan karena hanya menambah beberapa karakter, tidak terlalu buruk

    • Setelah use jiff::{Timestamp, ToSpan};, saya tersandung pada bagian ketika "2024-07-11T01:14:00Z".parse()? di-parse menjadi Timestamp
      Seingat saya Rust memakai sesuatu seperti interface alih-alih class, jadi saya penasaran mengapa ketika library diimpor, string tiba-tiba mendapat method parse(), dan mengapa method bernama umum itu membuat objek Timestamp
      Saya juga penasaran apakah tipe di sisi kiri yang menentukan makna str.parse(), dan apa yang terjadi jika library tanggal dan library ekspresi Lisp sama-sama menambahkan parse() ke string
      Pertanyaannya jadi makin banyak, termasuk mengapa tidak memakai sintaks seperti Timestamp.parse(str)
    • Setuju. Secara pribadi saya lebih suka let span = 5.days() + 8.hours() + 1.minutes();
    • Saya suka versi ini karena terlihat konsisten
      Sintaks aslinya terlihat seperti bentuk yang mungkin dipakai Ruby
    • Setuju. Dalam alur berpikir, saya ingin menentukan dulu apa yang dilakukan, lalu memasukkan detailnya, tetapi sintaks ini kebalikannya
      Saat membaca kode, akan lebih baik jika terlebih dahulu terlihat bahwa kita sedang menangani span
    • Lebih jauh lagi, let span = Span::days(5).hours(8).minutes(1); terlihat lebih baik
  • Saya sering melihat orang meremehkan kompleksitas library tanggal/waktu
    Pernyataan seperti “representasi internal cukup UTC/Unix time”, “durasi cukup direpresentasikan dalam nanodetik”, “pakai offset saja alih-alih zona waktu” terus berulang
    Kalau Anda berpikir begitu, sebaiknya baca dokumen desain Jiff: https://github.com/BurntSushi/jiff/blob/master/DESIGN.md
    Seperti karya BurntSushi lainnya, dokumen itu luar biasa dan terperinci
    Perbandingannya dengan chrono, library tanggal/waktu de facto standar di Rust, juga layak dibaca: https://docs.rs/jiff/latest/jiff/_documentation/comparison/i...
    Hal-hal seperti aritmetika DST yang tetap benar setelah serialisasi/deserialisasi, durasi yang bisa dibulatkan, aritmetika kalender yang sadar zona waktu, dan deteksi konflik zona waktu historis membuat library ini akurat, berguna, dan nyaman dipakai
    chrono adalah library yang komprehensif dan “akurat”, tetapi kaku dan tidak terlalu mudah digunakan

    • Saya suka ripgrep dari BurntSushi, dan selalu memakainya dengan memanggilnya langsung dari Emacs
      Saya sudah memakai ripgrep bahkan sebelum Debian menyediakan rg secara default, dan juga pernah memakai JodaTime pada masa ketika masih ada orang yang berpikir Eclipse lebih baik daripada IntelliJ IDEA
      Namun di dokumen itu tidak ada bagian yang membantah “durasi cukup direpresentasikan dalam nanodetik”
      Pengguna memang perlu melihat waktu yang benar sesuai zona waktu dan DST, tetapi program biasanya tidak
      Jika pekerjaan Anda bukan menangani banyak zona waktu secara langsung, merepresentasikan durasi dalam milidetik/nanodetik umumnya sangat aman
      Fakta bahwa manusia menciptakan zona waktu dan DST tidak mengubah fenomena fisik bahwa jam internal CPU berdetak miliaran kali per detik
      Lihat saja kernel sistem operasi yang beberapa hari lalu tidak meledak di separuh bumi; banyak bagian timeout dalam kode diekspresikan dalam milidetik
      Orang bisa salah paham seolah-olah untuk mengimplementasikan “cooldown 30 detik” kita harus menambahkan 30 detik ke zona waktu saat ini, menyimpannya sebagai string yang mencakup zona waktu, DST, format 12/24 jam, lalu memeriksa sampai ke leap second
      Cukup gunakan timeout/cooldown 30 detik yang direpresentasikan dalam milidetik, dan meskipun dari sudut pandang pengguna terjadi setelah 29 detik, kita tidak perlu peduli soal leap second
    • Baru setelah melihat frasa “tetap berfungsi setelah ser/de” saya sadar mengapa crate Serde dinamai begitu
    • Terima kasih sudah memberi tahu dokumen desainnya. Saat pertama menelusuri repositori saya melewatkannya, tetapi itu dokumen yang ditulis dengan baik dan menjawab banyak hal yang saya penasaran
    • Jika ingin melihat kegilaan tanggal/waktu dengan cara yang menyenangkan dan mudah diikuti, presentasi Kip Cole di ElixirConf 2022 bagus: https://www.youtube.com/watch?v=4VfPvCI901c
    • Orang yang menganggap tanggal/waktu itu mudah tidak boleh didekatkan ke scheduling atau kode pemrosesan tanggal
  • Terlihat seperti library yang keren
    Saya penasaran kenapa BurntSushi membuat library baru
    Saya belum banyak menangani waktu di Rust, jadi ingin tahu apakah library yang ada punya masalah performa, API yang ada tidak nyaman dipakai, atau hanya dibuat untuk bersenang-senang, atau ada alasan lain

  • Kondisi library kalender di Rust tidak terlalu ideal
    Di Pandas ada .tz_convert() dan .tz_localize(), dan konversi zona waktu praktis selesai dengan itu
    Operasi yang saya jadikan patokan adalah “mendapatkan jam pertama dari satu hari CET/CEST untuk tanggal tertentu dalam UTC”, dan di Pandas itu sangat sederhana
    Di Chrono, harus membuat NaiveDate, mengubahnya menjadi DateTime, lalu mengubahnya lagi menjadi DateTime, dan saya tidak menemukan pola yang konsisten untuk konversi seperti ini
    Kadang berupa member function, kadang static method dari objek zona waktu
    Saya berharap suatu hari ada yang membenahinya. Jiff terlihat seperti satu langkah ke arah yang benar, tetapi sintaksnya kadang terasa aneh, jadi saya menginginkan bentuk yang lebih dapat diprediksi

    • Itu bisa dilakukan dengan date(y, m, d).intz("Europe/Rome")?
      Jika ingin mendapatkan UTC dari situ, tinggal tambahkan with_time_zone(TimeZone::UTC)
      Akan menarik kalau bisa dijelaskan lebih lanjut bagaimana Jiff bisa dibuat lebih baik, dan bagian mana dari sintaksnya yang terasa aneh
  • “Sayang, bangun, BurntSushi baru sudah keluar”[0]
    Lebih seriusnya, saya penasaran apakah ada pengguna Rust di sini yang tahu kenapa crate ini tidak memakai sesuatu seperti tracing
    Mungkin karena terlalu berat. Dari sisi crate, ukurannya hampir setengahnya
    log tentu saja oke, dan saya juga tidak tahu apakah melacak sampai pemanggilan operasi zona waktu adalah use case umum, tetapi saya penasaran apakah ada alasan khusus
    [0] https://knowyourmeme.com/memes/wake-up-babe

    • Saya menganggap log kurang lebih sebagai penyebut umum terkecil
      Ia juga terintegrasi baik dengan tracing, jadi mungkin itulah alasan Jiff memakainya
      Itu juga sesuatu yang sudah terus dipakai sejak masa-masa awal crates.io
      Jiff tidak punya kebutuhan selain mengeluarkan pesan pada level log tertentu
      Tentu saja, menurut saya tracing juga pasti akan bekerja dengan baik
  • BurntSushi juga orang yang membuat seluruh ekosistem regex Rust

    • Saya ingat pernah berdebat tentang sesuatu di Reddit, lalu menyadari siapa lawan bicara saya dan berkata “baiklah, sudah”
  • Hal yang paling saya sayangkan dari library waktu yang ada, baik di Rust maupun ekosistem lain, adalah kurangnya dukungan leap second
    Biasanya karena secara internal mereka memakai timestamp UNIX, bukan TAI, dan sayangnya library ini juga tidak berbeda
    Sepertinya ada cara untuk mendukungnya sampai tingkat tertentu dengan file tzif, tetapi bukan dukungan kelas satu
    Ada detailnya di issue Jiff terkait: https://github.com/BurntSushi/jiff/issues/7
    Karena timestamp UNIX tidak memakai definisi detik SI, melainkan 1/86000 dari hari saat ini, panjang semua detik UNIX tidak sama sehingga perhitungan durasi yang benar menjadi rusak
    Saya paham ini adalah kompromi untuk mewarisi kompatibilitas dengan cara lama melacak waktu dan membuat pemformatan kalender cepat, tetapi saya tidak menganggapnya kompromi yang tepat
    Timestamp UNIX mencampurkan urusan representasi dengan data
    Menurut saya leap second harus diperlakukan persis seperti 29 Februari atau zona waktu

    • Saya penasaran kenapa itu diperlukan. Apa use case nyatanya, dan kenapa library ilmiah khusus seperti hifitime tidak cocok
      Setiap kali pembahasan leap second muncul, biasanya terasa mengarah ke hal yang abstrak
      Sangat jarang terhubung dengan use case dunia nyata
      Saya memahami use case ilmiah, dan menurut saya kebutuhan seperti itu ditangani dengan baik oleh library khusus
      Di luar itu, saya tidak terlalu yakin apakah masih ada kebutuhan lain
  • Jiff dilafalkan dengan G keras, jadi “Giff”

    • Saya bukan penutur asli, apa sebenarnya arti hard G? Maksudnya G seperti di go, atau G seperti di gin?
  • “Jiff dilafalkan sebagai gif dengan g lembut seperti pada gem.”
    Sama sekali tidak boleh!

    • Sempat menikmati waktu yang menyenangkan saat naik ke posisi 1 Hacker News, tetapi sepertinya sekarang cacat fatalnya sudah terungkap
      Saya akan tetap memakai chrono †
      † Tentu saja dilafalkan “trono”, seperti ch pada chase
    • https://x.com/drgonzo123/status/527520297512345600
    • Aneh, saya kira Jiff dilafalkan dengan “J” yang keras
    • Jadi dilafalkan GIF, bukan GIF?!
  • Jadi, ini diucapkan jiff, atau gif?

    • https://github.com/BurntSushi/jiff/blob/master/DESIGN.md#why...
      “Jiff diucapkan gif dengan g lembut seperti pada gem.”
      Ah, paham ini leluconnya apa…
    • Menurutku pelafalan itu ditentukan oleh pembuatnya
      GIF menurut pembuatnya selalu diucapkan “jif”, jadi agar tidak membingungkan, semoga pembuat alat baru ini mengucapkan Jiff sebagai “gif”
    • Karena ini pustaka pemrosesan waktu, aku akan menyebutnya biff saja