Moment.js:Lepší datová knihovna pro JavaScript

Jak každý zkušený programátor ví, data a časy jsou ve většině kódu na úrovni aplikace neuvěřitelně běžné. Data můžete použít ke sledování vytvoření objektu, ke sledování času od události nebo k uložení data nadcházející události. S daty však není snadné pracovat, takže je důležité mít knihovnu, která je přesná a zároveň má jednoduché rozhraní. Standardní JavaScript Date objekt není tak špatný, ale postrádá některé důležité funkce a ne vždy se s ním snadno pracuje.

V tomto článku uvidíte, jak Moment usnadňuje analýzu, formátování a manipulaci s daty a časy.

Data analýzy

Řetězce

Ve výchozím nastavení se Moment pokouší analyzovat datové řetězce pomocí formátu ISO 8601, který má širokou škálu platných dat. Pomocí tohoto formátu můžete ve svém datu a času určit tak malou nebo tolik přesnosti času, jak chcete. To je pro nás skvělé, protože data mohou mít mnoho různých podob v závislosti na úrovni podrobností, kterou chcete specifikovat.

Zvažujete pokus o vlastní analýzu všech těchto různých formátů:

  • 20160628
  • 2016-06-28T09
  • 20160628T080910,123
  • 2016-06-28 09:30:26.123
  • 2016-06-28 09:30:26.123+07:00

Jak vidíte, mění se nejen přesnost času, ale i formát, ve kterém je specifikován, se může značně lišit, a proto je tak důležité mít schopný analyzátor času.

Za prvé, nejjednodušší způsob, jak vytvořit moment objektem je volání konstruktoru bez argumentů:

> const moment = require('moment');
> let m = moment();

Tím se vytvoří instance objektu data s aktuálním časem.

Chcete-li analyzovat řetězec data a času pomocí Moment, předejte jej konstruktoru:

> let date = moment('2016-06-28 09:30:26.123');

Pokud z nějakého důvodu Moment není schopen analyzovat řetězec, který jste mu dali, vrátí se k použití vestavěného new Date() objekt pro analýzu.

Chcete-li zkontrolovat, zda bylo vaše datum analyzováno a platné, použijte .isValid() metoda:

> moment('2016-06-28 09:30:26.123').isValid();
true
> moment('derp').isValid();
false

U všech datových objektů vytvořených pomocí Moment, bez ohledu na to, jak je analyzujete nebo vytvoříte, bude časové pásmo v objektu výchozí na aktuální časové pásmo, pokud není uvedeno přímo. Chcete-li získat zpět časy UTC, použijte moment.utc() namísto. Další informace o časových pásmech naleznete v části Časová pásma okamžiku.

Určení formátů

Jednou z mých oblíbených funkcí analýzy v Momentu je analyzátor řetězců/formátů. Je to v podstatě jako formátovač reverzních řetězců. Zadáte řetězec data a času, který má být analyzován a další řetězec, který určuje formát, ve kterém se nachází. Tímto způsobem můžete používat řetězce libovolného formátu a stále je pohodlně používat s Momentem.

Například v USA (z nějakého důvodu) rádi formátujeme svá data jako „Měsíc/Den/Rok“, zatímco většina zbytku světa je formátuje jako „Den/Měsíc/Rok“. To ponechává velký prostor pro zmatky. Má být například datum „11/06/2016“ 6. listopadu nebo 11. června?


Obrázek:John Harding/Mona Chalabi přes The Guardian

Jak tedy budeme vědět, zda jsou vaše data analyzována správně? Použití specifikátorů formátu, jako je tento, zajistí, že ve vašich datech nebudou žádné nejednoznačnosti, za předpokladu, že předem víte, v jakém formátu jsou. V následujícím příkladu jsme stále schopni analyzovat správná data navzdory různým a potenciálně matoucím formátům.

> let d1 = moment('11.06.2016', 'DD-MM-YYYY');
> let d2 = moment('06/11/2016', 'MM-DD-YYYY');

> d1.format();    // '2016-06-11T00:00:00-05:00'
> d2.format();    // '2016-06-11T00:00:00-05:00'

Všimněte si, že v řetězcích data používáme také různé oddělovače "." a "/". Moment při používání těchto formátů ve skutečnosti ignoruje všechny nealfanumerické znaky, takže se nemusíte vždy starat o dokonalou shodu formátů.

Kompletní sadu dostupných formátovacích tokenů naleznete v této části dokumentu Moment.js.

Časová razítka Unix

Jak byste očekávali, Moment je také schopen analyzovat celočíselná data (čas Unix), a to buď ve formátu sekund nebo milisekund:

> moment.unix(1467128085);      // Date in seconds from 1970
> moment(1467128085747);        // Date in milliseconds from 1970

Jediný rozdíl ve výsledných časech je přesnost. millisecondDate bude mít nenulovou hodnotu pro milisekundové pole.

Data tisku

Podle mého názoru je to jedna z užitečnějších částí Momentu, hlavně proto, že JavaScript má vestavěný Date objekt pro něj nemá příliš dobrou podporu. Překvapivě je to jediný vestavěný způsob formátování pomocí Date je použít Date.toLocaleDateString() metoda, která působí dost neohrabaně a není tak flexibilní:

> let d = new Date(1467128085747);
> let options = {
...    weekday: 'long', year: 'numeric', month: 'short',
...    day: 'numeric', hour: '2-digit', minute: '2-digit'
... };

> date.toLocaleTimeString('en-us', options);
'Tuesday, Jun 28, 2016, 10:34 AM'

S Momentem můžeme snadno dosáhnout stejného formátování pouze s jedním řádkem kódu (což ukážu v další sekci).

Rozdělíme si to na několik podsekcí. Nejprve si projdeme tradiční formátování pomocí tokenů, potom si ukážeme dostupné relativní formáty data (např. „před 18 minutami“) a nakonec si ukážeme, jak formátovat data jako různé druhy strukturovaných dat, jako pole, JSON nebo prostý JavaScript Object .

Formátování

Použijte .format() metoda pro zobrazení data jako řetězce. Bez jakýchkoli argumentů vytiskne řetězec v reprezentaci ISO 8601:

> let date = moment.unix(1467128085);
> date.format();
'2016-06-28T10:34:45-05:00'

V opačném případě můžete poskytnout svůj vlastní formát a upravit jej podle svých představ pomocí tokenů.

> date.format('dddd, MMMM Do YYYY, h:mm a');
'Tuesday, June 28th 2016, 10:34 am'

Můžete si všimnout, že se jedná o stejnou reprezentaci jako Date.toLocaleTimeString() příklad shora, ale v jednom řádku. A vše, co bylo potřeba, byl řetězec 'dddd, MMMM Do YYYY, h:mm a'.

Úplný seznam formátovacích tokenů lze opět nalézt na velmi podrobné dokumentaci společnosti Moment.

Relativní formáty

Ve webových aplikacích je například často užitečné ukázat uživateli, kolik času uplynulo od události. Místo toho, abyste to sami počítali, nabízí Moment některé pomocné funkce, které toto formátování zvládnou za vás.

Ve všech případech můžete použít libovolné datum z minulosti nebo budoucnosti a vrácený řetězec bude odrážet správný čas.

Po vybalení získáte několik různých možností:

Čas od nynějška

Za předpokladu, že dnešní datum je 1. července 2016, získáte následující relativní formátování:

Zdarma e-kniha:Git Essentials

Prohlédněte si našeho praktického průvodce učením Git s osvědčenými postupy, průmyslově uznávanými standardy a přiloženým cheat sheetem. Přestaňte používat příkazy Google Git a skutečně se naučte to!

> moment({year: 2016, month: 3, day: 13, hour: 10}).fromNow();
'3 months ago'
> moment({year: 2016, month: 9, day: 23, hour: 10}).fromNow();
'in 4 months'

Volitelně můžete předat Boolean na .fromNow() sdělíte mu, zda má či nemá zahrnout do formátování řetězec „ago“ (nebo „in“). Tímto způsobem můžete v případě potřeby stále snadno přizpůsobit relativní řetězec.

> moment({year: 2016, month: 3, day: 13, hour: 10}).fromNow(true);
'3 months'

Čas od data

> let may = moment({year: 2016, month: 5, day: 3});
> let october = moment({year: 2016, month: 10, day: 9});
>
> may.from(october);
'5 months ago'
> october.from(may);
'in 5 months'

Čas do teď

> moment({year: 2016, month: 3, day: 13, hour: 10}).toNow();
'in 3 months'
> moment({year: 2016, month: 9, day: 23, hour: 10}).toNow();
'4 months ago'

Čas do data

> let may = moment({year: 2016, month: 5, day: 3});
> let october = moment({year: 2016, month: 10, day: 9});
> may.to(october)
'in 5 months'
> 
> october.to(may)
'5 months ago'

Možná jste si všimli, že metody „od“ a „do“ lze zaměnit v závislosti na tom, která data jsou předávána v argumentu. Všechno je relativní.

Strukturované datum-časy

V některých případech může být vhodnější mít data ve strukturovaném formátu, případně pro použití v algoritmu nebo serializaci. Moment nabízí několik různých způsobů formátování dat do datových struktur:

  • toDate() :Vrátí datum okamžiku jako JavaScript Date
  • toArray() :Vrátí data data jako pole - [ 2016, 5, 28, 10, 34, 45, 747 ]
  • toJSON() :Vrátí řetězec data ISO upravený na UTC – „2016-06-28T15:34:45.747Z“
  • toISOString() :Vrátí řetězec data ISO upravený na UTC – „2016-06-28T15:34:45.747Z“
  • toObject() :Vrací prostý JavaScript Object s daty data - {years: 2016, months: 5, date: 28, hours: 10, minutes: 34, seconds: 45, milliseconds: 747}
  • toString() :Vrátí formátovaný řetězec podobný Date.toString() - "Tue Jun 28 2016 10:34:45 GMT-0500"

Manipulace s daty

Schopnost manipulovat s daty je také velmi důležitá pro mnoho aplikací. A ani to není tak jednoduché jako vaše normální aritmetika – manipulace s daty je obtížná. Dokážete snadno zjistit tato sčítání/odčítání data/času? Programování není snadný úkol.

  • 21. února + 13 týdnů
  • 3:14 + 424 minut
  • 1. července – 1899400140 milisekund

Co když je přestupný rok? Nebo rok s přestupnou vteřinou? Naštěstí na to nemusíte přijít sami. Moment už pro vás má.

Metod manipulace s časem je poměrně dost, takže projdeme pouze ty běžněji používané:

Přičítání/odečítání

K manipulaci s datem použijte číslo/řetězec nebo objekt:

> moment().add(7, 'days');
> moment().subtract({days:13, months:3});

Řetězení také funguje dobře:

> moment().add({hours: 7}).subtract(13, 'minutes');

Začátek/konec času

Tyto pohodlné metody nastavují datum/čas na konec dané časové jednotky. Pokud máte například datum s časem 2:15, ale potřebujete, aby to byl začátek dne, použijte:

> moment().startOf('day');

Tím se čas nastaví na 12:00 téhož dne. Totéž platí pro rok, měsíc, hodinu a mnoho dalších.

> moment().endOf('year');   // sets date to 12-31-2016 23:59:59.999

Zjistil jsem, že je to velmi užitečné v aplikacích pro vytváření přehledů, kde si uživatelé mohou vybrat časové rámce pro přehledy, jako je Google Analytics. Abyste mohli načíst správná data, musíte mít správný rozsah.

Časová pásma okamžiku

Moment podporuje nastavení posunů časových pásem ihned po vybalení, ale pokud potřebujete lepší podporu časového pásma, měli byste zvážit použití moment-timezone .

Tato knihovna vám umožňuje specifikovat časová pásma podle města, regionu nebo jiných identifikátorů, což může výrazně zjednodušit práci aplikací pro uživatele.

Chcete-li jej použít, nainstalujte pomocí npm a require() toto místo moment :

> const moment = require('moment-timezone');

S více než 550 identifikátory časových pásem můžete své specifikátory časových pásem rozdělit podle různých regionálních kategorií a názvů:

  • Název časového pásma:US/Central, US/Eastern, US/Mountain atd
  • Město:Amerika/Chicago, Amerika/Los_Angeles, Asie/Dubaj, Austrálie/Sydney atd
  • Posun GMT:Etc/GMT+6, Etc/GMT-2, Etc/GMT0 atd

Úplný seznam identifikátorů časových pásem naleznete v úplném seznamu jmen provedením:

> const moment = require('moment-timezone');
> moment.tz.names()

Chcete-li použít tyto identifikátory k nastavení času a časového pásma pomocí .tz() metoda:

> moment.tz({year: 2016, month: 6, day: 30, hour: 11}, 'America/Los_Angeles').format();
'2016-07-30T11:00:00-07:00'
> moment.tz({year: 2016, month: 6, day: 30, hour: 11}, 'America/Chicago').format();
'2016-07-30T11:00:00-05:00'

Závěr

Programově pracovat s daty a časy je těžké, ale nemusí to být to nejtěžší, co děláte. Moment je skvělým příkladem knihovny, která značně zjednodušuje obtížné téma pomocí čistého a snadno použitelného rozhraní API.

Kromě analýzy, formátování a manipulace, které Moment poskytuje, je zde také přídavná podpora pro časová pásma prostřednictvím moment-timezone balík. Usnadněte život sobě i svým uživatelům přidáním lepší podpory pro časová pásma.

Jaké další funkce Momentu často používáte? Dejte nám vědět v komentářích!