Zpět na domů

Parser dat JavaScript: skryté chyby a fixy

Článek rozebírá nečekané chování konstruktoru Date v JavaScriptu, parsujícího data z jakéhokoli textu. Je popsán algoritmus V8, problémy s timezone a doporučení pro bezpečné parsování pro production.

Proč JS převádí text na data: rozbor V8 parseru
Advertisement 728x90

Nebezpečný parser dat v JavaScript: Jak se vyhnout chybám při práci se řetězci

Konstruktor new Date(string) v JavaScriptu se snaží extrahovat datum z jakéhokoli řetězce, což často vede k neočekávaným výsledkům. Toto není chyba, ale specifická funkce implementací V8 a SpiderMonkey, kde parser agresivně interpretuje text.

Příklady ukazují problém:

new Date("2020-01-23")
// Wed Jan 22 2020 19:00:00 GMT-0500 (interpretace UTC)

new Date("Dnes je 2020-01-23")
// Thu Jan 23 2020 00:00:00 GMT-0500 (místní čas)

new Date("Trasa 66")
// Sat Jan 01 1966 00:00:00 GMT-0500

new Date("Beverly Hills, 90210")
// Mon Jan 01 90210 00:00:00 GMT-0500

Takové převody vytvářejí platné objekty Date, ale s nesprávnými hodnotami, což komplikuje ladění. Parser Catch 22 vrací Invalid Date — vzácný případ, kdy logika funguje správně.

Google AdInline article slot

Mechanismus parsování ve V8

Specifikace ECMAScript požaduje parsování pouze podmnožiny ISO 8601. Ostatní části jsou na uvážení implementace.

Algoritmus V8:

  • Kontrola na ISO 8601: řetězec musí začínat čtyřciferným rokem nebo znaménkem.
  • Přechod do legacy-parsovače: ignorování slov před prvním číslem.
  • Zpracování čísel v DayComposer:

- 1–12: měsíc.

Google AdInline article slot

- 13–31: nejednoznačné, často odmítnuto.

- 32+: rok (50–99 +1900).

- Ve výchozím stavu: 1. leden.

Google AdInline article slot

To vysvětluje, proč "Route 66" je považováno za rok 1966 a "90210" za rok 90210.

Problémy s časovými pásmi

ISO řetězce jako "2020-01-23" se parsovaly jako UTC, legacy jako místní čas. Rozdíl vzniká kvůli předponám:

  • Čistá ISO: UTC.
  • S textem: legacy, místní čas.

Prázdné znaky na začátku nebo konci řetězce mění parser a posouvá výsledek o den podle časového pásma.

Safari (JavaScriptCore) je striktnější: odmítá legacy příklady a řetězce s koncovými mezerami.

Praktické chyby a řešení

V reálných projektech fallback na new Date() pro uživatelská data převede "Route 66" na datum, což poškozuje tabulky. Řešení: spoléhat pouze na vlastní parsovače s regex validací.

Doporučení pro střední a senior vývojáře:

  • Validujte formát pomocí regex před voláním new Date().
  • Použijte date-fns parseISO() pro přísné ISO.
  • Pro plnou kontrolu: knihovny jako Luxon nebo Day.js s vlastními parsovači.
  • Vyhněte se new Date(string) s neověřenými daty.
  • Testujte křížově prohlížečově: V8, SpiderMonkey, JSC.

Porovnání s Pythonem

Python vyhýbá neurčitosti:

  • datetime.fromisoformat(): pouze ISO 8601.
  • strptime(): přísný formát bez nepotřebných znaků.

JavaScript legacy-parser hádá tichounce, Python vyhazuje ValueError.

Co je důležité

  • Parser Date vytváří platné, ale nesprávné objekty z náhodného textu.
  • Rozdíl mezi parsery (ISO vs legacy) závisí na předponách a mezerách.
  • V produkci: vždy ověřujte vstup před parsováním.
  • Přejděte na Temporal API pro budoucnost bezpečný kód.
  • Křížové testování prohlížečů je povinné kvůli rozdílům v enginech.

— Editorial Team

Advertisement 728x90

Číst dál