Flutter Date and Time Pickers: showDatePicker and showTimePicker

Coding Liquids blog cover featuring Sagnik Bhattacharya for the Flutter date and time pickers guide, with a calendar date picker dialog, a clock time picker, and a formatted DateTime result.
Coding Liquids blog cover featuring Sagnik Bhattacharya for the Flutter date and time pickers guide.

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 course thumbnail

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 now

Every 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.

Follow me on Instagram@sagnikteaches

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.

Connect on LinkedInSagnik Bhattacharya

If you'd rather watch a booking form with date and time pickers built live, the channel covers these flows in real apps.

Subscribe on YouTube@codingliquids

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.

The Complete Flutter Guide course thumbnail

Build booking and scheduling apps

The Complete Flutter Guide covers pickers, forms, and async flows inside real, shipped apps.

Enrol now

Show 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 null when dismissed; always check.
  • initialDate outside the bounds. It must sit within firstDatelastDate or 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's DateFormat for 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 firstDatelastDate bounds.

Further reads

Keep going with the tutorials that pair with this guide:

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.