Flutter
DateTime
Formatting
Mobile Development
Dart

How to format DateTime in Flutter

Interview Questions practice on Codemia

Over 8,000 real interview questions from top companies, searchable by company and role.

Browse interview questions

Introduction

In Flutter, format DateTime objects using the intl package's DateFormat class. Dart's built-in DateTime has no formatting method beyond .toString() and .toIso8601String(). The intl package provides DateFormat with pattern-based formatting (like yyyy-MM-dd) and locale-aware output (month names, day names in different languages). For simple cases without adding a dependency, you can also build format strings manually from DateTime properties.

Setup: Add the intl Package

yaml
1# pubspec.yaml
2dependencies:
3  flutter:
4    sdk: flutter
5  intl: ^0.19.0
bash
flutter pub get
dart
import 'package:intl/intl.dart';

Basic Formatting with DateFormat

dart
1import 'package:intl/intl.dart';
2
3void main() {
4  final now = DateTime.now();
5
6  // Common formats
7  print(DateFormat('yyyy-MM-dd').format(now));       // 2025-09-23
8  print(DateFormat('dd/MM/yyyy').format(now));        // 23/09/2025
9  print(DateFormat('MM-dd-yyyy').format(now));        // 09-23-2025
10  print(DateFormat('yyyy-MM-dd HH:mm:ss').format(now)); // 2025-09-23 14:30:45
11  print(DateFormat('hh:mm a').format(now));           // 02:30 PM
12  print(DateFormat('EEEE, MMMM d, yyyy').format(now)); // Tuesday, September 23, 2025
13}

Pattern Reference

PatternMeaningExample
yyyy4-digit year2025
yy2-digit year25
MM2-digit month09
MMonth without padding9
MMMAbbreviated month nameSep
MMMMFull month nameSeptember
dd2-digit day23
dDay without padding3
EEEEFull weekday nameTuesday
EEEAbbreviated weekdayTue
HH24-hour hour (00-23)14
hh12-hour hour (01-12)02
mmMinutes30
ssSeconds45
aAM/PMPM
SFractional seconds3

Named Constructors (Predefined Formats)

dart
1import 'package:intl/intl.dart';
2
3final now = DateTime(2025, 9, 23, 14, 30, 45);
4
5print(DateFormat.yMd().format(now));        // 9/23/2025
6print(DateFormat.yMMMMd().format(now));      // September 23, 2025
7print(DateFormat.yMMMEd().format(now));      // Tue, Sep 23, 2025
8print(DateFormat.jm().format(now));          // 2:30 PM
9print(DateFormat.jms().format(now));         // 2:30:45 PM
10print(DateFormat.Hm().format(now));          // 14:30
11print(DateFormat.yMd().add_jm().format(now)); // 9/23/2025 2:30 PM

Named constructors are locale-aware and adjust output based on the user's locale.

Locale-Aware Formatting

dart
1import 'package:intl/intl.dart';
2import 'package:intl/date_symbol_data_local.dart';
3
4void main() async {
5  // Initialize locale data
6  await initializeDateFormatting('fr_FR', null);
7  await initializeDateFormatting('ja_JP', null);
8  await initializeDateFormatting('de_DE', null);
9
10  final date = DateTime(2025, 9, 23);
11
12  print(DateFormat.yMMMMd('en_US').format(date));  // September 23, 2025
13  print(DateFormat.yMMMMd('fr_FR').format(date));  // 23 septembre 2025
14  print(DateFormat.yMMMMd('ja_JP').format(date));  // 2025年9月23日
15  print(DateFormat.yMMMMd('de_DE').format(date));  // 23. September 2025
16  print(DateFormat.EEEE('fr_FR').format(date));    // mardi
17}

Call initializeDateFormatting before using locale-specific formats. Pass the locale string as the first argument to DateFormat or its named constructors.

Manual Formatting (Without intl)

dart
1String formatDate(DateTime date) {
2  final y = date.year.toString();
3  final m = date.month.toString().padLeft(2, '0');
4  final d = date.day.toString().padLeft(2, '0');
5  return '$y-$m-$d';
6}
7
8String formatTime(DateTime date) {
9  final h = date.hour.toString().padLeft(2, '0');
10  final m = date.minute.toString().padLeft(2, '0');
11  final s = date.second.toString().padLeft(2, '0');
12  return '$h:$m:$s';
13}
14
15void main() {
16  final now = DateTime.now();
17  print(formatDate(now));  // 2025-09-23
18  print(formatTime(now));  // 14:30:45
19}

Manual formatting avoids the intl dependency but does not support locale-aware month/day names.

Parsing Strings to DateTime

dart
1import 'package:intl/intl.dart';
2
3// Parse a formatted string back to DateTime
4final dateStr = '2025-09-23 14:30:00';
5final parsed = DateFormat('yyyy-MM-dd HH:mm:ss').parse(dateStr);
6print(parsed);  // 2025-09-23 14:30:00.000
7
8// Parse ISO 8601
9final iso = DateTime.parse('2025-09-23T14:30:00Z');
10print(iso);  // 2025-09-23 14:30:00.000Z
11
12// Parse with locale
13final frDate = DateFormat('d MMMM yyyy', 'fr_FR').parse('23 septembre 2025');
14print(frDate);  // 2025-09-23 00:00:00.000

Relative Time (Time Ago)

dart
1String timeAgo(DateTime date) {
2  final diff = DateTime.now().difference(date);
3
4  if (diff.inDays > 365) return '${(diff.inDays / 365).floor()} years ago';
5  if (diff.inDays > 30) return '${(diff.inDays / 30).floor()} months ago';
6  if (diff.inDays > 0) return '${diff.inDays} days ago';
7  if (diff.inHours > 0) return '${diff.inHours} hours ago';
8  if (diff.inMinutes > 0) return '${diff.inMinutes} minutes ago';
9  return 'just now';
10}
11
12// Usage
13print(timeAgo(DateTime.now().subtract(Duration(hours: 3))));  // 3 hours ago
14print(timeAgo(DateTime.now().subtract(Duration(days: 45))));   // 1 months ago

Flutter Widget Example

dart
1import 'package:flutter/material.dart';
2import 'package:intl/intl.dart';
3
4class DateDisplay extends StatelessWidget {
5  final DateTime date;
6  const DateDisplay({required this.date, super.key});
7
8  
9  Widget build(BuildContext context) {
10    return Column(
11      crossAxisAlignment: CrossAxisAlignment.start,
12      children: [
13        Text(
14          DateFormat.yMMMMEEEEd().format(date),
15          style: const TextStyle(fontSize: 18, fontWeight: FontWeight.bold),
16        ),
17        Text(
18          DateFormat.jm().format(date),
19          style: const TextStyle(fontSize: 14, color: Colors.grey),
20        ),
21      ],
22    );
23  }
24}

Common Pitfalls

  • Month vs minute confusion: MM is month, mm is minutes. DateFormat('yyyy-mm-dd') formats minutes in the month position. Always use uppercase MM for months.
  • Missing locale initialization: Using DateFormat.yMMMMd('fr_FR') without calling initializeDateFormatting('fr_FR') first throws a LocaleDataException. Initialize locales at app startup.
  • 24-hour vs 12-hour format: HH is 24-hour (00-23), hh is 12-hour (01-12). Using hh without a (AM/PM) makes afternoon times ambiguous.
  • UTC vs local time: DateTime.now() returns local time. DateTime.now().toUtc() returns UTC. Formatting does not convert between zones — it formats whatever DateTime it receives. Always be explicit about which zone your DateTime is in.
  • Parsing strict vs lenient: DateFormat.parse() is lenient by default. DateFormat('yyyy-MM-dd').parse('2025-13-45') may not throw. Use parseStrict() for validation: DateFormat('yyyy-MM-dd').parseStrict('2025-13-45') throws a FormatException.

Summary

  • Use the intl package's DateFormat for flexible DateTime formatting in Flutter
  • Pattern-based: DateFormat('yyyy-MM-dd HH:mm') for custom formats
  • Named constructors: DateFormat.yMd(), DateFormat.jm() for locale-aware defaults
  • Initialize locale data with initializeDateFormatting() before using non-English locales
  • Use DateTime.parse() or DateFormat.parse() to convert strings back to DateTime
  • For simple formats without dependencies, build strings manually from DateTime properties

Related reading
Free course
Beginner
7 lessons
2 hours
Tackling System Design Interview Problems

A short course that equips you with the skills to approach system design interviews methodically.

Start the free course
Track what you have practised

A free account saves your progress, solutions and study plan across every problem on Codemia.

Interview Questions practice on Codemia

Over 8,000 real interview questions from top companies, searchable by company and role.

Browse interview questions

All Rights Reserved.