Menu
CoddyTech

Ngày tháng với DateFormat

Thuộc phần Dữ liệu và mạng trong hành trình Flutter của Coddy. Bài học 20 trên 27.

Máy chủ gửi ngày tháng dưới dạng văn bản theo một khuôn dạng cố định, chẳng hạn như "2026-11-03T18:30:00": năm, tháng, ngày, rồi đến giờ. DateTime.parse chuyển văn bản đó thành một DateTime. Khi in ra như vốn có, DateTime sẽ trông như 2026-11-03 18:30:00.000, kiểu mà chẳng ai muốn đọc trên điện thoại.

Gói intl định dạng ngày tháng để mọi người dễ đọc. DateFormat nhận một mẫu, gồm các chữ cái đại diện cho những phần của ngày tháng:

import 'package:intl/intl.dart';

final day = DateTime.parse('2026-11-03T18:30:00');
DateFormat('EEE, MMM d').format(day)    // Thứ Ba, 3 thg 11
DateFormat('EEEE d MMMM').format(day)   // Thứ Ba, ngày 3 tháng 11

E là thứ trong tuần, M là tháng và d là ngày trong tháng. Nhiều chữ cái hơn sẽ cho dạng dài hơn: EEE là Tue, EEEE là Tuesday, MMM là Nov, MMMM là November, MM là 11. Chữ hoa rất quan trọng: D là ngày trong năm. Dấu phẩy và khoảng trắng trong mẫu vẫn được giữ nguyên.

challenge icon

Thử thách

Dễ

Danh sách sự kiện hiển thị ngày tháng ở dạng thô. Định dạng từng ngày bằng DateFormat, để sự kiện đầu tiên hiển thị Tue, Nov 3. Đã có sẵn lệnh import intl.

Tự làm thử

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 iconTự kiểm tra

Bài học này có một bài trắc nghiệm ngắn. Bắt đầu bài học để trả lời và theo dõi tiến độ.

Tất cả bài học trong Dữ liệu và mạng

Tự luyện tập: Trình biên dịch Flutter online