Schedule-X & Temporal API
Schedule-X uses the Temporal API to handle dates and times. If you are not yet familiar with this API or its background, here’s a blog post that explains some of its benefits: https://docs.timetime.in/blog/js-dates-finally-fixed/
Since Temporal only started becoming available in browsers in 2025, most users of Schedule-X will need to polyfill it. On the one hand, this adds a dependency to your project, but on the other hand, it allows Schedule-X to tap into date and time features that are not available in the native Date API. This made it possible to implement support for timezones with very little effort, which is something the community has requested repeatedly.
Polyfilling Temporal
There are at least 2 well-maintained polyfills available for Temporal:
Example
import 'temporal-polyfill/global'
const date = Temporal.PlainDate.from('2025-01-01')
console.log(date.toString())
const calendar = createCalendar({
events: [
{
id: 1,
start: Temporal.PlainDate.from('2025-01-01'),
end: Temporal.PlainDate.from('2025-01-02'),
},
{
id: 2,
start: Temporal.ZonedDateTime.from('2025-01-01T12:00:00+01:00[Europe/Berlin]'),
end: Temporal.ZonedDateTime.from('2025-01-01T13:00:00+01:00[Europe/Berlin]'),
}
]
})
Browser support
If you know all of your users well, and know that they are using a browser that supports Temporal, you do not need to polyfill it.
You can check current browser support for Temporal here: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal#browser_compatibility
Converting different date and time formats to Temporal
RFC 9557
If you are setting up a new application, consider saving strings compatibe with RFC 9557 in your DB. These are likely the future of date and time formats on the internet anyway.
If you do, you can simply convert them to the appropriate Temporal object like so:
const plainDate = Temporal.PlainDate.from('1996-12-19')
const zonedDateTime = Temporal.ZonedDateTime.from('1996-12-19T16:39:57-08:00[America/Los_Angeles]')
Old custom Schedule-X date and time formats
Schedule-X used to have its own custom date and time formats. These are not compatible with Temporal, but you can convert them to Temporal like so:
const oldDateString = '2025-01-01'
const plainDate = Temporal.PlainDate.from(oldDateString)
function convertOldDateTimeStringToZonedDateTime(dateString: string): Temporal.ZonedDateTime {
const [date, time] = dateString.split(' ')
const [year, month, day] = date.split('-')
const [hour, minute] = time.split(':')
return Temporal.ZonedDateTime.from({
year: parseInt(year),
month: parseInt(month),
day: parseInt(day),
hour: parseInt(hour),
minute: parseInt(minute),
timeZone: 'UTC',
})
}
const oldDateTimeString = '2025-01-01 12:00'
const zonedDateTime = convertOldDateTimeStringToZonedDateTime(oldDateTimeString)
JS Date
If you are using a JS Date object, you can first convert it to a Temporal.Instant, and then convert it to a Temporal.ZonedDateTime:
function dateToZonedDateTime(date, timeZone = "UTC") {
// Convert JS Date → Instant
// This is basically the Temporal equivalent of a JS Date
// i.e. a plain point in time represented by a number of milliseconds since the Unix epoch
const instant = Temporal.Instant.fromEpochMilliseconds(date.getTime());
// Convert Instant → ZonedDateTime
return instant.toZonedDateTimeISO(timeZone);
}
const jsDate = new Date('2025-01-01T12:00:00Z')
const zonedDateTime = dateToZonedDateTime(jsDate, 'Europe/Berlin')