Nem sempre é fácil deixar um horário ou data no formato em que queremos. Tanto em Flutter quanto em outras tecnologias. Nesse artigo, vou te dar algumas dicas de como trabalhar melhor a formatação das datas com um foco em Flutter. Para editar os códigos, estou usando Flutter juntamente com o VSCode. Vamos criar um pequeno projeto para ilustrar melhor esse processo.

Criando o projeto

Primeiramente, vamos utilizar o comando para criação de um novo projeto. Vou nomear o projeto como data para ficar mais didático. Basta abrir o terminal, navegar até a pasta em que você quer que seu projeto fique e utilizar o comando:

flutter create datas

Após a criação do projeto, podemos abrir a nova pasta no VSCode e começar a trabalhar nosso código. A estrutura do projeto ficará assim:

Será criada também uma pasta chamada test, mas você pode deletá-la, sem problemas.

Código base

Agora, vamos alterar o código do arquivo pubspec.yaml, já que é preciso importar o intl, que é o pacote com as funções de formatação que serão usadas nesse projeto. Usaremos também o localizations, do próprio Flutter, para traduzir as datas. Se você quiser dar uma lida na documentação oficial, basta clicar no nome dos pacotes.

Enfim, o arquivo deve ficar assim:

name: datas
description: A new Flutter project.

publish_to: 'none'

version: 1.0.0+1

environment:
  sdk: ">=2.3.0 <3.0.0"

dependencies:
  flutter:
    sdk: flutter
  flutter_localizations:
    sdk: flutter
  cupertino_icons: ^0.1.2

dev_dependencies:
  flutter_test:
    sdk: flutter
  intl: ^0.16.0

flutter:


  uses-material-design: true

No arquivo main.dart, você pode apagar todo o conteúdo e deixar apenas o seguinte:

import 'package:flutter/material.dart';

main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      debugShowCheckedModeBanner: false,
      title: 'Formatação de datas',
      theme: ThemeData(
        brightness: Brightness.dark,
        accentColor: Colors.white,
        visualDensity: VisualDensity.adaptivePlatformDensity,
      ),
      home: MyHomePage(title: "Formatação de datas"),
    );
  }
}

class MyHomePage extends StatefulWidget {
  MyHomePage({Key key, this.title}) : super(key: key);
  final String title;

  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title),
        centerTitle: true,
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            Container(
              height: MediaQuery.of(context).size.width * 0.1,
              width: MediaQuery.of(context).size.width * 0.75,
              margin: EdgeInsets.all(4),
              color: Colors.grey[800],
              child: Row(
                mainAxisAlignment: MainAxisAlignment.center,
                children: [
                  Text("Datas"),
                ],
              ),
            ),
          ],
        ),
      ),
    );
  }
}

Com essas alterações, ao executar, o App deverá estar assim:

Até agora, fiz apenas algumas alterações visuais e preparei o espaço em que ficarão os exemplos.

Começando a implementar

Para começar, devemos fazer a importação dos pacotes que serão utilizados no código:

import 'package:flutter_localizations/flutter_localizations.dart';
import 'package:intl/intl.dart';

Após a importação, já salve seu código para que o VSCode rode o pub get automaticamente e baixe os pacotes.

No próximo passo, criaremos uma variável e definiremos o valor dela como a data atual. Para isso, vamos colocar o seguinte trecho de código abaixo do State da página e acima de override:

class _MyHomePageState extends State<MyHomePage> {
  DateTime data = DateTime.now();
  @override

Com isso já temos a data que será usada para fazer diversas formatações!

Formatando

Para o primeiro exemplo, basta substituir o Text, que contém a string Datas, pelo seguinte:

Text(DateFormat("'Data numérica:' dd/MM/yyyy").format(data)),

Dentro das aspas duplas está o código referente ao DateFormat do pacote intl. Ou seja, ‘dd’ significa dia, ‘MM’ significa mês e ‘yyyy’ significa ano. Para interpolar esses dados com texto, precisamos deixar o texto entre aspas simples dentro das aspas duplas anteriores. Beleza?

O resultado no App vai ser o seguinte:

Agora vamos adicionar outras formatações. Basta adiciornar outros Containers dentro da nossa Column. Após a virgula do primeiro Container, cole esse trecho de código:

Container(
              height: MediaQuery.of(context).size.width * 0.1,
              width: MediaQuery.of(context).size.width * 0.75,
              margin: EdgeInsets.all(4),
              color: Colors.grey[800],
              child: Row(
                mainAxisAlignment: MainAxisAlignment.center,
                children: [
                  Text(DateFormat("'Data por extenso:' d 'de' MMMM 'de' y")
                      .format(data)),
                ],
              ),
            ),

Com esse código, o mês estará por extenso. Porém, em inglês, pois é o padrão da linguagem.

Traduzindo para o português

Para fazer a tradução para ptBR, precisamos fazer algumas inclusões no projeto. É agora que usaremos o import do flutter_localizations, que eu mencionei mais acima. Feito o import, vamos adicionar o seguinte trecho de código lá na Class MyApp, ou seja, lá em cima no código:

localizationsDelegates: [
        GlobalMaterialLocalizations.delegate,
        GlobalWidgetsLocalizations.delegate
      ],
      supportedLocales: [const Locale('pt', 'BR')],

O trecho deve ficar entre o return do MaterialApp e o themeData, dessa forma:

return MaterialApp(
      localizationsDelegates: [
        GlobalMaterialLocalizations.delegate,
        GlobalWidgetsLocalizations.delegate
      ],
      supportedLocales: [const Locale('pt', 'BR')],
      debugShowCheckedModeBanner: false,
      title: 'Formatação de datas',
      theme: ThemeData(

Feito isso, tudo o que precisamos fazer agora é alterar um pouco o DateFormat que estavámos fazendo. O que antes estava assim:

DateFormat("'Data por extenso:' d 'de' MMMM 'de' y").format(data)

Deverá ficar assim:

DateFormat("'Data por extenso:' d 'de' MMMM 'de' y", "pt_BR").format(data)

Ou seja, tudo o que precisamos fazer agora é indicar dentro do DateFormat a língua em que queremos que o resultado seja impresso. O resultado no App vai ser esse:

Mais alguns exemplos

Outra formatação útil é a de abreviação do mês, que pode ser feita da seguinte forma:

Container(
              height: MediaQuery.of(context).size.width * 0.1,
              width: MediaQuery.of(context).size.width * 0.75,
              margin: EdgeInsets.all(4),
              color: Colors.grey[800],
              child: Row(
                mainAxisAlignment: MainAxisAlignment.center,
                children: [
                  Text(DateFormat("'Mês:' MMMM '//' 'Abreviação:' MMM", "pt_BR")
                      .format(data)),
                ],
              ),
            ),

O resultado será:

E por último, mas não menos importante, o dia da semana:

Container(
              height: MediaQuery.of(context).size.width * 0.1,
              width: MediaQuery.of(context).size.width * 0.75,
              margin: EdgeInsets.all(4),
              color: Colors.grey[800],
              child: Row(
                mainAxisAlignment: MainAxisAlignment.center,
                children: [
                  Text(DateFormat("'Dia da semana:' EEEE", "pt_BR")
                      .format(data)),
                ],
              ),
            ),

Resultado:

Finalizando

O código final do arquivo main.dart é o seguinte:

import 'package:flutter/material.dart';
import 'package:flutter_localizations/flutter_localizations.dart';
import 'package:intl/intl.dart';

main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      localizationsDelegates: [
        GlobalMaterialLocalizations.delegate,
        GlobalWidgetsLocalizations.delegate
      ],
      supportedLocales: [const Locale('pt', 'BR')],
      debugShowCheckedModeBanner: false,
      title: 'Formatação de datas',
      theme: ThemeData(
        brightness: Brightness.dark,
        accentColor: Colors.white,
        visualDensity: VisualDensity.adaptivePlatformDensity,
      ),
      home: MyHomePage(title: "Formatação de datas"),
    );
  }
}

class MyHomePage extends StatefulWidget {
  MyHomePage({Key key, this.title}) : super(key: key);
  final String title;

  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  DateTime data = DateTime.now();
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title),
        centerTitle: true,
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            Container(
              height: MediaQuery.of(context).size.width * 0.1,
              width: MediaQuery.of(context).size.width * 0.75,
              margin: EdgeInsets.all(4),
              color: Colors.grey[800],
              child: Row(
                mainAxisAlignment: MainAxisAlignment.center,
                children: [
                  Text(DateFormat("'Data numérica:' dd/MM/yyyy").format(data)),
                ],
              ),
            ),
            Container(
              height: MediaQuery.of(context).size.width * 0.1,
              width: MediaQuery.of(context).size.width * 0.75,
              margin: EdgeInsets.all(4),
              color: Colors.grey[800],
              child: Row(
                mainAxisAlignment: MainAxisAlignment.center,
                children: [
                  Text(DateFormat(
                          "'Data por extenso:' d 'de' MMMM 'de' y", "pt_BR")
                      .format(data)),
                ],
              ),
            ),
            Container(
              height: MediaQuery.of(context).size.width * 0.1,
              width: MediaQuery.of(context).size.width * 0.75,
              margin: EdgeInsets.all(4),
              color: Colors.grey[800],
              child: Row(
                mainAxisAlignment: MainAxisAlignment.center,
                children: [
                  Text(DateFormat("'Mês:' MMMM '//' 'Abreviação:' MMM", "pt_BR")
                      .format(data)),
                ],
              ),
            ),
            Container(
              height: MediaQuery.of(context).size.width * 0.1,
              width: MediaQuery.of(context).size.width * 0.75,
              margin: EdgeInsets.all(4),
              color: Colors.grey[800],
              child: Row(
                mainAxisAlignment: MainAxisAlignment.center,
                children: [
                  Text(DateFormat("'Dia da semana:' EEEE", "pt_BR")
                      .format(data)),
                ],
              ),
            ),
          ],
        ),
      ),
    );
  }
}

Lembrando que, como extraímos no início o dia atual, o resultado irá variar de acordo com o dia em que você estiver lendo esse artigo. Então, não pense que algo está errado caso o resultado seja diferente do mostrado nos prints!

Se quiser saber mais sobre os códigos utilizados pelo intl para fazer formatações, vou deixar alguns links abaixo! Bons estudos, galera!

Links úteis