On this page23 sections
- Prerequisites
- Connection With Previous Lectures
- Learning Objectives
- 1. What Is a DateTime?
- 2. Creating a Fixed Date
- 3. The Current Moment — DateTime.now()
- 4. Reading the Parts
- 5. Month and Day Overflow
- 6. Comparing Dates
- 7. Local Time and UTC
- 8. Dates as Text — toIso8601String
- 9. Text Back to a Date — parse and tryParse
- 10. Formatting by Hand
- 11. A Real-World Example
- Code Examples
- Common Beginner Mistakes
- Best Practices
- Mini Challenge
- Practice Questions
- Practice Answers
- Quick Revision
- Key Takeaways
- What's Next?
Lecture 110 — Date & Time
| Category | 18 — Files, JSON & Core Utilities |
| Lecture | 110 of 140 |
| Estimated video length | 9 min |
| Target | Dart 3.12.2 |
| Level | Intermediate |
A date stored as the text
'2026-10-17'can't tell you its weekday or which of two days comes first. ADateTimeis 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:
padLefton strings (Lecture 008) andint.tryParsereturningnull(Lecture 010)compareToand sorting a list with a comparator (Lecture 045)- catching a
FormatExceptionwithtry/catch(Lecture 084) jsonEncodeandjsonDecode(Lectures 108–109)
Connection With Previous Lectures
In Lecture 109 we turned objects into JSON. Try that with a date and it fails:
import 'dart:convert';
void main() {
var order = {'item': 'Notebook', 'date': DateTime(2026, 10, 17)};
print(jsonEncode(order));
}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
DateTimeand get the current one withDateTime.now() - Read
year,month,day,hour,minuteandweekday - Use month and day overflow on purpose
- Compare dates with
isBefore,isAfter,compareToand== - Explain the difference between local time and UTC
- Convert dates to and from ISO 8601 text with
toIso8601String,parseandtryParse - 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:
void main() {
var exam = DateTime(2026, 10, 17, 9, 30);
var holiday = DateTime(2026, 12, 25);
print(exam);
print(holiday);
}2026-10-17 09:30:00.000
2026-12-25 00:00:00.000Months 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:
void main() {
print(DateTime.now());
}2026-10-17 14:24:18.400885Your 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:
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);
}2026
10
17
9
30
6
trueweekday 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:
void main() {
print(DateTime(2024, 13, 1));
print(DateTime(2026, 2, 30));
print(DateTime(2026, 3, 0));
}2025-01-01 00:00:00.000
2026-03-02 00:00:00.000
2026-02-28 00:00:00.000Month 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:
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);
}true
false
true
-1
2026-01-01 00:00:00.000compareTo 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:
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);
}2026-10-17 04:30:00.000Z
true
false
true
falsetoLocal() 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:
void main() {
print(DateTime(2026, 10, 17, 9, 30).toIso8601String());
print(DateTime.utc(2026, 10, 17, 9, 30).toIso8601String());
}2026-10-17T09:30:00.000
2026-10-17T09:30:00.000ZISO 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:
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);
}
}2026-10-17 00:00:00.000
true
null
Invalid date formatJust 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:
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)}');
}05/03/2026 at 09:05For 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":
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()}');
}Reader: Sara
Borrowed: 25/09/2026
Due: 09/10/2026
Status: late
Saved as: 2026-10-09T00:00:00.000Day 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
void main() {
var birthday = DateTime(2020, 4, 12);
print(birthday);
print('Zayan was born in ${birthday.year}.');
}2020-04-12 00:00:00.000
Zayan was born in 2020.Example 2 — Weekday Name
void main() {
var names = ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'];
var holiday = DateTime(2026, 12, 25);
print(names[holiday.weekday - 1]);
}Friweekday starts at 1, list indexes at 0 — hence - 1.
Example 3 — Days in a Month
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));
}28
29
31For December, month + 1 is 13, which overflows into January — and day 0 steps back to
December 31st.
Example 4 — Which Comes First?
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.');
}Sara travels first.Example 5 — ISO Round Trip
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);
}2026-10-17T09:30:00.000Z
trueBoth are UTC and the same moment, so == is true.
Example 6 — Safe Parsing
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}');
}
}2026-10-17: day 17
tomorrow: invalid
2026-12-25T18:00:00: day 25Example 7 — Ali's Exam Timetable
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');
}
}2 Nov: Math
5 Nov: English
9 Nov: ScienceExample 8 — Delivery Date
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}');
}Total: 1500
Delivery: 02/11/2026October 33rd overflows to November 2nd.
Example 9 — Bank Deposits This Month
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');
}October deposits: 1500"Not before the 1st" includes the 1st itself.
Example 10 — Hottest Reading
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');
}Hottest: 38.0 at 14:30Common Beginner Mistakes
1. Comparing with < or >
void main() {
var exam = DateTime(2026, 10, 17);
var holiday = DateTime(2026, 12, 25);
// print(exam < holiday); // ✗
print(exam.isBefore(holiday));
}Error: The operator '<' isn't defined for the type 'DateTime'.2. Trying to change a part
void main() {
var exam = DateTime(2026, 10, 17);
// exam.year = 2027; // ✗
exam = DateTime(2027, exam.month, exam.day);
print(exam);
}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,isAfterandisAtSameMomentAs; sort withcompareTo. - Store and send dates as UTC ISO 8601 text (
toUtc().toIso8601String()). - Use
tryParsefor text you don't control. - Write small
formatDatehelpers instead of repeatingpadLefteverywhere. - Reach for the
intlpackage 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.
Sports day: 14/11/2026
Weekend: trueTry it yourself before opening the solution.
Show solution
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');
}Sports day: 14/11/2026
Weekend: trueNovember 14th, 2026 is a Saturday, so weekday is 6.
Practice Questions
Beginner
- Create a
DateTimefor 1 January 2027 at 08:15 and print it. - For
DateTime(2026, 7, 4), print the year, month and day on one line as2026 7 4. - Print what
DateTime(2026, 12, 32)becomes.
Application
- Print
trueorfalse: isDateTime(2026, 5, 1)afterDateTime(2026, 4, 30)? - Convert
DateTime.utc(2026, 8, 15, 6, 0)to ISO 8601 text and print it. - Use
tryParseon'2026-08-15'and'15-08-2026'and print both results. - Write
String formatTime(DateTime d)that returnsHH:mm, and print it forDateTime(2026, 1, 1, 7, 5).
Challenge
- Sort
['2026-03-10', '2026-01-20', '2026-02-05']as dates and print the earliest one asdd/mm/yyyy. - Using overflow, print how many days February 2028 has.
- Sara's subscription started on
DateTime(2026, 11, 20)and lasts 30 days. Print the end date withformatDateand whether it ends beforeDateTime(2027, 1, 1).
Practice Answers
Question 1 — Solution
void main() {
print(DateTime(2027, 1, 1, 8, 15));
}2027-01-01 08:15:00.000Question 2 — Solution
void main() {
var d = DateTime(2026, 7, 4);
print('${d.year} ${d.month} ${d.day}');
}2026 7 4Question 3 — Solution
void main() {
print(DateTime(2026, 12, 32));
}2027-01-01 00:00:00.000Question 4 — Solution
void main() {
print(DateTime(2026, 5, 1).isAfter(DateTime(2026, 4, 30)));
}trueQuestion 5 — Solution
void main() {
print(DateTime.utc(2026, 8, 15, 6, 0).toIso8601String());
}2026-08-15T06:00:00.000ZQuestion 6 — Solution
void main() {
print(DateTime.tryParse('2026-08-15'));
print(DateTime.tryParse('15-08-2026'));
}2026-08-15 00:00:00.000
nullQuestion 7 — Solution
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)));
}07:05Question 8 — Solution
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}');
}20/01/2026Question 9 — Solution
void main() {
print(DateTime(2028, 3, 0).day);
}292028 is a leap year.
Question 10 — Solution
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)));
}Ends: 20/12/2026
trueQuick Revision
- Which number is January in
DateTime? Whichweekdaynumber is Sunday? - Why should examples avoid
DateTime.now()? - What does
DateTime(2026, 3, 0)give? - Which methods compare two dates?
- When is
==falseeven though two dates are the same moment? - What does the
Zat the end of a date mean? - What is the difference between
parseandtryParse?
Key Takeaways
- A
DateTimeis 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,
weekdayruns 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,toUtcandtoLocalswitch clocks;isUtctells which one you have.toIso8601String,parseandtryParsemove dates in and out of text and JSON.- Format for people with
padLeft, or theintlpackage 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.