Watch the video (8 min)
On this page23 sections
  1. Prerequisites
  2. Connection With Previous Lectures
  3. Learning Objectives
  4. 1. What Is a Duration?
  5. 2. Reading a Duration
  6. 3. Duration Arithmetic
  7. 4. Moving a Date with add and subtract
  8. 5. The Gap Between Two Dates
  9. 6. Days Until an Event
  10. 7. Calculating Age
  11. 8. The Daylight Saving Trap
  12. 9. Formatting a Duration as h:mm:ss
  13. 10. Stopwatch Gives a Duration
  14. 11. A Real-World Example
  15. Code Examples
  16. Common Beginner Mistakes
  17. Best Practices
  18. Mini Challenge
  19. Practice Questions
  20. Practice Answers
  21. Quick Revision
  22. Key Takeaways
  23. What's Next?

Lecture 111 — Duration & Time Calculations

Category18 — Files, JSON & Core Utilities
Lecture111 of 140
Estimated video length8 min
TargetDart 3.12.2
LevelIntermediate

A DateTime says when something happens, but not how long it lasts or how far away it is. A Duration measures the gap — and lets you add it, compare it, and print it.

Contents

Prerequisites · Connection · Objectives · Lesson · Code Examples · Common Mistakes · Best Practices · Mini Challenge · Practice Questions · Answers · Takeaways

Every error message in this lecture is real. Each one was produced by running the code shown on Dart 3.12.2, so you will recognize it when you meet it yourself.


Prerequisites

Students should already understand, from Lectures 001–110:

  • integer division ~/, remainder %, and padLeft (Lectures 008, 017)
  • Future.delayed, Duration(seconds: …) and Stopwatch (Lectures 087, 091)
  • creating dates with DateTime(…) and DateTime.utc(…), and reading year, month, day (Lecture 110)

Connection With Previous Lectures

In Lecture 110 we created exact moments:

dart
void main() {
  var examDay = DateTime.utc(2026, 12, 20);
  print(examDay);
}
output
2026-12-20 00:00:00.000Z

Now Sara asks: how many days until the exam? What date is 30 days after today? How old is Ali? Each question is about the distance between two moments, and a DateTime alone cannot answer it.


Learning Objectives

By the end of this lecture you will be able to:

  • Create a Duration from days, hours, minutes and seconds
  • Read a duration with inDays, inHours, inMinutes and inSeconds
  • Explain why those properties cut off the remainder
  • Add, subtract, multiply and compare durations
  • Move a date with add and subtract, and measure a gap with difference
  • Calculate days until an event and a person's age
  • Avoid the daylight saving trap when adding calendar days
  • Format a duration as h:mm:ss

1. What Is a Duration?

A Duration is a length of time with no date attached: "90 minutes", not "Tuesday at 9".

Analogy — a DateTime is a spot on a ruler; a Duration is the distance between two spots. "2 cm" means the same wherever you measure it.

Every parameter is named and optional, and they add up:

dart
void main() {
  var lecture = Duration(hours: 1, minutes: 30);
  var trip = Duration(days: 2, hours: 5);
  print(lecture);
  print(trip);
}
output
1:30:00.000000
53:00:00.000000

print shows hours, minutes, seconds and microseconds. Days are turned into hours: 2 days and 5 hours is 53 hours.


2. Reading a Duration

The in… properties give the whole length in one unit, as an int:

dart
void main() {
  var movie = Duration(minutes: 150);
  print(movie.inHours);
  print(movie.inMinutes);
  print(movie.inSeconds);
}
output
2
150
9000

150 minutes is 2.5 hours, yet inHours says 2. These properties truncate: they drop the part that does not make a full unit, exactly like ~/. They never round up.

dart
void main() {
  var almostTwoDays = Duration(hours: 47, minutes: 59);
  print(almostTwoDays.inDays);
}
output
1

3. Duration Arithmetic

Durations work with +, -, * and the comparison operators:

dart
void main() {
  var morning = Duration(hours: 2, minutes: 15);
  var evening = Duration(hours: 1, minutes: 50);
  var total = morning + evening;
  print(total);
  print(morning - evening);
  print(evening * 3);
  print(total > Duration(hours: 4));
}
output
4:05:00.000000
0:25:00.000000
5:30:00.000000
true

Subtracting a longer duration gives a negative one. isNegative detects it, and abs() removes the sign:

dart
void main() {
  var gap = Duration(minutes: 10) - Duration(minutes: 25);
  print(gap);
  print(gap.isNegative);
  print(gap.abs());
}
output
-0:15:00.000000
true
0:15:00.000000

4. Moving a Date with add and subtract

A DateTime plus a Duration is a new DateTime. The original date never changes:

dart
void main() {
  var orderTime = DateTime.utc(2026, 10, 17, 9, 0);
  var delivery = orderTime.add(Duration(hours: 50));
  var reminder = orderTime.subtract(Duration(minutes: 30));
  print(delivery);
  print(reminder);
  print(orderTime);
}
output
2026-10-19 11:00:00.000Z
2026-10-17 08:30:00.000Z
2026-10-17 09:00:00.000Z

50 hours after 9:00 on the 17th is 11:00 on the 19th — Dart handles the days for you.


5. The Gap Between Two Dates

a.difference(b) returns the Duration from b to a:

dart
void main() {
  var start = DateTime.utc(2026, 10, 17, 9, 0);
  var end = DateTime.utc(2026, 10, 17, 17, 45);
  var worked = end.difference(start);
  print(worked);
  print(worked.inMinutes);
  print(start.difference(end));
}
output
8:45:00.000000
525
-8:45:00.000000

Read it as "end minus start". Swap them and the result is negative.


6. Days Until an Event

Combine difference with inDays:

dart
void main() {
  var today = DateTime.utc(2026, 10, 17);
  var exam = DateTime.utc(2026, 12, 20);
  var daysLeft = exam.difference(today).inDays;
  print('$daysLeft days until the exam');
}
output
64 days until the exam

In a real app, today comes from DateTime.now(). Strip the time first — DateTime.utc(now.year, now.month, now.day) — otherwise 14:00 today to midnight on exam day is 63 days and 10 hours, and inDays truncates it to 63.


7. Calculating Age

Age is not difference(...).inDays ~/ 365 — leap years make that wrong around birthdays. Count calendar years instead, then subtract one if this year's birthday has not happened yet:

dart
int ageOn(DateTime birth, DateTime today) {
  var age = today.year - birth.year;
  var hadBirthday =
      today.month > birth.month ||
      (today.month == birth.month && today.day >= birth.day);
  if (!hadBirthday) age--;
  return age;
}

void main() {
  var ali = DateTime.utc(2004, 12, 5);
  var sara = DateTime.utc(2006, 3, 14);
  var today = DateTime.utc(2026, 10, 17);
  print('Ali: ${ageOn(ali, today)}');
  print('Sara: ${ageOn(sara, today)}');
}
output
Ali: 21
Sara: 20

2026 − 2004 is 22, but Ali's birthday in December has not arrived, so he is 21.


8. The Daylight Saving Trap

Duration(days: 1) means exactly 24 hours. In countries with daylight saving time, a local calendar day is sometimes 23 or 25 hours long. On a computer set to New York time, clocks go back one hour on 1 November 2026:

dart
void main() {
  var day = DateTime(2026, 11, 1);
  print(day.add(Duration(days: 1)));
  print(DateTime(day.year, day.month, day.day + 1));
}
output
2026-11-01 23:00:00.000
2026-11-02 00:00:00.000

Adding 24 hours landed on the same date. The second line asks for "the next calendar day" directly, and Dart gets it right. Your output depends on your computer's time zone — in Pakistan, for example, both lines print 2026-11-02, because there is no daylight saving.

The constructor also rolls over months and years for you, so d + 1 is always safe:

dart
void main() {
  print(DateTime.utc(2026, 1, 31 + 1));
  print(DateTime.utc(2026, 12, 31 + 1));
}
output
2026-02-01 00:00:00.000Z
2027-01-01 00:00:00.000Z

Rule: for calendar days, use DateTime(y, m, d + n). For exact lengths of time (hours, minutes, a timer), use add(Duration(...)). UTC dates never shift, which is why this lecture counts days with DateTime.utc.

Time zones and local time were introduced in Lecture 110.


9. Formatting a Duration as h:mm:ss

print adds microseconds nobody wants. Build the text from whole units and the remainder %:

dart
String formatDuration(Duration d) {
  var hours = d.inHours;
  var minutes = (d.inMinutes % 60).toString().padLeft(2, '0');
  var seconds = (d.inSeconds % 60).toString().padLeft(2, '0');
  return '$hours:$minutes:$seconds';
}

void main() {
  print(formatDuration(Duration(seconds: 3725)));
  print(formatDuration(Duration(minutes: 7, seconds: 5)));
}
output
1:02:05
0:07:05

inMinutes of 3725 seconds is 62; % 60 keeps the 2 that does not fit in a full hour. padLeft turns 2 into 02.


10. Stopwatch Gives a Duration

In Lecture 091 we read stopwatch.elapsedMilliseconds. The elapsed property returns a full Duration, so everything in this lecture works on it:

dart
void main() async {
  var stopwatch = Stopwatch()..start();
  await Future.delayed(Duration(milliseconds: 1500));
  stopwatch.stop();
  var elapsed = stopwatch.elapsed;
  print(elapsed.inSeconds);
  print(elapsed > Duration(seconds: 1));
}
output
1
true

elapsed is about 1.5 seconds, and inSeconds truncates it to 1.


11. A Real-World Example

Zayan logs his study sessions. Each has a start and an end; the program totals them and checks the weekly goal:

dart
String formatDuration(Duration d) {
  var minutes = (d.inMinutes % 60).toString().padLeft(2, '0');
  var seconds = (d.inSeconds % 60).toString().padLeft(2, '0');
  return '${d.inHours}:$minutes:$seconds';
}

void main() {
  var sessions = [
    (DateTime.utc(2026, 10, 12, 16, 0), DateTime.utc(2026, 10, 12, 17, 20)),
    (DateTime.utc(2026, 10, 14, 18, 30), DateTime.utc(2026, 10, 14, 19, 15)),
    (DateTime.utc(2026, 10, 16, 15, 10), DateTime.utc(2026, 10, 16, 17, 0)),
  ];
  var goal = Duration(hours: 4);

  var total = Duration.zero;
  for (var (start, end) in sessions) {
    total += end.difference(start);
  }

  print('Studied: ${formatDuration(total)}');
  if (total >= goal) {
    print('Goal reached!');
  } else {
    print('Still to go: ${formatDuration(goal - total)}');
  }
}
output
Studied: 3:55:00
Still to go: 0:05:00

Duration.zero is an empty starting total, difference measures each session, += adds them, and comparison and subtraction decide the message.


Code Examples

Example 1 — Creating Durations

dart
void main() {
  print(Duration(minutes: 45));
  print(Duration(hours: 2, seconds: 30));
  print(Duration(milliseconds: 1500));
}
output
0:45:00.000000
2:00:30.000000
0:00:01.500000

Example 2 — Truncating Properties

dart
void main() {
  var d = Duration(hours: 3, minutes: 59);
  print(d.inHours);
  print(d.inMinutes);
}
output
3
239

Example 3 — Adding Durations

dart
void main() {
  var cooking = Duration(minutes: 40);
  var baking = Duration(minutes: 35);
  print(cooking + baking);
}
output
1:15:00.000000

Example 4 — Comparing Durations

dart
void main() {
  var aliRun = Duration(minutes: 24, seconds: 10);
  var saraRun = Duration(minutes: 23, seconds: 55);
  print(saraRun < aliRun ? 'Sara wins' : 'Ali wins');
}
output
Sara wins

Example 5 — A Date 30 Days Later

dart
void main() {
  var issued = DateTime.utc(2026, 10, 17);
  var due = issued.add(Duration(days: 30));
  print(due);
}
output
2026-11-16 00:00:00.000Z

Example 6 — Next Month, the Safe Way

dart
void main() {
  var payday = DateTime.utc(2026, 11, 25);
  var next = DateTime.utc(payday.year, payday.month + 2, payday.day);
  print(next);
}
output
2027-01-25 00:00:00.000Z

Month 13 rolls over into January of the next year.

Example 7 — Student Exam Time

dart
void main() {
  var start = DateTime.utc(2026, 10, 17, 9, 0);
  var handedIn = DateTime.utc(2026, 10, 17, 11, 25);
  var limit = Duration(hours: 2, minutes: 30);
  var used = handedIn.difference(start);
  print('Used ${used.inMinutes} of ${limit.inMinutes} minutes');
  print(used <= limit ? 'On time' : 'Late');
}
output
Used 145 of 150 minutes
On time

Example 8 — Shopping Delivery Date

dart
void main() {
  var ordered = DateTime.utc(2026, 10, 30);
  var shippingDays = 5;
  var arrives = DateTime.utc(
    ordered.year,
    ordered.month,
    ordered.day + shippingDays,
  );
  print('Arrives: ${arrives.day}/${arrives.month}/${arrives.year}');
}
output
Arrives: 4/11/2026

Example 9 — Bank Interest Days

dart
void main() {
  var deposited = DateTime.utc(2026, 1, 1);
  var withdrawn = DateTime.utc(2026, 7, 1);
  var days = withdrawn.difference(deposited).inDays;
  var balance = 10000.0;
  var interest = balance * 0.05 * days / 365;
  print('Days: $days');
  print('Interest: ${interest.toStringAsFixed(2)}');
}
output
Days: 181
Interest: 247.95

Example 10 — Temperature Readings Every 90 Minutes

dart
void main() {
  var first = DateTime.utc(2026, 10, 17, 6, 0);
  var temps = [18.5, 21.0, 24.5, 26.0];
  for (var i = 0; i < temps.length; i++) {
    var time = first.add(Duration(minutes: 90) * i);
    var minute = time.minute.toString().padLeft(2, '0');
    print('${time.hour}:$minute → ${temps[i]}°C');
  }
}
output
6:00 → 18.5°C
7:30 → 21.0°C
9:00 → 24.5°C
10:30 → 26.0°C

Common Beginner Mistakes

1. Expecting inHours to round

Duration(minutes: 119).inHours is 1, not 2. The in… properties always truncate. Use inMinutes (or smaller) when the remainder matters.

2. Passing a decimal to a Duration parameter

dart
void main() {
  // var d = Duration(hours: 1.5); // ✗
}
output
Error: The argument type 'double' can't be assigned to the parameter type 'int'.

Every parameter is an int. Write Duration(hours: 1, minutes: 30) or Duration(minutes: 90).

3. Using + on a DateTime

dart
void main() {
  var day = DateTime.utc(2026, 10, 17);
  // print(day + Duration(days: 1)); // ✗
}
output
Error: The operator '+' isn't defined for the type 'DateTime'.

Use day.add(Duration(days: 1)). Only two durations can be added with +.

4. Getting difference backwards

start.difference(end) is negative. Always write the later date first.

5. Adding 24-hour days to local dates

localDate.add(Duration(days: 1)) can land on 23:00 of the same day. For calendar days use DateTime(y, m, d + 1).

6. Forgetting % 60 when formatting

'${d.inHours}:${d.inMinutes}' prints 1:62 for 62 minutes. The minutes part needs d.inMinutes % 60.


Best Practices

  • Use named units that read naturally: Duration(minutes: 90), not Duration(seconds: 5400).
  • Use add(Duration(...)) for exact lengths of time, DateTime(y, m, d + n) for calendar days.
  • Count days between dates with UTC dates at midnight.
  • Calculate age from years, months and days — never by dividing days by 365.
  • Write your own formatDuration instead of printing raw microseconds to users.
  • Start totals at Duration.zero.

Mini Challenge

Sara's train leaves at 22:40 on 17 October 2026 and the trip takes 9 hours 35 minutes. Print the arrival time and the trip length as h:mm:ss. Use UTC dates.

Your program should print exactly:

output
Arrives: 2026-10-18 08:15:00.000Z
Trip: 9:35:00

Try it yourself before opening the solution.

Show solution
dart
void main() {
  var departs = DateTime.utc(2026, 10, 17, 22, 40);
  var trip = Duration(hours: 9, minutes: 35);
  var arrives = departs.add(trip);
  var minutes = (trip.inMinutes % 60).toString().padLeft(2, '0');
  var seconds = (trip.inSeconds % 60).toString().padLeft(2, '0');
  print('Arrives: $arrives');
  print('Trip: ${trip.inHours}:$minutes:$seconds');
}
output
Arrives: 2026-10-18 08:15:00.000Z
Trip: 9:35:00

How it works

  1. add moves the departure forward by exactly 9 h 35 min, crossing midnight.
  2. inHours gives 9; inMinutes % 60 gives 35; seconds are 00.

Practice Questions

Work through these in order — they run from beginner to application to challenge.

Beginner

  1. Create a Duration of 2 hours 45 minutes and print it.
  2. For Duration(seconds: 200), print inMinutes and inSeconds.
  3. Add Duration(minutes: 50) and Duration(minutes: 25) and print the result.

Application

  1. Print the date 100 days after DateTime.utc(2026, 10, 17).
  2. Print how many minutes passed between 08:15 and 13:40 on 17 October 2026 (UTC).
  3. Print how many days are left from 17 October 2026 until 1 January 2027 (UTC).
  4. Zayan was born on 17 October 2020. Using the ageOn function from section 7, print his age on 16 October 2026 and on 17 October 2026.

Challenge

  1. Using DateTime.utc(y, m, d + n), print the date 3 days after 30 December 2026.
  2. Ali ran 5 laps of Duration(minutes: 1, seconds: 48) each. Print the total as h:mm:ss.
  3. A parking garage charges 100 rupees per started hour. A car parked from 10:05 to 12:20 (UTC, same day). Print the duration in minutes and the fee (300).

Practice Answers

Question 1 — Solution

dart
void main() {
  print(Duration(hours: 2, minutes: 45));
}
output
2:45:00.000000

Question 2 — Solution

dart
void main() {
  var d = Duration(seconds: 200);
  print(d.inMinutes);
  print(d.inSeconds);
}
output
3
200

Question 3 — Solution

dart
void main() {
  print(Duration(minutes: 50) + Duration(minutes: 25));
}
output
1:15:00.000000

Question 4 — Solution

dart
void main() {
  print(DateTime.utc(2026, 10, 17).add(Duration(days: 100)));
}
output
2027-01-25 00:00:00.000Z

Question 5 — Solution

dart
void main() {
  var start = DateTime.utc(2026, 10, 17, 8, 15);
  var end = DateTime.utc(2026, 10, 17, 13, 40);
  print(end.difference(start).inMinutes);
}
output
325

Question 6 — Solution

dart
void main() {
  var today = DateTime.utc(2026, 10, 17);
  var newYear = DateTime.utc(2027, 1, 1);
  print(newYear.difference(today).inDays);
}
output
76

Question 7 — Solution

dart
int ageOn(DateTime birth, DateTime today) {
  var age = today.year - birth.year;
  var hadBirthday =
      today.month > birth.month ||
      (today.month == birth.month && today.day >= birth.day);
  if (!hadBirthday) age--;
  return age;
}

void main() {
  var zayan = DateTime.utc(2020, 10, 17);
  print(ageOn(zayan, DateTime.utc(2026, 10, 16)));
  print(ageOn(zayan, DateTime.utc(2026, 10, 17)));
}
output
5
6

Question 8 — Solution

dart
void main() {
  var day = DateTime.utc(2026, 12, 30);
  print(DateTime.utc(day.year, day.month, day.day + 3));
}
output
2027-01-02 00:00:00.000Z

Question 9 — Solution

dart
void main() {
  var total = Duration(minutes: 1, seconds: 48) * 5;
  var minutes = (total.inMinutes % 60).toString().padLeft(2, '0');
  var seconds = (total.inSeconds % 60).toString().padLeft(2, '0');
  print('${total.inHours}:$minutes:$seconds');
}
output
0:09:00

Question 10 — Solution

dart
void main() {
  var parked = DateTime.utc(2026, 10, 17, 10, 5);
  var left = DateTime.utc(2026, 10, 17, 12, 20);
  var minutes = left.difference(parked).inMinutes;
  var hours = (minutes + 59) ~/ 60;
  print('Parked: $minutes minutes');
  print('Fee: ${hours * 100}');
}
output
Parked: 135 minutes
Fee: 300

inHours would give 2 — truncated. Adding 59 minutes before ~/ 60 counts any started hour as a full one.


Quick Revision

  1. What is the difference between a DateTime and a Duration?
  2. What does Duration(minutes: 150).inHours return, and why?
  3. Which operator subtracts two durations? Which method moves a date?
  4. What does a.difference(b) return when a is earlier than b?
  5. Why is days ~/ 365 a poor way to calculate age?
  6. Why can add(Duration(days: 1)) land on the same date?
  7. Which two tools turn 62 minutes into the 02 in 1:02:05?

Key Takeaways

  • A Duration is a length of time; build it from named int parameters.
  • inDays, inHours, inMinutes, inSeconds give whole units and truncate.
  • Durations support +, -, *, comparisons, isNegative and abs().
  • add and subtract move a DateTime; later.difference(earlier) measures the gap.
  • Count days with UTC dates at midnight; calculate age from the calendar, not from days.
  • Duration(days: 1) is 24 hours — use DateTime(y, m, d + 1) for the next calendar day.
  • Format with inHours, % 60 and padLeft(2, '0').
  • Stopwatch.elapsed is a Duration too.

What's Next?

Lecture 112 — URI & Core Utilities. Dates and durations are only one part of dart:core. Apps also handle web addresses, query parameters and encoded text. Next we will build and take apart URLs with Uri and meet a few more everyday core utilities.


Video lecture

Subscribe
Placeholder video — the real recording isn't linked yet.