Menu
CoddyTech
flag Ar iconالعربيةdown icon

التواريخ باستخدام DateFormat

جزء من قسم البيانات والشبكة في رحلة Flutter على Coddy. الدرس 20 من 27.

ترسل الخوادم التواريخ كنصوص بتنسيق ثابت، مثل "2026-11-03T18:30:00": السنة، ثم الشهر، ثم اليوم، ثم الوقت. تحوّل DateTime.parse هذا النص إلى DateTime. وعند طباعته كما هو، يبدو DateTime بهذا الشكل 2026-11-03 18:30:00.000، وهو تنسيق لا يرغب أحد في قراءته على الهاتف.

تنسّق الحزمة intl التواريخ لتكون سهلة القراءة. تأخذ DateFormat نمطًا، أي أحرفًا تدل على أجزاء التاريخ:

import 'package:intl/intl.dart';

final day = DateTime.parse('2026-11-03T18:30:00');
DateFormat('EEE, MMM d').format(day)    // الثلاثاء، نوفمبر 3
DateFormat('EEEE d MMMM').format(day)   // الثلاثاء 3 نوفمبر

يشير E إلى يوم الأسبوع، وM إلى الشهر، وd إلى يوم الشهر. تعطي الأحرف الإضافية صيغة أطول: EEE تعني Tue، وEEEE تعني Tuesday، وMMM تعني Nov، وMMMM تعني November، وMM تعني 11. للأحرف الكبيرة أهمية: يشير D إلى يوم السنة. تبقى الفواصل والمسافات في النمط كما هي.

challenge icon

التحدي

سهل

تعرض قائمة الفعاليات تواريخ خامًا. نسّق كل تاريخ باستخدام DateFormat، بحيث يظهر تاريخ الفعالية الأولى بالشكل Tue, Nov 3. استيراد intl موجود بالفعل.

جرّب بنفسك

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 iconاختبر نفسك

يتضمن هذا الدرس اختبارًا قصيرًا. ابدأ الدرس للإجابة عليه وتتبّع تقدمك.

جميع دروس البيانات والشبكة

تدرّب بنفسك: مترجم Flutter عبر الإنترنت