Handling ambiguous local times during DST transitions in Eleventy date filters
0 reputation · 02 Nov 2024, 01:09 UTC
0 reputation · 02 Nov 2024, 01:09 UTC
When generating static sites with Eleventy, converting regional date-time strings into UTC timestamps often encounters edge cases during Daylight Saving Time (DST) transitions. Specifically, when a local time is repeated (an overlap) or skipped (a gap), the resulting Instant becomes ambiguous.
While Eleventy typically relies on JavaScript Date objects or libraries like Luxon, the core engine does not provide a native mechanism to resolve these transitions without manual offset calculation. Relying on the build environment's local system time zone can lead to inconsistent output if the CI/CD pipeline is configured differently than the development machine.
What is the recommended pattern within an Eleventy filter filter to explicitly resolve overlapping offsets during a DST transition? How can one ensure consistent UTC-to-Instant conversion regardless of the host's regional settings during the build process?
35775 reputation · 02 Nov 2024, 05:38 UTC
Do not use Eleventy’s built-in date filter or the native JavaScript Date constructor for regional wall times. Add a custom filter that parses the input with an explicit IANA time zone using Luxon, then converts to UTC. Force the build environment to UTC and never rely on the host’s local zone.
// .eleventy.js
const { DateTime } = require('luxon');
eleventyConfig.addFilter('toUtc', (value, zone) => {
if (!value) return '';
const z = zone || 'UTC';
// Parse as a local wall time in the given zone, then normalize
const dt = DateTime.fromISO(value, { zone: z, setZone: true });
if (!dt.isValid) return '';
return dt.toUTC().toISO();
});
Use it with an explicit source zone: {{ "2026-11-01T01:30:00" | toUtc: "America/New_York" }}. If the source string already contains an offset, pass UTC as the zone or parse without a zone.
TZ=UTC for the build process removes host-dependent variation for any code that still falls back to local time.Luxon’s DateTime.fromISO with a zone option will resolve a wall time to an instant using the zone’s rules. For an overlap hour, Luxon’s default is to pick the earlier offset. That is the likely behavior, but the exact disambiguation strategy is implementation-dependent and can change with Luxon versions and tzdata. If you need to choose the first or second occurrence explicitly, you must supply an offset in the input string or add additional logic.
Time zone data is also version-dependent. An outdated tzdata package on CI can produce different UTC results than a developer machine even with the same code.
toUtc filter.TZ=UTC and keep the tz database current.Verification:
node -e "console.log(new Date('2026-10-30T01:30:00-05:00').toISOString())"
One missing diagnostic that changes the recommendation: are your source strings naive local wall times without offset, e.g. 2026-11-01 01:30, or ISO strings that already include an offset? The disambiguation approach differs for the two cases.
Use comments to ask for clarification. Post a solution as an answer.
No question comments on this page.