Új dátumkezelés JavaScript-tel: Temporal

Új dátumkezelés JavaScript-tel: Temporal

Talán egyetérthetünk abban, hogy a dátumkezelés soha nem volt kényelmes és egyszerű a JavaScript berkein belül. Mindig meg lehetett oldani mindenféle feladatot, de vagy egy külső könyvtár, vagy végeláthatatlan dokumentáció túrás kellett ahhoz, hogy el tudjuk érni a célunkat. Szerencsére vannak biztató füstjelek a jövőt tekintve, ugyanis már a horizonton van a Temporal.

Kezdetek és alapvető problémák

Nagyon hosszasan bele lehetne menni a témába, hogy mi okozhatja a legtöbb gondot a dátumkezeléssel kapcsolatban. Talán most elég, ha annyit érintünk, hogy annak idején Brendan Eich 10 nap alatt fektette le a JavaScript alapjait, aminek még ma is isszuk a levét bizonyos szempontból. Mindez 1995-ben történt, méghozzá úgy, hogy fogta az akkori Java nyelvben megtalálható java.Util.Date implementációt és áthelyezte a saját, újonnan készülő programnyelvébe. A gond csak az, hogy a Java 1.1 1997-ben teljesen le is cserélte az alapjaiban kaotikus megoldást, a JavaScript-ben viszont benne maradt.🤦🏼‍♂️

Lássuk a problémákat a teljesség igénye nélkül:

  • Időzónák támogatásának hiánya (kivéve a felhasználó saját időzónája és UTC)
  • A különböző parserek nehézkesen vagy megbízhatatlanul működnek
  • A Date objektum mutálható
  • A téli időszámítással kapcsolatos viselkedések kiszámíthatatlanok
  • A dátumokkal kapcsolatos számítások nehézkesek natív API megvalósítással
  • Nem Gergely-naptár támogatásának hiánya

A megoldás: Temporal

Fontos tudni, hogy az itt ismertetett megoldást még nem támogatják a böngészők! A Temporal még 3-as fejlesztési fázisban van. Ki lehet próbálni és esetleges hibákat jelenteni, de kész termékekbe nem érdemes beépíteni! Ezen írásommal nem az a célom, hogy teljes segédletet nyújtsak a Temporal API használatához, csupán betekintést szeretnék nyújtani!

Lássuk a medvét!🐻

A Temporal API két fő adattípust biztosít számunkra:

  1. Sima adattípus (plain): egy dátum vagy idő, amely nem tartalmaz időzónával kapcsolatos információkat. Adja magát, hogy akkor lehet igazán hasznos, ha olyan időt szeretnénk megjeleníteni, ahol nem lényegesek az időzónával kapcsolatos adatok, mert nincsenek.

  2. Zónázott adattípus (zoned): olyan specifikus dátum és idő, ahol adva vannak az időzónával kapcsolatos adatok. Nyilván akkor érdemes használni, ha egy kifejezett időzónába tartozó dátumot és időt szeretnénk megjeleníteni vagy műveleteket végezni rajta.

Hogyan néz ki ez a “valóságban”?! Nézzünk meg pár példa kódot!

// Sima adattípus
const today = Temporal.Now.plainDateTimeISO();

A fenti kódból jól olvasható, hogy a temporal.now() függvény a háttérben mindig a jelenlegi dátumot és időt fogja visszaadni, méghozzá a helyi időzónában.

Lehetőségünk lesz kicsit szétválasztani a dolgokat:

// Sima adattípus, szétválsztva dátum és idő
const todayDate = Temporal.Now.plainDateISO();
const nowTime = Temporal.Now.plainTimeISO();

console.log(todayDate.toString()); // 2023-12-13
console.log(nowTime.toString()); // 13:56:21.325160744

Jelen kód a todayDate változóban fogja a jelenlegi dátumot eltárolni, amit akár egy toString() függvénnyel szöveggé is alakíthatnánk, illetve a nowTime fogja az aktuális időt külön tartalmazni, amit szintén, igény szerint szöveggé lehetne alakítani.

Ez mind szép és jó, de nézzük meg az izgalmasabbik részét a dolgoknak. A zónázott adattípus ugye, ahogyan korábban említettem már tartalmaz időzónával kapcsolatos információkat is, illetve megkönnyíti az ezeket érintő számításokat is.

// Zónázott adattípus: helyi dátum és idő, időzónával
const time = Temporal.Now.zonedDateTimeISO();
console.log(time.toString()); // 2023-12-13T13:56:56.179188491+01:00[Europe/Budapest]

Azért ez már elég menő nem?! A szöveggé alakított time változó már időzónával együtt tud az aktuális dátumról és időről.

Tegyük fel, hogy tudni akarom, hogy mennyi az idő most Honolulu-ban:

// Zónázott adattípus: Honolulu
const time = Temporal.Now.zonedDateTimeISO('Pacific/Honolulu');
console.log(time.toString()); // 2023-12-13T03:01:41.264482268-10:00[Pacific/Honolulu]

Nagyszerű, nemdebár?! Végezetül nézzük meg, hogy milyen egyszerűen végezhetünk műveleteket a Temporal segítségével! Lássuk be, a jelenleg is használt JavaScript implementáció tud gondot okozni ilyen téren, de ez az új megoldás csodás alternatíva lesz majd!

// Sima adattípus, dátum megjelenítése, időzóna nélkül
const today = Temporal.Now.plainDateISO();
console.log(today.toString()); //2023-12-13

// Vonjunk ki 15 napot! :-)
const thePast = today.subtract({ days: 15 });
console.log(thePast.toString()); // 2023-11-28

Csodás, nem?! Lényegében a subtract függvény segítségével meghatároztuk, hogy adott dátumból vonjon ki 15 napot és készen is vagyunk. A konfigurációnál természetesen hónapot (months) is meghatározhattunk volna, vagy akár évet is (years). Illetve nyilván hozzá is adhatunk dátumhoz ugyanezzel a logikával, csak éppen az add függvény segítségével. Például, ha március 31.-ét egy nappal megnöveljük a fenti módon, akkor az eredmény április 1 lesz és nem kell nekünk külön arra figyelni, hogy új hónap következik.

Mutatok még izgalmasat!

const duration = Temporal.Duration.from({ hours: 12, minutes: 30 });

console.log(duration.toString()); // PT12H30M
console.log(duration.total('minutes')); // 750
console.log(duration.total('secons')); // 45000

A fenti kód a Duration segítségével megmondja, hogy 12 óra és 30 perc az megfelel 750 percnek vagy 45000 másodpercnek.

Van lehetőségünk természetesen saját Temporal dátumokat létrehozni:

const now = Temporal.PlainDate.from('2023-12-13');

console.log(now.toString()); // 2023-12-13

Illetve, ha nem szöveggel, hanem számokkal dolgozunk:

const now = new Temporal.PlainDate(2023, 12, 13);

console.log(now.toString()); // 2023-12-13

Természetesen kezünkben van a kulcs, hogy akár új, tetszőleges dátumot és időt hozzunk létre, akár általunk meghatározott időzónában:

const now = Temporal.ZonedDateTime.from({
  year: 2023,
  month: 12,
  day: 13,
  timeZone: 'Pacific/Honolulu',
});

console.log(now.toString()); // 2023-12-13T00:00:00+01:00[Pacific/Honolulu]

Ugyanez, csak helyi időzónával:

const now = Temporal.ZonedDateTime.from({
  year: 2023,
  month: 12,
  day: 13,
  timeZone: Temporal.Now.timeZoneId(),
});

console.log(now.toString()); // 2023-12-13T00:00:00+01:00[Europe/Budapest]

Összegzés

A fenti, kiragadott példák jól mutatják, hogy mennyivel egyszerűbb dolgunk lesz a Temporal használatával a mostani állapotokhoz képest. Nincs más dolgunk, mint várni, hogy bekerüljön a böngészőkbe. Addig is, ha valaki ki szeretné próbálni, annak van módja rá, ha felteszi az alábbi csomagot:

npm i @js-temporal/polyfill

Telepítést követően pedig már el is lehet kezdeni a felfedezést:

import { Temporal } from '@js-temporal/polyfill';

// Itt már használható az új Temporal

Jó kísérletezgetést!