Watch the video (9 min)
On this page23 sections
  1. Prerequisites
  2. Connection With Previous Lectures
  3. Learning Objectives
  4. 1. What Is a DateTime?
  5. 2. Creating a Fixed Date
  6. 3. The Current Moment — DateTime.now()
  7. 4. Reading the Parts
  8. 5. Month and Day Overflow
  9. 6. Comparing Dates
  10. 7. Local Time and UTC
  11. 8. Dates as Text — toIso8601String
  12. 9. Text Back to a Date — parse and tryParse
  13. 10. Formatting by Hand
  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 110 — Date & Time

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

A date stored as the text '2026-10-17' can't tell you its weekday or which of two days comes first. A DateTime is a moment in time, so Dart can read, compare and convert 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–109:

  • padLeft on strings (Lecture 008) and int.tryParse returning null (Lecture 010)
  • compareTo and sorting a list with a comparator (Lecture 045)
  • catching a FormatException with try/catch (Lecture 084)
  • jsonEncode and jsonDecode (Lectures 108–109)

Connection With Previous Lectures

In Lecture 109 we turned objects into JSON. Try that with a date and it fails:

dart
import 'dart:convert';

void main() {
  var order = {'item': 'Notebook', 'date': DateTime(2026, 10, 17)};
  print(jsonEncode(order));
}
output
Unhandled exception:
Converting object to an encodable object failed: Instance of 'DateTime'

JSON has no date type. So dates travel as text — and text is useless for asking "is this order late?" or "what weekday is it?". We need a real date object, and a reliable way to turn it into text and back.


Learning Objectives

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

  • Create a fixed DateTime and get the current one with DateTime.now()
  • Read year, month, day, hour, minute and weekday
  • Use month and day overflow on purpose
  • Compare dates with isBefore, isAfter, compareTo and ==
  • Explain the difference between local time and UTC
  • Convert dates to and from ISO 8601 text with toIso8601String, parse and tryParse
  • Format a date by hand with padLeft

1. What Is a DateTime?

A DateTime is one exact moment: a date plus a time of day, down to the microsecond.

Analogy — think of the stamp a library puts in a borrowed book. It records one moment, and anyone can read the day, month and year from it, or check whether it is before today.

DateTime lives in dart:core, so no import is needed.


2. Creating a Fixed Date

Pass the year, month and day, then optionally hour, minute and second:

dart
void main() {
  var exam = DateTime(2026, 10, 17, 9, 30);
  var holiday = DateTime(2026, 12, 25);
  print(exam);
  print(holiday);
}
output
2026-10-17 09:30:00.000
2026-12-25 00:00:00.000

Months count from 1 (January) to 12. Anything you leave out is zero, so holiday starts at midnight.


3. The Current Moment — DateTime.now()

DateTime.now() reads your computer's clock:

dart
void main() {
  print(DateTime.now());
}
output
2026-10-17 14:24:18.400885

Your output will be different — it is the moment you run it. That is why every other example in this lecture uses fixed dates: their output never changes.


4. Reading the Parts

Each part of a date is a property:

dart
void main() {
  var exam = DateTime(2026, 10, 17, 9, 30);
  print(exam.year);
  print(exam.month);
  print(exam.day);
  print(exam.hour);
  print(exam.minute);
  print(exam.weekday);
  print(exam.weekday == DateTime.saturday);
}
output
2026
10
17
9
30
6
true

weekday runs from 1 (Monday) to 7 (Sunday). The constants DateTime.monday … DateTime.sunday save you from remembering the numbers. These properties are read-only — a DateTime never changes after it is created.


5. Month and Day Overflow

Give a month or day that is too big, and Dart rolls it forward into the next month or year:

dart
void main() {
  print(DateTime(2024, 13, 1));
  print(DateTime(2026, 2, 30));
  print(DateTime(2026, 3, 0));
}
output
2025-01-01 00:00:00.000
2026-03-02 00:00:00.000
2026-02-28 00:00:00.000

Month 13 of 2024 is January 2025. February 2026 has 28 days, so the 30th is March 2nd. Day 0 means "the day before the 1st" — the last day of the previous month. That gives a neat trick: DateTime(year, month + 1, 0).day is the number of days in month.


6. Comparing Dates

A DateTime doesn't support < and >. It has methods with clear names instead:

dart
void main() {
  var exam = DateTime(2026, 10, 17);
  var holiday = DateTime(2026, 12, 25);
  print(exam.isBefore(holiday));
  print(exam.isAfter(holiday));
  print(exam == DateTime(2026, 10, 17));
  print(exam.compareTo(holiday));

  var dates = [holiday, exam, DateTime(2026, 1, 1)];
  dates.sort((a, b) => a.compareTo(b));
  print(dates.first);
}
output
true
false
true
-1
2026-01-01 00:00:00.000

compareTo works exactly as in Lecture 045 — negative means "comes first" — so dates sort oldest to newest.


7. Local Time and UTC

So far every date has been local: in your computer's time zone. UTC is the single world reference time that time zones are measured from. A UTC date prints with a Z:

dart
void main() {
  var meeting = DateTime.utc(2026, 10, 17, 4, 30);
  print(meeting);
  print(meeting.isUtc);

  var local = meeting.toLocal();
  print(local.isUtc);
  print(meeting.isAtSameMomentAs(local));
  print(meeting == local);
}
output
2026-10-17 04:30:00.000Z
true
false
true
false

toLocal() and toUtc() show the same moment on a different clock. isAtSameMomentAs confirms that. But == is stricter: it is true only for the same moment and the same kind (both UTC or both local).

Printing local gives a time that depends on your time zone. In Pakistan (UTC+5) it prints 2026-10-17 09:30:00.000; in London you would see a different hour. Store and send dates in UTC, and convert to local only to show them to a person.


8. Dates as Text — toIso8601String

ISO 8601 is the international text format for dates: year, month, day, then T and the time. It is the safe way to put a date into JSON:

dart
void main() {
  print(DateTime(2026, 10, 17, 9, 30).toIso8601String());
  print(DateTime.utc(2026, 10, 17, 9, 30).toIso8601String());
}
output
2026-10-17T09:30:00.000
2026-10-17T09:30:00.000Z

ISO text sorts correctly even as plain strings, because the biggest unit comes first.


9. Text Back to a Date — parse and tryParse

DateTime.parse reads ISO 8601 text. A trailing Z makes a UTC date:

dart
void main() {
  print(DateTime.parse('2026-10-17'));
  var start = DateTime.parse('2026-10-17T09:30:00Z');
  print(start.isUtc);
  print(DateTime.tryParse('17/10/2026'));

  try {
    DateTime.parse('17/10/2026');
  } on FormatException catch (e) {
    print(e.message);
  }
}
output
2026-10-17 00:00:00.000
true
null
Invalid date format

Just like int.parse and int.tryParse: parse throws a FormatException on bad text, and tryParse returns null. '17/10/2026' is not ISO 8601, so both reject it.


10. Formatting by Hand

toString() is meant for programmers. For people, build the text yourself, using padLeft to keep two digits:

dart
String formatDate(DateTime d) {
  var day = d.day.toString().padLeft(2, '0');
  var month = d.month.toString().padLeft(2, '0');
  return '$day/$month/${d.year}';
}

String formatTime(DateTime d) {
  var hour = d.hour.toString().padLeft(2, '0');
  var minute = d.minute.toString().padLeft(2, '0');
  return '$hour:$minute';
}

void main() {
  var exam = DateTime(2026, 3, 5, 9, 5);
  print('${formatDate(exam)} at ${formatTime(exam)}');
}
output
05/03/2026 at 09:05

For month names, languages and many formats, real projects use the intl package. We will see how to add packages like it in Lectures 103–105; here, padLeft is all we need.


11. A Real-World Example

Sara borrowed a library book. The borrow date arrives from JSON as ISO text, the loan lasts 14 days, and we check it against a fixed "today":

dart
import 'dart:convert';

String formatDate(DateTime d) {
  var day = d.day.toString().padLeft(2, '0');
  var month = d.month.toString().padLeft(2, '0');
  return '$day/$month/${d.year}';
}

void main() {
  var data = jsonDecode('{"reader": "Sara", "borrowed": "2026-09-25"}');
  var borrowed = DateTime.parse(data['borrowed']);
  var due = DateTime(borrowed.year, borrowed.month, borrowed.day + 14);
  var today = DateTime(2026, 10, 17);

  print('Reader: ${data['reader']}');
  print('Borrowed: ${formatDate(borrowed)}');
  print('Due: ${formatDate(due)}');
  print(today.isAfter(due) ? 'Status: late' : 'Status: on time');
  print('Saved as: ${due.toIso8601String()}');
}
output
Reader: Sara
Borrowed: 25/09/2026
Due: 09/10/2026
Status: late
Saved as: 2026-10-09T00:00:00.000

Day 25 + 14 = 39 overflows September's 30 days into October 9th. Parsing, overflow, comparing, formatting and ISO output all work together.


Code Examples

Example 1 — A Birthday

dart
void main() {
  var birthday = DateTime(2020, 4, 12);
  print(birthday);
  print('Zayan was born in ${birthday.year}.');
}
output
2020-04-12 00:00:00.000
Zayan was born in 2020.

Example 2 — Weekday Name

dart
void main() {
  var names = ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'];
  var holiday = DateTime(2026, 12, 25);
  print(names[holiday.weekday - 1]);
}
output
Fri

weekday starts at 1, list indexes at 0 — hence - 1.

Example 3 — Days in a Month

dart
int daysInMonth(int year, int month) => DateTime(year, month + 1, 0).day;

void main() {
  print(daysInMonth(2026, 2));
  print(daysInMonth(2024, 2));
  print(daysInMonth(2026, 12));
}
output
28
29
31

For December, month + 1 is 13, which overflows into January — and day 0 steps back to December 31st.

Example 4 — Which Comes First?

dart
void main() {
  var aliTrip = DateTime(2026, 11, 3);
  var saraTrip = DateTime(2026, 11, 1);
  var first = aliTrip.isBefore(saraTrip) ? 'Ali' : 'Sara';
  print('$first travels first.');
}
output
Sara travels first.

Example 5 — ISO Round Trip

dart
void main() {
  var original = DateTime.utc(2026, 10, 17, 9, 30);
  var text = original.toIso8601String();
  var back = DateTime.parse(text);
  print(text);
  print(back == original);
}
output
2026-10-17T09:30:00.000Z
true

Both are UTC and the same moment, so == is true.

Example 6 — Safe Parsing

dart
void main() {
  var inputs = ['2026-10-17', 'tomorrow', '2026-12-25T18:00:00'];
  for (var text in inputs) {
    var date = DateTime.tryParse(text);
    print(date == null ? '$text: invalid' : '$text: day ${date.day}');
  }
}
output
2026-10-17: day 17
tomorrow: invalid
2026-12-25T18:00:00: day 25

Example 7 — Ali's Exam Timetable

dart
void main() {
  var exams = {
    'Science': DateTime(2026, 11, 9),
    'Math': DateTime(2026, 11, 2),
    'English': DateTime(2026, 11, 5),
  };
  var subjects = exams.keys.toList();
  subjects.sort((a, b) => exams[a]!.compareTo(exams[b]!));
  for (var subject in subjects) {
    print('${exams[subject]!.day} Nov: $subject');
  }
}
output
2 Nov: Math
5 Nov: English
9 Nov: Science

Example 8 — Delivery Date

dart
void main() {
  var ordered = DateTime(2026, 10, 30);
  var delivery = DateTime(ordered.year, ordered.month, ordered.day + 3);
  var day = delivery.day.toString().padLeft(2, '0');
  var month = delivery.month.toString().padLeft(2, '0');
  print('Total: 1500');
  print('Delivery: $day/$month/${delivery.year}');
}
output
Total: 1500
Delivery: 02/11/2026

October 33rd overflows to November 2nd.

Example 9 — Bank Deposits This Month

dart
void main() {
  var deposits = {'2026-09-28': 500, '2026-10-02': 1200, '2026-10-15': 300};
  var monthStart = DateTime(2026, 10, 1);
  var total = 0;
  deposits.forEach((date, amount) {
    if (!DateTime.parse(date).isBefore(monthStart)) total += amount;
  });
  print('October deposits: $total');
}
output
October deposits: 1500

"Not before the 1st" includes the 1st itself.

Example 10 — Hottest Reading

dart
void main() {
  var readings = {
    DateTime(2026, 6, 1, 9, 0): 31.5,
    DateTime(2026, 6, 1, 14, 30): 38.0,
    DateTime(2026, 6, 1, 18, 5): 34.2,
  };
  var hottest = readings.keys.first;
  for (var time in readings.keys) {
    if (readings[time]! > readings[hottest]!) hottest = time;
  }
  var hour = hottest.hour.toString().padLeft(2, '0');
  var minute = hottest.minute.toString().padLeft(2, '0');
  print('Hottest: ${readings[hottest]} at $hour:$minute');
}
output
Hottest: 38.0 at 14:30

Common Beginner Mistakes

1. Comparing with < or >

dart
void main() {
  var exam = DateTime(2026, 10, 17);
  var holiday = DateTime(2026, 12, 25);
  // print(exam < holiday); // ✗
  print(exam.isBefore(holiday));
}
output
Error: The operator '<' isn't defined for the type 'DateTime'.

2. Trying to change a part

dart
void main() {
  var exam = DateTime(2026, 10, 17);
  // exam.year = 2027; // ✗
  exam = DateTime(2027, exam.month, exam.day);
  print(exam);
}
output
Error: The setter 'year' isn't defined for the type 'DateTime'.

A DateTime can't change. Create a new one instead.

3. Counting months from 0

DateTime(2026, 0, 1) is not January — it overflows backwards to 2025-12-01. January is 1.

4. Parsing a non-ISO string

DateTime.parse('17/10/2026') and even DateTime.parse('2026-1-5') throw FormatException: Invalid date format. ISO 8601 needs two-digit months and days: '2026-01-05'. Use tryParse when the text comes from a user.

5. Trusting tryParse to check the calendar

DateTime.tryParse('2026-02-30') returns 2026-03-02, not null — overflow applies to parsing too. The format is checked, not whether the day exists.

6. Comparing a UTC date with a local one using ==

== is false for a UTC date and its toLocal() copy. Use isAtSameMomentAs to ask "same moment?".


Best Practices

  • Use fixed dates in examples and tests; keep DateTime.now() for the real clock.
  • Compare with isBefore, isAfter and isAtSameMomentAs; sort with compareTo.
  • Store and send dates as UTC ISO 8601 text (toUtc().toIso8601String()).
  • Use tryParse for text you don't control.
  • Write small formatDate helpers instead of repeating padLeft everywhere.
  • Reach for the intl package when you need month names or many formats.

Mini Challenge

Zayan's school sports day is on '2026-11-14' (ISO text). Parse it, then print the date as dd/mm/yyyy and whether it falls on a weekend.

output
Sports day: 14/11/2026
Weekend: true

Try it yourself before opening the solution.

Show solution
dart
void main() {
  var day = DateTime.parse('2026-11-14');
  var dd = day.day.toString().padLeft(2, '0');
  var mm = day.month.toString().padLeft(2, '0');
  var weekend =
      day.weekday == DateTime.saturday || day.weekday == DateTime.sunday;
  print('Sports day: $dd/$mm/${day.year}');
  print('Weekend: $weekend');
}
output
Sports day: 14/11/2026
Weekend: true

November 14th, 2026 is a Saturday, so weekday is 6.


Practice Questions

Beginner

  1. Create a DateTime for 1 January 2027 at 08:15 and print it.
  2. For DateTime(2026, 7, 4), print the year, month and day on one line as 2026 7 4.
  3. Print what DateTime(2026, 12, 32) becomes.

Application

  1. Print true or false: is DateTime(2026, 5, 1) after DateTime(2026, 4, 30)?
  2. Convert DateTime.utc(2026, 8, 15, 6, 0) to ISO 8601 text and print it.
  3. Use tryParse on '2026-08-15' and '15-08-2026' and print both results.
  4. Write String formatTime(DateTime d) that returns HH:mm, and print it for DateTime(2026, 1, 1, 7, 5).

Challenge

  1. Sort ['2026-03-10', '2026-01-20', '2026-02-05'] as dates and print the earliest one as dd/mm/yyyy.
  2. Using overflow, print how many days February 2028 has.
  3. Sara's subscription started on DateTime(2026, 11, 20) and lasts 30 days. Print the end date with formatDate and whether it ends before DateTime(2027, 1, 1).

Practice Answers

Question 1 — Solution

dart
void main() {
  print(DateTime(2027, 1, 1, 8, 15));
}
output
2027-01-01 08:15:00.000

Question 2 — Solution

dart
void main() {
  var d = DateTime(2026, 7, 4);
  print('${d.year} ${d.month} ${d.day}');
}
output
2026 7 4

Question 3 — Solution

dart
void main() {
  print(DateTime(2026, 12, 32));
}
output
2027-01-01 00:00:00.000

Question 4 — Solution

dart
void main() {
  print(DateTime(2026, 5, 1).isAfter(DateTime(2026, 4, 30)));
}
output
true

Question 5 — Solution

dart
void main() {
  print(DateTime.utc(2026, 8, 15, 6, 0).toIso8601String());
}
output
2026-08-15T06:00:00.000Z

Question 6 — Solution

dart
void main() {
  print(DateTime.tryParse('2026-08-15'));
  print(DateTime.tryParse('15-08-2026'));
}
output
2026-08-15 00:00:00.000
null

Question 7 — Solution

dart
String formatTime(DateTime d) {
  var hour = d.hour.toString().padLeft(2, '0');
  var minute = d.minute.toString().padLeft(2, '0');
  return '$hour:$minute';
}

void main() {
  print(formatTime(DateTime(2026, 1, 1, 7, 5)));
}
output
07:05

Question 8 — Solution

dart
void main() {
  var dates = [
    '2026-03-10',
    '2026-01-20',
    '2026-02-05',
  ].map(DateTime.parse).toList();
  dates.sort((a, b) => a.compareTo(b));
  var first = dates.first;
  var dd = first.day.toString().padLeft(2, '0');
  var mm = first.month.toString().padLeft(2, '0');
  print('$dd/$mm/${first.year}');
}
output
20/01/2026

Question 9 — Solution

dart
void main() {
  print(DateTime(2028, 3, 0).day);
}
output
29

2028 is a leap year.

Question 10 — Solution

dart
String formatDate(DateTime d) {
  var day = d.day.toString().padLeft(2, '0');
  var month = d.month.toString().padLeft(2, '0');
  return '$day/$month/${d.year}';
}

void main() {
  var start = DateTime(2026, 11, 20);
  var end = DateTime(start.year, start.month, start.day + 30);
  print('Ends: ${formatDate(end)}');
  print(end.isBefore(DateTime(2027, 1, 1)));
}
output
Ends: 20/12/2026
true

Quick Revision

  1. Which number is January in DateTime? Which weekday number is Sunday?
  2. Why should examples avoid DateTime.now()?
  3. What does DateTime(2026, 3, 0) give?
  4. Which methods compare two dates?
  5. When is == false even though two dates are the same moment?
  6. What does the Z at the end of a date mean?
  7. What is the difference between parse and tryParse?

Key Takeaways

  • A DateTime is one moment; DateTime(y, m, d, h, min) creates a fixed one.
  • DateTime.now() changes every run — use fixed dates in examples and tests.
  • Months run 1–12, weekday runs 1 (Monday) to 7 (Sunday), and parts are read-only.
  • Too-big or zero months and days overflow into neighbouring months.
  • Compare with isBefore, isAfter, compareTo; == also needs the same UTC/local kind.
  • DateTime.utc, toUtc and toLocal switch clocks; isUtc tells which one you have.
  • toIso8601String, parse and tryParse move dates in and out of text and JSON.
  • Format for people with padLeft, or the intl package for richer formats.

What's Next?

Lecture 111 — Duration & Time Calculations. We added 14 days by overflowing the day field — but how many days are left until a deadline, or how long did a task take in hours and minutes? Next we will meet Duration, and add, subtract and measure the gap between dates properly.


Video lecture

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