Skip to content

toExcelSerial

toExcelSerial(isoString: string, options?: { system?: ExcelDateSystem; }): number | null

Convert an ISO 8601 instant string to an Excel day serial.

  • The serial is days, with the time of day as the fraction: 45361.5 is midday on 2024-03-10. The date is the UTC wall clock — a zoned input is converted to UTC first, so "2024-03-10T12:00:00-05:00" is serial 45361.708…, the 17:00 UTC it names.
  • The 1900 system’s serial 60 is the phantom 29 February 1900, a date that never existed — 1900 was not a leap year. Lotus 1-2-3 got it wrong and Excel keeps the bug for compatibility. No instant maps to serial 60: 1900-02-28 is 59 and 1900-03-01 is 61. Silently “fixing” this would put GMT one day out from Excel for every date before March 1900.
  • Instants outside Excel’s own serial range are invalid input, not an out-of-range number: the 1900 system runs from serial 1 (1900-01-01) to 2958465 (9999-12-31), the 1904 system from serial 0 (1904-01-01) to 2957003. Serial 0 in the 1900 system is Excel’s “January 0, 1900” placeholder, not a date, so it is rejected too.
  • The serial is a double, as it is in a workbook. The whole-day part is exact; the intra-day fraction is not, so precision below roughly a microsecond is not representable, and it degrades toward year 9999. Round-tripping through fromExcelSerial is exact to the millisecond, which is as fine as Excel itself goes.
  • The last ~20 µs of 9999-12-31 returns null, from "9999-12-31T23:59:59.999979884Z" on. A double near serial 2958465 resolves to about 40 µs, so those instants round to exactly 2958466 — one past Excel’s last serial. The range check is deliberately made on the rounded serial rather than the exact instant, so a returned number is always one Excel accepts; the alternative is handing back a 2958466 that Excel rejects on the way in.
ParameterTypeDescription
isoStringstringISO 8601 instant string (e.g. “2024-03-10T12:00:00Z”)

options

Which Excel date system the serial is in

OptionTypeDefaultDescription
system?"1900" | "1904" (ExcelDateSystem)"1900"Which Excel date system the serial is counted in. "1900" counts serial 1 as 1900-01-01 and has the phantom serial 60; "1904" is the legacy Mac system, whose serial 0 is 1904-01-01 and which has no phantom day. The same instant is exactly 1462 lower in the 1904 system.

Excel day serial as a number, or null on invalid input

import { toExcelSerial } from "@northguild/gmt/precision/convert";
toExcelSerial("1900-01-01T00:00:00Z") // 1 — Excel's first serial
output 

precision/convert/toExcelSerial.ts