ZonedDateTime class

A date-time with a timezone such as 2023-04-13 10:15:30+08:00 Asia/Singapore.

A ZonedDateTime is immutable. It can represent a specific point in time. Time is stored to microsecond precision.

It can represent date-times with:

  • A fixed offset from UTC across all points in time.
  • A timezone in the IANA TZ database, including geographical locations with varying offsets across points in time.

Caveats

By default, ZonedDateTime.now without specifying a timezone only works on Windows, MacOS, Linux and web. The Factory timezone will be returned on all other platforms. This is due to limitations with dart:ffi. See Timezone.platformTimezoneProvider.

Timezones Transitions

Obtaining the offset for a local date-time is not trivial. Due to timezone transitions, it is possible for a local date-time to be ambiguous or invalid. There are three cases.

Normal, with one valid offset. This is the case for most of the year.

Gap, with zero offsets. This is when the clock jumps forward, when transitioning from winter to summer time. If a local date-time fails in the middle of a gap, the offset after the gap, i.e. summer time, is returned.

Clock jumping forward

// EST to EDT transition occurs at 2023-03-12 02:00
// Offset from -05:00 to -04:00
//
// https://www.timeanddate.com/time/change/usa/detroit?year=2023

final datetime = ZoneDateTime('America/Detroit', 2023, 3, 12, 2, 30);
print(datetime); // 2023-03-12 03:30-04:00 [America/Detroit]

Overlap, with two valid offsets. This is when clocks are set back, typically when transitioning from summer to winter time. If a local date-time falls in the middle of an overlap, the offset before the overlap, i.e. winter time, is returned.

Clock moving backwards

// EDT to EST transition occurs at 2023-11-05 01:00
// Offset from -04:00 to -05:00
//
// https://www.timeanddate.com/time/change/usa/detroit?year=2023

final datetime = ZoneDateTime('America/Detroit', 2023, 11, 5, 1, 30);
print(datetime); // 2023-11-05 01:30-05:00 [America/Detroit]

Working with ZonedDateTimes

To create a ZonedDateTime:

final now = ZonedDateTime.now();
final berlinWallFall = ZonedDateTime('Europe/Berlin'), 1989, 11, 9, 18, 53);

You can add and subtract different types of time intervals, including:

Duration stores a fixed quantity of time in microseconds while Period and the individual units of time represent the conceptual units of time. For example, a duration of 1 day is always 86,400,000,000 microseconds while a period of 1 day is 1 "day". This leads to differences when adding/subtracting from a ZonedDateTime near a DST transition.

// DST occurs at 2023-03-12 02:00
// https://www.timeanddate.com/time/change/usa/detroit?year=2023

final datetime = ZoneDateTime('America/Detroit', 2023, 3, 12);

datetime.add(Duration(days: 1)); // 2023-03-13 01:00
datetime + Period(days: 1);      // 2023-03-13 00:00

ZonedDateTime can be compared with isBefore, isSameMomentAs and isAfter. Two ZonedDateTime may be in different timezones but still represent the same moment. However, they are only considered equal, using ==, if they represent the same moment in the same timezone.

final singapore = ZonedDateTime('Asia/Singapore', 2023, 5, 11, 13, 11);
final tokyo = ZonedDateTime('Asia/Tokyo', 2023, 5, 11, 14, 11);

print(singapore.isSameMomentAs(tokyo); // true;
print(singapore == tokyo); // false

You can also truncate, round, ceil and floor ZonedDateTime.

print(berlinWallFall.truncate(to: DateTime.days); // 1989-11-09 00:00
print(berlinWallFall.round(TimeUnit.hours, 12);   // 1989-11-10 00:00
print(berlinWallFall.ceil(TimeUnit.hours, 5);     // 1989-11-10 00:00
print(berlinWallFall.floor(TimeUnit.hours, 5);    // 1989-11-09 12:00

Constructors

ZonedDateTime(String timezone, int year, [int month = 1, int day = 1, int hour = 0, int minute = 0, int second = 0, int millisecond = 0, int microsecond = 0])
Creates a ZonedDateTime.
factory
ZonedDateTime.from(Timezone timezone, int year, [int month = 1, int day = 1, int hour = 0, int minute = 0, int second = 0, int millisecond = 0, int microsecond = 0])
Creates a ZonedDateTime.
factory
ZonedDateTime.fromEpochMicroseconds(Timezone timezone, EpochMicroseconds microseconds)
Creates a ZonedDateTime that represents the microseconds since Unix epoch (January 1st 1970) in the timezone.
ZonedDateTime.fromEpochMilliseconds(Timezone timezone, EpochMilliseconds milliseconds)
Creates a ZonedDateTime that represents the milliseconds since Unix epoch (January 1st 1970) in the timezone.
ZonedDateTime.now([Timezone? timezone])
Creates a ZonedDateTime that represents the current date-time in the timezone.
factory

Properties

day int
The day.
no setterinherited
dayOfYear int
The ordinal day of the year.
no setter
daysInMonth int
The number of days in the month.
no setter
epochMicroseconds EpochMicroseconds
The microseconds since Unix epoch.
final
epochMilliseconds EpochMilliseconds
The milliseconds since Unix epoch.
no setter
firstDayOfMonth ZonedDateTime
The first day of the month.
no setter
firstDayOfWeek ZonedDateTime
The first day of the week.
no setter
hashCode int
The hash code for this object.
no setteroverride
hour int
The hour.
no setterinherited
lastDayOfMonth ZonedDateTime
The last day of the month.
no setter
lastDayOfWeek ZonedDateTime
The last day of the week.
no setter
leapYear bool
Whether this year is a leap year.
no setter
microsecond int
The microsecond.
no setterinherited
millisecond int
The millisecond.
no setterinherited
minute int
The minute.
no setterinherited
month int
The month.
no setterinherited
runtimeType Type
A representation of the runtime type of the object.
no setterinherited
second int
The second.
no setterinherited
span TimezoneSpan
The span in which this date-time occurs.
final
timezone Timezone
The timezone.
final
weekday int
The day of the week.
no setter
weekOfYear int
The ordinal week of the year.
no setter
year int
The year.
no setterinherited

Methods

add(Duration duration) ZonedDateTime
Returns a copy of this with the duration added.
ceil(TemporalUnit unit, int value) ZonedDateTime
Returns a copy of this ceiled to the nearest unit and value.
copyWith({Timezone? timezone, int? year, int? month, int? day, int? hour, int? minute, int? second, int? millisecond, int? microsecond}) ZonedDateTime
Returns a copy of this with the updated units of time.
difference(ZonedDateTime other) Duration
Returns the difference in exact microseconds between this and other.
floor(TemporalUnit unit, int value) ZonedDateTime
Returns a copy of this floored to the nearest unit and value.
isAfter(ZonedDateTime other) bool
Returns true if this is after other.
isBefore(ZonedDateTime other) bool
Returns true if this ZonedDateTime is before other.
isSameMomentAs(ZonedDateTime other) bool
Returns true if this occurs at the same moment as other.
minus({int years = 0, int months = 0, int days = 0, int hours = 0, int minutes = 0, int seconds = 0, int milliseconds = 0, int microseconds = 0}) ZonedDateTime
Returns a copy of this with the units of time subtracted.
noSuchMethod(Invocation invocation) → dynamic
Invoked when a nonexistent method or property is accessed.
inherited
plus({int years = 0, int months = 0, int days = 0, int hours = 0, int minutes = 0, int seconds = 0, int milliseconds = 0, int microseconds = 0}) ZonedDateTime
Returns a copy of this with the units of time added.
round(TemporalUnit unit, int value) ZonedDateTime
Returns a copy of this rounded to the nearest unit and value.
subtract(Duration duration) ZonedDateTime
Returns a copy of this with the duration subtracted.
toLocal() LocalDateTime
Converts this to a LocalDateTime.
toString() String
Returns a ISO-8601 formatted string.
override
truncate({required TemporalUnit to}) ZonedDateTime
Returns a copy of this truncated to the TemporalUnit.

Operators

operator +(Period period) ZonedDateTime
Returns a copy of this with the period added.
operator -(Period period) ZonedDateTime
Returns a copy of this with the period subtracted.
operator ==(Object other) bool
Returns true if other is a ZonedDateTime at the same moment and in the same timezone.
override