Picking a date or a time is a small interaction with a few sharp edges: the pickers are async dialogs you await, they return null when cancelled, and time comes back as a TimeOfDay rather than a DateTime. Get those three facts right and the rest is easy. This guide covers showDatePicker with its date bounds, awaiting the result, showTimePicker and TimeOfDay, formatting with the intl package, the range picker, and the cancel-and-bounds pitfalls, with paste-ready code.

The Complete Flutter Guide: Build Android, iOS and Web apps
Go from scratch to building industry-standard apps with Riverpod, Firebase, animations, REST APIs, and more.
Enrol nowEvery snippet below is paste-ready against current stable Flutter. The pickers return a Future you await, just like returning a value from a screen — the same async pattern underneath.
We'll show a date picker, await its result, show a time picker, format the result with intl, and cover the range picker and the gotchas.
If you'd rather watch a booking form with date and time pickers built live, the channel covers these flows in real apps.
Show a date picker
showDatePicker opens the calendar dialog. Give it an initialDate, a firstDate, and a lastDate to bound the range, then await the result — a DateTime? that is null if the user cancels.
Future<void> _pickDate() async {
final picked = await showDatePicker(
context: context,
initialDate: DateTime.now(),
firstDate: DateTime(2020),
lastDate: DateTime(2030),
);
if (picked != null) {
setState(() => _date = picked);
}
}
The firstDate and lastDate set the selectable window — handy for a date of birth (no future dates) or a booking (no past dates). Always guard the null cancel case before using the result.
Mind the async gap
Because you await the dialog, the widget might be gone by the time it returns. If you call setState or use the context after the await, guard with a mounted check first.
final picked = await showDatePicker(/* ... */);
if (!mounted) return; // widget may have been disposed
if (picked != null) setState(() => _date = picked);
This is the standard "don't use context across an async gap" rule, and it applies to any dialog you await.

Build booking and scheduling apps
The Complete Flutter Guide covers pickers, forms, and async flows inside real, shipped apps.
Enrol nowShow a time picker
showTimePicker opens the clock dialog and returns a TimeOfDay? — not a DateTime. A TimeOfDay holds just an hour and minute.
final picked = await showTimePicker(
context: context,
initialTime: TimeOfDay.now(),
);
if (picked != null) {
setState(() => _time = picked);
}
To display it, use picked.format(context), which respects the device's 12 or 24 hour setting. If you need a full timestamp, combine the date and time yourself: DateTime(d.year, d.month, d.day, t.hour, t.minute).
Format with intl
A raw DateTime prints as an ISO string, which is rarely what you want to show. The intl package's DateFormat turns it into readable, localised text.
import 'package:intl/intl.dart';
final label = DateFormat('d MMM yyyy').format(_date); // 20 Jun 2026
Add intl to pubspec.yaml and you get patterns for dates, times, ordinals, and locales without hand-building strings. The same package powers full app translation, covered in the internationalisation guide.
The range picker
For a start-and-end date — a holiday, a report window — showDateRangePicker returns a DateTimeRange? with start and end. It takes the same firstDate and lastDate bounds and is awaited the same way, so the cancel and bounds rules carry straight over.
Common mistakes
- Not handling the null cancel. The pickers return
nullwhen dismissed; always check. - initialDate outside the bounds. It must sit within
firstDate–lastDateor it throws. - Using context across the async gap. Add an
if (!mounted) return;after the await. - Treating TimeOfDay as DateTime. It has only hour and minute; combine with a date for a timestamp.
- Building date strings by hand. Use
intl'sDateFormatfor readable, localised output.
Frequently asked questions
How do I show a date picker in Flutter?
Call showDatePicker with initialDate, firstDate, and lastDate, then await the DateTime? and handle the null cancel.
How do I show a time picker in Flutter?
Call showTimePicker with initialTime: TimeOfDay.now(); it returns a TimeOfDay?. Display it with picked.format(context).
How do I format a DateTime in Flutter?
Use the intl package's DateFormat, e.g. DateFormat('d MMM yyyy').format(date) for "20 Jun 2026".
Why does my Flutter date picker return null?
The user cancelled the dialog — the result is nullable by design. Also check that initialDate sits within the firstDate–lastDate bounds.
Further reads
Keep going with the tutorials that pair with this guide:
- Flutter Development Guide 2026 — the full Flutter hub.
- Flutter TextField and TextEditingController — show the chosen date in a field.
- Flutter Pass Data Between Screens — the same await-a-result pattern.
- Flutter DropdownButton — another selection input for your forms.
- Flutter Material Widgets Catalogue — the full input and dialog family.
Sources: Flutter documentation — showDatePicker, showTimePicker, TimeOfDay, showDateRangePicker, DateTimeRange, and the intl package DateFormat reference (docs.flutter.dev, pub.dev/packages/intl). Verified against current stable Flutter.