Dates With DateFormat
Part of the Data and the Network section of Coddy's Flutter journey. Lesson 20 of 27.
Servers send dates as text in one fixed shape, like "2026-11-03T18:30:00": year, month, day, then the time. DateTime.parse turns that text into a DateTime. Printed as it is, a DateTime looks like 2026-11-03 18:30:00.000, which nobody wants to read on a phone.
The intl package formats dates for people. DateFormat takes a pattern, letters that stand for the parts of a date:
import 'package:intl/intl.dart';
final day = DateTime.parse('2026-11-03T18:30:00');
DateFormat('EEE, MMM d').format(day) // Tue, Nov 3
DateFormat('EEEE d MMMM').format(day) // Tuesday 3 NovemberE is the weekday, M the month and d the day of the month. More letters give a longer form: EEE is Tue, EEEE is Tuesday, MMM is Nov, MMMM is November, MM is 11. Capitals matter: D is the day of the year. Commas and spaces in the pattern are kept as they are.
Challenge
EasyThe events list shows raw dates. Format each one with DateFormat, so the first event reads Tue, Nov 3. The intl import is already there.
Try it yourself
import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:intl/intl.dart';
import 'api.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return const MaterialApp(
debugShowCheckedModeBanner: false,
home: EventsScreen(),
);
}
}
class EventsScreen extends StatefulWidget {
const EventsScreen({super.key});
@override
State<EventsScreen> createState() => _EventsScreenState();
}
class _EventsScreenState extends State<EventsScreen> {
late Future<List<Event>> _events;
@override
void initState() {
super.initState();
_events = loadEvents();
}
Future<List<Event>> loadEvents() async {
final body = await fetch('/events');
final items = jsonDecode(body) as List<dynamic>;
return items.map((item) => Event.fromJson(item as Map<String, dynamic>)).toList();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('Events')),
body: FutureBuilder<List<Event>>(
future: _events,
builder: (context, snapshot) {
if (snapshot.hasError) {
return Center(child: Text('Could not load: ${snapshot.error}'));
}
if (snapshot.hasData) {
final events = snapshot.data!;
return ListView.builder(
itemCount: events.length,
itemBuilder: (context, index) {
final event = events[index];
return ListTile(
title: Text(event.title),
subtitle: Text('${event.start}'),
);
},
);
}
return const Center(child: CircularProgressIndicator());
},
),
);
}
}
class Event {
Event({required this.title, required this.start});
final String title;
final DateTime start;
factory Event.fromJson(Map<String, dynamic> json) {
return Event(
title: json['title'] as String,
start: DateTime.parse(json['start'] as String),
);
}
}
This lesson includes a short quiz. Start the lesson to answer it and track your progress.
All lessons in Data and the Network
Practice on your own: Online Flutter compiler