ZonedDateTime
A ZonedDateTime represents a date-time with a time offset and/or a time zone in the ISO-8601 calendar system.
On its own, ZonedDateTime only supports specifying time offsets such as UTC or UTC+02:00, plus the SYSTEM time zone ID.
The SYSTEM zone ID
The SYSTEM zone ID is a non-standard ID that is specific to js-joda. It represents the default time zone of the current JavaScript runtime. The JavaScript spec does not provide an API this; it only provides the system default time offset for a point in the timeline (Date.prototype.getTimezoneOffset()).
You should not exchange ZonedDateTime instances using the SYSTEM zone ID between JavaScript environments (e.g. between server and client, or between two servers). The time offset on another machine won't necessarily be the same as yours. Before sending a ZonedDateTime to someone else, convert it to a fixed offset:
// current time with default `SYSTEM`
ZonedDateTime.now().toString(); // e.g. 2016-03-18T12:38:23.561+01:00[SYSTEM]
// converted to a fixed time offset
ZonedDateTime.now()
.withFixedOffsetZone()
.toString(); // e.g. 2016-03-18T12:38:23.561+01:00
Working with time zones
A time zone and a time offset are not the same thing. Some timezones change from standard time to daylight savings time and back every year:
- In the
Europe/Berlintime zone, the time offset isUTC+2during the summer, andUTC+1during the rest of the year. - In the
Africa/Lagostime zone, on the other hand, the time offset isUTC+1all year round.
Calculations that might span time zones or daylight savings transitions need to reference the time zone, not just the offset.
The @js-joda/timezone package provides bindings to the the IANA tz database, making joda-js's calculations time zone aware. The tz database uses zone names like Africa/Bujumbura, America/New_York, and Europe/Lisbon (see the full list).
To specify time zones using these names, you just need to require @js-joda/timezone.
var jsJoda = require("@js-joda/core");
require("@js-joda/timezone");
var zdt = ZonedDateTime.now(ZoneId.of("Europe/Paris"));
Create a ZonedDateTime
// get now with the default system time zone
ZonedDateTime.now().toString(); // e.g. 2016-03-18T12:38:23.561+01:00[SYSTEM]
// get now with the UTC time zone
ZonedDateTime.now(ZoneOffset.UTC).toString(); // e.g. 2016-03-18T11:38:23.561Z
// get now with a fixed offset time zone
ZonedDateTime.now(ZoneId.of("UTC-05:00")).toString(); // e.g. 2016-03-18T06:38:23.561-05:00[UTC-05:00]
// get now with a ZoneRegion (requires `@js-joda/timezone`)
ZonedDateTime.now(ZoneId.of("Europe/Paris")).toString(); // e.g. 2017-02-04T17:01:15.846+01:00[Europe/Paris]
// parse a date time with a time zone ISO String
ZonedDateTime.parse("2016-03-18T12:38:23.561+01:00[SYSTEM]");
ZonedDateTime.parse("2016-03-18T12:38:23.561+01:00");
ZonedDateTime.parse("2016-03-18T11:38:23.561Z");
ZonedDateTime.parse("2016-03-18T06:38:23.561-05:00[UTC-05:00]");
ZonedDateTime.parse("2017-02-04T17:01:15.846+01:00[Europe/Paris]");
// create from a LocalDate(Time) (requires `@js-joda/timezone`)
LocalDate.parse("2012-06-06")
.atStartOfDay()
.atZone(ZoneId.of("Europe/Paris")); // 2012-06-06T00:00+02:00[Europe/Paris]
ZonedDateTime.of(
LocalDateTime.parse("2012-06-06T00:00"),
ZoneId.of("Europe/Paris")
); // 2012-06-06T00:00+02:00[Europe/Paris]
ZonedDateTime.of(
LocalDate.parse("2012-06-06"),
LocalTime.MIDNIGHT,
ZoneId.of("Europe/Paris")
); // 2012-06-06T00:00+02:00[Europe/Paris]
// create from an Instant
ZonedDateTime.ofInstant(Instant.now(), ZoneId.SYSTEM); // current system time
Switch time zones
These examples require
@js-joda/timezone.
var d = LocalDate.of(2016, 3, 18);
var zdt = d.atTime(LocalTime.NOON).atZone(ZoneId.of("America/New_York")); //2016-03-18T12:00-04:00[America/New_York]
// switch time zone retaining the local date-time if possible
zdt.withZoneSameLocal(ZoneId.of("Europe/Berlin")); // 2016-03-18T12:00+01:00[Europe/Berlin]
// switch time zone and retain the instant
zdt.withZoneSameInstant(ZoneId.of("Europe/Berlin")); // 2016-03-18T17:00+01:00[Europe/Berlin]
Get and manipulate values from a ZonedDateTime
ZonedDateTime implements the same methods as LocalDateTime for getting or setting values. See the examples above for LocalDateTime.
Calculate values across daylight savings transitions
When adding to or subtracting from a ZonedDateTime instance, the calculation is different depending on whether date or time units are passed.
- Addition/subtraction of date units are made on the local timeline.
- Addition/subtraction of time units are made on the instant timeline.
This example shows the difference for a daylight saving transition.
// assume the system default time zone is CET; we define a time as 2016-03-18 at 17:00 local time
var zdt = ZonedDateTime.parse("2016-03-18T17:00+01:00[Europe/Berlin]");
// adding a date unit of 2 weeks, crossing a daylight saving transition
zdt.plusWeeks(2); // 2016-04-01T17:00+02:00[Europe/Berlin] (still 17:00)
// adding a time unit of 2 weeks (2 * 7 * 24)
zdt.plusHours(2 * 7 * 24); // 2016-04-01T18:00+02:00[Europe/Berlin] (now 18:00)
