Blog·Craft·

A timezone conversion keeps the same instant

Local dates can differ while Unix seconds stay the same. Use the Time response to carry both the clock reading and the moment it represents.

A meeting at three in the afternoon in New York can land on tomorrow's calendar in Tokyo. The two dates look different, but everyone still needs to join the same call.

The Time API returns both views of that moment. In API 2.0.0, this request converts a New York clock reading to Tokyo time:

GET /time/America/New_York?to=Asia/Tokyo&at=2026-09-16T15:00

The response includes this excerpt:

{
  "timezone": "America/New_York",
  "at": "2026-09-16T15:00:00-04:00",
  "unix": 1789585200,
  "to": {
    "timezone": "Asia/Tokyo",
    "at": "2026-09-17T04:00:00+09:00",
    "unix": 1789585200
  }
}

The source and target have the same unix value because the conversion preserves the instant. Their at strings express that instant on different local clocks, complete with the date and UTC offset. These fields are in the basic response. You don't need deep=true to convert a time.

The input deserves some care. When you pass to, a timestamp without an offset is read as local time in the source zone. That's what makes 15:00 mean New York afternoon in this example. An explicit offset, including the Z for UTC, identifies the instant directly. Sending at=2026-09-16T19:00:00Z in the same conversion gives the same answer. Without to, an offsetless at is interpreted as UTC, so keep the offset when passing a timestamp you've already resolved.

For a JavaScript date, unix is measured in seconds and the numeric Date constructor takes milliseconds:

const instant = new Date(result.unix * 1000)
instant.toISOString() // "2026-09-16T19:00:00.000Z"

Don't add the returned UTC offset to that number. It already identifies the meeting's instant. Apply a timezone when displaying the date, or use the returned local at value when you want the API's representation.

There is a precision difference to keep in mind. unix is rounded down to whole seconds, while at preserves milliseconds supplied in the request. If your application needs those fractions, retain the timestamp rather than reconstructing it from integer seconds.

For a recurring meeting, keep its intended local time and timezone too. One resolved instant is enough for this occurrence. It cannot specify how next month's occurrence should follow a changing local clock. The Time reference explains conversion inputs and how repeated or skipped local times are resolved.