Timespans

Timespans

Timespan represents an exact interval of time with nanosecond precision. You can create one with any combination of days, hours, minutes, seconds, milliseconds, microseconds, and nanoseconds. Some examples:

Timespan(days: 90);
Timespan(hours: 5, minutes: 32);
Timespan(seconds: 2, nanoseconds: 25);

You can also convert back to an integer number of different time units:

Timespan(days: 1).inSeconds = 86400;
Timespan(hours: 1, minutes: 30).inMinutes = 90;

It’s important to note, however, that the precision of Timespan exceeds a single integer, so be careful of overflow when dealing with numbers larger than 53 bits.

Timespans can be added or subtracted from one another:

Timespan(days: 1) + Timespan(hours: 12) == Timespan(hours: 36);
Timespan(days: 1) - Timespan(hours: 12) == Timespan(hours: 24);

They can be negated, and you can take the absolute value:

Timespan(hours: -3) == -Timespan(hours: 3);
Timespan(hours: -3).abs() == Timespan(hours: 3);

They can even be divided by a number:

Timespan(minutes: 60) ~/ 2 == Timespan(minutes: 30);

Adding a Timespan to a datetime adds exactly that amount. For the local types like LocalDateTime this is straightforward. Adding a duration of 1 day and 12 hours to January 2 at 12:30 PM, gives January 4 at 12:30 AM:

final date = LocalDateTime(2025, 1, 2, 12, 30);
date.plusTimespan(Timespan(days: 1, hours: 12)) ==
  LocalDateTime(2025, 1, 4, 0, 30);

Which is exactly the same as adding 36 hours:

date.plusTimespan(Timespan(hours: 36)) ==
  LocalDateTime(2025, 1, 4, 0, 30);

You can also find the exact amount of time between two datetimes:

final date1 = LocalDateTime(2025, 1, 1, 12, 30);
final date2 = LocalDateTime(2025, 1, 2, 13, 30);
date1.timespanUntil(date2) == Timespan(hours: 25);

Things get more complicated, however, with ZonedDateTime. It tracks civil time changes in a specific location, along with all the complexities that entails. For example, what is the timespan between November 2, 2025 at 12:30 PM and November 3, 2025 at the same time of day?

defaultZoneId = 'America/Los_Angeles';
final date1 = ZonedDateTime(2025, 11, 1, 12, 30);
final date2 = ZonedDateTime(2025, 11, 2, 12, 30);
date1.timespanUntil(date2) // == What?

If you answered 25 hours, congratulations. You apparently have a time zone database in your head. The Pacific time zone switched from daylight savings to standard time at 2:00 AM on November 2, 2025. The clock jumped back to 1:00 AM, adding an extra hour to the day.

A similar thing happens when you add a Timespan. For example, adding 1 day results in November 3, 2025 at 11:30 AM. That that extra hour strikes again:

date1.plusTimespan(Timespan(days: 1)) ==
  ZonedDateTime(2025, 11, 3, 11, 30);

When you remember ZonedDateTime is an absolute moment in time, and Timespan is a fixed interval of time, this behavior makes sense. November 2, 2025 had an extra hour. But if you write code that adds one day to a datetime, this is probably not what you intended. You probably want a Period.