Wanzul Blog

Nota, pendapat, dan pengajaran yang aku bayar sendiri.

Date Range Picker js

RoR: Menentukan Dua Tarikh Dalam Julat Yang Diterima

Ada dua tarikh, di mana tarikh pertama greater or equal (gteq) dan tarikh kedua less than or equal (lteq). Kedua-dua tarikh ada peraturan: jaraknya mesti dalam lingkungan 3 bulan. Macam biasa, ada banyak cara nak tentukan julat antara gteq dan lteq. Aku akan bincang tiga (3) penyelesaian, dan penyelesaian ketiga yang paling elok nak pakai.

Penyelesaian #1

Penyelesaian ni andaikan ada 30 hari sebulan.

Sebagai developer Ruby baru, kau mula panik. Lepas tu kau cepat-cepat google cara nak selesaikan, dan hasilnya keluar.

Macam yang dicadang dalam forum overflow, kau kena buat penolakan antara dua tarikh. Tapi itu tak kena dengan kes kau, sebab kau nak beza tu dinyatakan dalam bulan, bukan hari. Cari beza dengan gteq tolak lteq (lteq – gteq) akan bagi kau bilangan hari yang mungkin tak tepat bila bilangan hari dalam sebulan diambil kira.

Greater than or equal to (gteq)

Less than or equal to (lteq)

Istilah biasa dalam manipulasi tarikh

Bayangkan kau bandingkan 1 Januari 2019 dengan 1 April 2019, sambil andaikan 30 hari sama dengan 1 bulan. Masa tu kau bertuah. Tapi macam mana kalau tahun tu tahun lompat (contoh: 2020), di mana Februari ada tambahan 1 hari. Banding tarikh yang sama pada 2020 akan bagi 91 hari, bukan 90 hari macam 2019. Dalam 2019, 90 bahagi 30 jadi tepat 3. Dalam 2020, 91 bahagi 30 jadi 3.033 — bukan 3, sebab titik perpuluhan tu.

Dengan semua kebimbangan ni, Penyelesaian #1 mungkin bukan yang terbaik untuk tentukan dua tarikh dalam julat yang diterima. Jom tengok Penyelesaian #2.

Penyelesaian #2

Penyelesaian ni andaikan ada 30.42 hari sebulan, di mana setiap tahun 365 hari dan tiada tahun lompat.

Andaian 30 hari sebulan tak tepat kalau julat tarikh jatuh antara pertama Februari (1 Februari) sampai kedua Mac (2 Mac). Bergantung pada kitaran tahun lompat, dua bulan boleh dianggap satu bulan bila guna andaian 30 hari. Jadi kau putuskan tak nak rumitkan lagi, dan kau import ruby gem di mana logiknya dah dibungkus dalam class method.

Lepas buka beberapa website dari senarai hasil carian google, kau sampai ke satu repo gem. Sampai sini, kau mungkin dah percaya dengan hujah kenapa Ruby sendiri tak ada helper beza masa. Jadi gem ni datang menyelamatkan.

Nampak macam kau dah sampai ke penghujung untuk banding sama ada ia dalam julat yang diterima. Dalam contoh di atas, ia andaikan kau nak check sama ada julat antara gteq dan lteq lebih besar daripada tiga (3), yang akan bagi true kalau kurang atau sama, dan false kalau lebih 3.

Sampai sini kau rasa puas, sebab kau biarkan magik tu berlaku dalam class itu sendiri, tanpa kau tanya apa-apa. Pada masa sama, kau ikut kejahilan kau yang bersembunyi bawah nama reuse. Entah macam mana, kau tertanya-tanya magik apa sebenarnya berlaku, dan kau jumpa kebenarannya. Ia guna andaian yang dibuat dalam Penyelesaian #2, di mana purata hari sebulan 30.42.

Bergantung pada andaian purata 30.42 hari sebulan sepanjang tahun memang salah setiap empat tahun, sebab purata hari sebulan jadi 30.5 hari. Penyelesaian #2 bukan juara sepanjang masa — andaiannya tak cukup tepat, walaupun ia boleh kena untuk kes tertentu. Jom tengok yang terakhir dan terbaik, Penyelesaian #3.

Penyelesaian #3

Jangan guna apa-apa andaian. Tambah tiga (3) pada nilai bulan gteq dan banding hasilnya dengan lteq — sama ada lteq lebih besar daripada hasil tu.

Ini yang paling senang dan paling tepat. Dan logik ni sepatutnya dah ada dalam kepala setiap web developer. Tambah nilai bulan dan buat perbandingan — itu akal sihat biasa. Tapi kadang, bila banyak benda nak fikir, kita terus ambil Penyelesaian #1 dan #2 yang bodoh tu.

Kesimpulan

Aku sebenarnya cari cara untuk capai:

  • Kalau gteq dan lteq yang diberi tak lebih besar daripada hari ni.
  • lteq mesti sentiasa lebih besar daripada gteq, atau paling kurang sama.
  • Julat mesti dalam tempoh 2 tahun dan 3 bulan. Mana-mana julat 3 bulan dalam tempoh 2 tahun boleh diterima.
  • Ganti tarikh dengan semalam kalau user langgar peraturan.

Dalam controller Ruby on Rails, set hook before action supaya logik tu jalan sebelum ia mula execute dalam method tertentu yang layan request user.

Kalau kau orang yang kena buat kerja ni, macam mana kau akan handle?

Wan Zulkarnain Avatar

Written by 


Comments

Leave a Reply