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!