Formatar data - Angular - DatePipe

Se você utiliza substring e mais uma série de outros artifícios para formatar uma data no seu projeto Angular, saiba que com o DatePipe a coisa fica muito mais simples. Com apenas alguns comandos podemos traduzir os meses e dias, alterar a exibição do timezone e modificar o layout da data.

import { Component, VERSION } from '@angular/core';

@Component({
  selector: 'my-app',
  templateUrl: './app.component.html',
})
export class AppComponent  {
  data1 = new Date('2021-04-23T10:00:00.000');
}

No template:

<div>
  {{data1 | date}}
  <!-- Apr 23, 2021 -->
</div>

Por default o DatePipe irá formatar a data com o seguinte layout: MMM d, y.

Observação: para utilizar o DatePipe é necessário importar o CommonModule:

import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { BrowserModule } from '@angular/platform-browser';

import { AppComponent } from './app.component';
import { HelloComponent } from './hello.component';

@NgModule({
  imports:      [ BrowserModule, CommonModule ],
  declarations: [ AppComponent, HelloComponent ],
  bootstrap:    [ AppComponent ]
})
export class AppModule { }
app.module.ts

Parâmetros do DatePipe

O DatePipe tem 3 parâmetros opcionais:

  1. format - Indica como o objeto date deverá ser formatado. Exemplo: dd/MM/yyyy HH:mm
  2. timezone - Utilizado para renderizar a data em um timezone específico. Exemplo: -03:00
  3. locale - O valor padrão é en-US e é utilizado para indicar o esquema de formatação de acordo com o idioma/país

Parâmetro format

O primeiro parâmetro que podemos passar para o DatePipe é o format, ou seja, é como gostaríamos de renderizar o objeto date na tela.

Podemos utilizar configurações pré-definidas conforme a tabela abaixo, ou podemos utilizar um formato customizado através das letras, por exemplo: dd/MM/yyyy HH:mm.

Option Equivalent to Example
'short' 'M/d/yy, h:mm a' 6/15/15, 9:03 AM
'medium' 'MMM d, y, h:mm:ss a' Jun 15, 2015, 9:03:01 AM
'long' 'MMMM d, y, h:mm:ss a z' June 15, 2015 at 9:03:01 AM GMT+1
'full' 'EEEE, MMMM d, y, h:mm:ss a zzzz' Monday, June 15, 2015 at 9:03:01 AM GMT+01:00
'shortDate' 'M/d/yy' 6/15/15
'mediumDate' 'MMM d, y' Jun 15, 2015
'longDate' 'MMMM d, y' June 15, 2015
'fullDate' 'EEEE, MMMM d, y' Monday, June 15, 2015
'shortTime' 'h:mm a' 9:03 AM
'mediumTime' 'h:mm:ss a' 9:03:01 AM
'longTime' 'h:mm:ss a z' 9:03:01 AM GMT+1
'fullTime' 'h:mm:ss a zzzz' 9:03:01 AM GMT+01:00

fonte: https://angular.io/api/common/DatePipe#pre-defined-format-options

Na prática isto é extremamente simples, veja abaixo:

<div>
  <!-- Indicando qual o formato desejado -->
  {{data1 | date : 'dd/MM/yyyy HH:mm'}}
  <!-- 23/04/2021 10:00 -->
</div>
<div>
  <!-- Indicando qual o formato desejado -->
  {{data1 | date : 'dd/MM/yyyy'}}
  <!-- 23/04/2021 -->
</div>
<div>
  <!-- Indicando qual o formato desejado -->
  {{data1 | date : 'HH:mm'}}
  <!-- 10:00 -->
</div>
<div>
  {{data1 | date : 'dd MMM yyyy'}}
  <!-- 23 Apr 2021 -->

  <!-- 
       IMPORTANTE:
       Veja que o mês está em inglês mas você entenderá
       quando chegar no parâmetro locale
  -->
</div>

Parâmetro timezone

Quando você executa o comando data1 = new Date('2021-04-23T10:00:00.000'); no navegador, ele irá considerar que o valor da data é: 23 de abril de 2021 10:00 no timezone do computador onde o código está sendo executado. Então se o timezone do seu computador está em GMT-03:00 (horário de Brasília), estamos falando que são dez horas da manhã do dia 23/04/2021.

Se você trocar o timezone do seu computador para GMT-02:00, essa data será 23/04/2021 10:00 (horário local em GMT-02:00), ou seja, dez horas da manhã em GMT-02:00. Isto significa que no Brasil, GMT-03:00, são nove horas da manhã.

Supondo que sua API retorne a data no formato ISO 8601, que é justamente o formato utilizado em JSON.stringify({ data: new Date() }), o valor terá o seguinte formato: 2021-04-22T13:15:08.533Z

O Z no final da string indica um offset +00:00 em relação UTC, ou seja, em Brasília  (UTC-03:00) o horário acima corresponde a 22/04/2021 10:08.533.

UTM é o sucessor do Tempo Médio de Greenwich (Greenwich Mean Time), cuja sigla é GMT. A nova denominação foi cunhada para eliminar a inclusão de uma localização específica num padrão internacional, assim como para basear a medida do tempo nos padrões atômicos, mais do que nos celestes.

Retomando o exemplo anterior, vamos incluir o Z no final da string passada como parâmetro no new Date(). Lembre-se que meu computador está configurado com o horário de Brasília GMT-03:00:

import { Component, VERSION } from '@angular/core';

@Component({
  selector: 'my-app',
  templateUrl: './app.component.html',
})
export class AppComponent  {
  // Inclusão do Z do final da string abaixo:
  data1 = new Date('2021-04-23T10:00:00.000Z');
}

app.component.ts
<div>
  {{data1 | date }}
  <!-- Apr 23, 2021 -->
</div>
<div>
  {{data1 | date : 'dd/MM/yyyy HH:mm'}}
  <!-- 23/04/2021 07:00 -->
</div>
app.component.html

Por padrão o DatePipe irá utilizar o timezone do computador do cliente, por isto houve o ajuste de -3 (menos três) horas.

Para indicar o timezone manualmente, podemos utilizar o segundo parâmetro do DatePipe conforme os exemplos abaixo:

<div>
  <!-- Indicando qual o formato desejado -->
  {{data1 | date : 'dd/MM/yyyy HH:mm'}}
  <!-- 23/04/2021 07:00 -->
</div> 
<div>
  <!-- Indicando qual o formato e o timezone desejado -->
  {{data1 | date : 'dd/MM/yyyy HH:mm' : '-01:00' }}
  <!-- 23/04/2021 09:00 -->
</div>
<div>
  <!-- Indicando qual o formato e o timezone desejado -->
  {{data1 | date : 'dd/MM/yyyy HH:mm' : '+00:00' }}
  <!-- 23/04/2021 10:00 -->
</div>

Então temos o seguinte para data1 = new Date('2021-04-23T10:00:00.000Z');:

  • GMT-00:00 = 23/04/2021 10:00
  • GMT-01:00 = 23/04/2021 09:00
  • GMT-03:00 = 23/04/2021 07:00

Parâmetro locale

Este parâmetro altera o esquema de formatação de data de acordo com os padrões do idioma/país. Ele também traduz automaticamente o nome dos meses e dias da semana. Sendo assim, podemos declarar direto no template o idioma/país conforme o seguinte exemplo: {{data1 | date : 'short' : '' : 'pt-BR'}}

Importante: Antes de colocar o pt-BR no parâmetro locale, não se esqueça de importar manualmente a configuração do idioma/país no seu AppModule. Veja abaixo o exemplo de como fazer isto:

Only the en-US locale data comes with Angular. To localize dates in another language, you must import the corresponding locale data. See the I18n guide for more information.
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { CommonModule } from '@angular/common';

import { AppComponent } from './app.component';
import { HelloComponent } from './hello.component';

/* *********************************************** */
/* Importando a configuração de algumas linguagens */
import { registerLocaleData } from '@angular/common';
import localePT from '@angular/common/locales/pt';
import localeES from '@angular/common/locales/es';
import localeDE from '@angular/common/locales/de';
import localeFR from '@angular/common/locales/fr';
registerLocaleData(localePT);
registerLocaleData(localeES);
registerLocaleData(localeDE);
registerLocaleData(localeFR);
/* *********************************************** */

@NgModule({
  imports:      [ BrowserModule, CommonModule ],
  declarations: [ AppComponent, HelloComponent ],
  bootstrap:    [ AppComponent ],
})
export class AppModule { }
app.module.ts

Após efetuar o registro do idioma podemos utilizar o parâmetro locale:

<div>
  {{data1 | date : 'short'}}
  <!-- 11/23/21, 7:00 AM -->
</div>
<div>
  {{data1 | date : 'short' : '' : 'pt-BR'}}
  <!-- 23/11/2021 07:00 -->
</div>
app.component.html

Caso queira modificar o padrão de locale para toda sua aplicação, que por default é o en-US, basta modificar o provider LOCALE_ID no seu AppModule:

import { LOCALE_ID, NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { CommonModule } from '@angular/common';

import { AppComponent } from './app.component';
import { HelloComponent } from './hello.component';

import { registerLocaleData } from '@angular/common';
import localePT from '@angular/common/locales/pt';
import localeES from '@angular/common/locales/es';
import localeDE from '@angular/common/locales/de';
import localeFR from '@angular/common/locales/fr';
registerLocaleData(localePT);
registerLocaleData(localeES);
registerLocaleData(localeDE);
registerLocaleData(localeFR);

@NgModule({
  imports:      [ BrowserModule, CommonModule ],
  declarations: [ AppComponent, HelloComponent ],
  bootstrap:    [ AppComponent ],
  providers: [
   { provide: LOCALE_ID, useValue: 'pt-br' },
  ]
})
export class AppModule { }

Com a configuração acima, a formatação da data será sempre no padrão pt-BR e o nome dos dias e meses também respeitarão o idioma, veja nos exemplos abaixo:

<h2>Format: short</h2>
<div>
  {{data1 | date : 'short' : '' : 'en-US'}}
  <!-- 4/23/21, 7:00 AM -->
</div>
<div>
  {{data1 | date : 'short' : '' : 'es-ES'}}
  <!-- 23/4/21 7:00 -->
</div>
<div>
  <!-- 
       Quando não indicamos nada, vale o que está
       configurado no LOCALE_ID (pt_BR)
  -->
  {{data1 | date : 'short'}} 
  <!-- 23/04/2021 07:00 -->
</div>
<div>
  {{data1 | date : 'short' : '' : 'de-ch'}}
  <!-- 23.04.21, 07:00 -->
</div>
<div>
  {{data1 | date : 'short' : '' : 'fr-ca'}}
  <!-- 23/04/2021 07:00 -->
</div>
<h2>Format: long</h2>
<!-- **************************************** -->
<div>
  {{data1 | date : 'long' : '' : 'en-US'}}
  <!-- April 23, 2021 at 7:00:00 AM GMT-3 -->
</div>
<div>
  {{data1 | date : 'long' : '' : 'es-ES'}}
  <!-- 23 de abril de 2021, 7:00:00 GMT-3 -->
</div>
<div>
  <!-- 
       Quando não indicamos nada, vale o que está
       configurado no LOCALE_ID (pt_BR)
  -->
  {{data1 | date : 'long'}} 
  <!-- 23 de abril de 2021 07:00:00 GMT-3 -->
</div>
<div>
  {{data1 | date : 'long' : '' : 'de-ch'}}
  <!-- 23. April 2021 um 7:00:00 GMT-3 -->
</div>
<div>
  {{data1 | date : 'long' : '' : 'fr-ca'}}
  <!-- 23 avril 2021 à 7:00:00 GMT-3 -->
</div>
app.component.html

Considerações

O DatePipe fornece 3 parâmetros que nos ajudam em vários cenários. Na maioria dos casos que presenciei como desenvolvedor, acabei não utilizando nada além de indicar o LOCALE_ID para formatar a data no padrão nacional. Mas em poucos projetos a utilização do format e timezone foi de suma importância.

formatar-data-datepipe-angular - StackBlitz
Como formatar datas utilizando o DatePipe do Angular
Exemplo da utilização do DatePipe

Links interessantes: