Menu
CoddyTech

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 November

E 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 icon

Challenge

Easy

The 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),
    );
  }
}
quiz iconTest yourself

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