-
-
Notifications
You must be signed in to change notification settings - Fork 36
Description
Description
The format() function throws Error: Invalid offset format on Microsoft Edge 32-bit (Chromium-based, version 144.0.3719.82). The same code works perfectly on Edge 64-bit.
Root Cause
Edge 32-bit has a bug in Intl.DateTimeFormat.formatToParts() where time components are silently dropped when:
- A non-UTC timezone is specified (e.g.,
timeZone: 'Europe/Berlin') - AND time options use
'2-digit'format
This causes tempo's offset() function (in offset.mjs) to receive incomplete date parts, resulting in an invalid Date object and ultimately NaN values in the offset calculation.
Reproduction
// This works on Edge 64-bit but FAILS on Edge 32-bit
import { format } from '@formkit/tempo';
const date = new Date('2026-01-20T08:07:40.000Z');
const result = format(date, 'YYYY-MM-DD HH:mm:ss');
// Edge 32-bit throws: Error: Invalid offset formatDebug Information
Edge 32-bit behavior with Intl.DateTimeFormat:
// Using '2-digit' - BROKEN on Edge 32-bit
const formatter = new Intl.DateTimeFormat('en-US', {
timeZone: 'Europe/Berlin',
year: 'numeric', month: '2-digit', day: '2-digit',
hour: '2-digit', minute: '2-digit', second: '2-digit',
hourCycle: 'h23'
});
console.log(formatter.formatToParts(new Date()));
// Output on Edge 32-bit (TIME PARTS MISSING!):
[
{ "type": "month", "value": "01" },
{ "type": "literal", "value": "/" },
{ "type": "day", "value": "20" },
{ "type": "literal", "value": "/" },
{ "type": "year", "value": "2026" }
]
// Using 'numeric' - WORKS on Edge 32-bit
const formatter2 = new Intl.DateTimeFormat('en-US', {
timeZone: 'Europe/Berlin',
year: 'numeric', month: '2-digit', day: '2-digit',
hour: 'numeric', minute: 'numeric', second: 'numeric'
});
console.log(formatter2.formatToParts(new Date()));
// Output on Edge 32-bit (correct):
[
{ "type": "month", "value": "01" },
{ "type": "literal", "value": "/" },
{ "type": "day", "value": "20" },
{ "type": "literal", "value": "/" },
{ "type": "year", "value": "2026" },
{ "type": "literal", "value": ", " },
{ "type": "hour", "value": "10" },
{ "type": "literal", "value": ":" },
{ "type": "minute", "value": "47" },
{ "type": "literal", "value": ":" },
{ "type": "second", "value": "30" },
{ "type": "literal", "value": " " },
{ "type": "dayPeriod", "value": "AM" }
]How tempo fails
format()callsoffset(inputDate, tz, "utc")informat.mjs:30offset()usesrelativeTime()which callsIntl.DateTimeFormat(...).formatToParts()- On Edge 32-bit,
formatToParts()returns only date parts (no hour/minute/second) relativeTime()constructs:"2026-01-20T${undefined}:${undefined}:${undefined}Z"new Date(...)returns Invalid DategetTime()returnsNaNsecsToOffset(NaN)produces"+NaN:NaN:NaN"fixedLengthByOffset("+NaN:NaN:NaN")throws"Invalid offset format"
Environment
- Browser: Microsoft Edge 144.0.3719.82 (Official build) (32-bit) - Chromium-based
- OS: Windows
- @formkit/tempo version: 1.0.0
Suggested Fix
Option 1: Add try/catch in format() with graceful degradation
Option 2: In offset.mjs, validate that relativeTime() returns a valid Date before calculating offset
Option 3: Consider using 'numeric' instead of '2-digit' for internal Intl.DateTimeFormat options (though this may affect output formatting)
Workaround
We've implemented a wrapper that catches the error and falls back to native Date formatting:
import { format as tempoFormat } from '@formkit/tempo';
export function format(date, formatStr) {
try {
return tempoFormat(date, formatStr);
} catch {
// Native fallback for Edge 32-bit
const pad = (n) => n.toString().padStart(2, '0');
return `${date.getFullYear()}-${pad(date.getMonth() + 1)}-${pad(date.getDate())} ${pad(date.getHours())}:${pad(date.getMinutes())}:${pad(date.getSeconds())}`;
}
}Related
This is a Chromium/Edge bug that should also be reported to Microsoft, but tempo could be more resilient to malformed Intl responses.