date-fns + @date-fns/tz
Purpose
Use this skill to implement, review, and refactor date/time code with modern date-fns and the native timezone package @date-fns/tz.
Version baseline (re-check when invoked)
date-fns latest verified: 4.1.0
@date-fns/tz latest verified: 1.4.1
- Re-check commands:
npm view date-fns version
npm view @date-fns/tz version
npm view date-fns dist-tags --json
npm view @date-fns/tz dist-tags --json
When to use
- Parsing, validating, formatting, comparing, and calculating dates.
- Building timezone-aware business logic (scheduling, boundaries, reporting).
- Migrating date logic to immutable utility patterns.
- Hardening code against DST and token-format bugs.
Non-negotiable rules
- Use native timezone package:
@date-fns/tz.
- Do not recommend
date-fns-tz.
- If legacy code already uses
date-fns-tz, suggest migration to @date-fns/tz.
- Parse once, validate early (
isValid), and pass Date values through operations.
- Use Unicode tokens correctly (
yyyy, MM, dd) and avoid Moment-style token assumptions.
- For timezone-sensitive calculations, use explicit timezone context (
TZDate or { in: tz("...") }).
Canonical imports
import { format, parseISO, isValid, addDays, startOfDay } from "date-fns";
import { TZDate, tz, tzOffset, tzName, tzScan } from "@date-fns/tz";
Workflow
1) Normalize input
- Use
parseISO/toDate for conversion.
- Guard with
isValid.
- Keep internal values as
Date/TZDate, not mixed string math.
2) Compute with pure helpers
- Prefer
add/sub, differenceIn*, startOf*/endOf*, isSame*, isWithinInterval.
- Avoid mutating
Date via setters unless there is a clear reason.
3) Apply timezone context explicitly
- Option A: use
TZDate values.
- Option B: use date-fns
in option with tz("Area/City") for deterministic zone context.
4) Format/output safely
- Use
format for display.
- Use standards helpers for exchange formats (
formatISO, formatRFC3339).
- Keep transport format and display format separate.
Deliverables
When answering, provide:
- Exact imports.
- Minimal correct function set for the use case.
- Timezone strategy (
TZDate vs { in: tz(...) }) and why.
- Edge-case notes (DST boundaries, token correctness, invalid inputs).
Progressive disclosure
Load only what is needed:
reference/core-functions.md for essential helpers.
reference/native-timezones.md for @date-fns/tz patterns.
reference/imports-and-practices.md for import/runtime practices.
reference/format-parse-tokens.md for token correctness.
reference/examples.md for copy-ready snippets.
reference/anti-patterns.md for strict "never use date-fns-tz" guidance.
reference/version-and-sources.md for version checks and source links.
1---2name: date-fns3description: Practical workflow for date-fns v4 and native @date-fns/tz usage, covering imports, parsing/formatting, calculations, timezone-safe patterns, and common pitfalls.4---56# date-fns + @date-fns/tz78## Purpose910Use this skill to implement, review, and refactor date/time code with modern `date-fns` and the native timezone package `@date-fns/tz`.1112## Version baseline (re-check when invoked)1314- `date-fns` latest verified: `4.1.0`15- `@date-fns/tz` latest verified: `1.4.1`16- Re-check commands:17 - `npm view date-fns version`18 - `npm view @date-fns/tz version`19 - `npm view date-fns dist-tags --json`20 - `npm view @date-fns/tz dist-tags --json`2122## When to use2324- Parsing, validating, formatting, comparing, and calculating dates.25- Building timezone-aware business logic (scheduling, boundaries, reporting).26- Migrating date logic to immutable utility patterns.27- Hardening code against DST and token-format bugs.2829## Non-negotiable rules3031- Use native timezone package: `@date-fns/tz`.32- Do not recommend `date-fns-tz`.33- If legacy code already uses `date-fns-tz`, suggest migration to `@date-fns/tz`.34- Parse once, validate early (`isValid`), and pass `Date` values through operations.35- Use Unicode tokens correctly (`yyyy`, `MM`, `dd`) and avoid Moment-style token assumptions.36- For timezone-sensitive calculations, use explicit timezone context (`TZDate` or `{ in: tz("...") }`).3738## Canonical imports3940```ts41import { format, parseISO, isValid, addDays, startOfDay } from "date-fns";42import { TZDate, tz, tzOffset, tzName, tzScan } from "@date-fns/tz";43```4445## Workflow4647### 1) Normalize input4849- Use `parseISO`/`toDate` for conversion.50- Guard with `isValid`.51- Keep internal values as `Date`/`TZDate`, not mixed string math.5253### 2) Compute with pure helpers5455- Prefer `add/sub`, `differenceIn*`, `startOf*/endOf*`, `isSame*`, `isWithinInterval`.56- Avoid mutating `Date` via setters unless there is a clear reason.5758### 3) Apply timezone context explicitly5960- Option A: use `TZDate` values.61- Option B: use date-fns `in` option with `tz("Area/City")` for deterministic zone context.6263### 4) Format/output safely6465- Use `format` for display.66- Use standards helpers for exchange formats (`formatISO`, `formatRFC3339`).67- Keep transport format and display format separate.6869## Deliverables7071When answering, provide:7273- Exact imports.74- Minimal correct function set for the use case.75- Timezone strategy (`TZDate` vs `{ in: tz(...) }`) and why.76- Edge-case notes (DST boundaries, token correctness, invalid inputs).7778## Progressive disclosure7980Load only what is needed:8182- `reference/core-functions.md` for essential helpers.83- `reference/native-timezones.md` for `@date-fns/tz` patterns.84- `reference/imports-and-practices.md` for import/runtime practices.85- `reference/format-parse-tokens.md` for token correctness.86- `reference/examples.md` for copy-ready snippets.87- `reference/anti-patterns.md` for strict "never use `date-fns-tz`" guidance.88- `reference/version-and-sources.md` for version checks and source links.