Como formatar datas, horas e moedas em JavaScript?
Introdução
A World Wide Web é fascinante por conseguir conectar pessoas em diferentes locais do mundo. Alguém no Japão pode acessar uma página brasileira ou vice-versa e isso é maravilhoso! É o que chamamos de Internacionalização, pois os recursos de aplicações, sistemas web e sites estão disponíveis em todos os lugares do globo.
No entanto, lugares distintos apresentam normas e padrões culturais também distintos, e que não ficam restritos ao idioma, tais como convenções de formatos de data, hora, unidade de medida, temperatura, peso, dentre outros.
Um exemplo clássico é o formato de datas nos Estados Unidos, onde tipicamente as datas tem a estrutura “mês/dia/ano” (ex: 08/21/1988), enquanto no Brasil e em vários países da Europa as datas começam pelo dia, com a estrutura “dia/mês/ano” (ex: 21/08/1988 - meu aniversário, anota aí!).
Imagine o cenário de uma loja online norte-americana em que você precisa responder um formulário com sua data de nascimento e insere o padrão brasileiro. Provavelmente o formulário vai retornar um erro se a aplicação não apresentar as configurações de conversão de acordo com a localidade do navegador do cliente.
Ou então, imagine que você trabalha no Japão e quer acompanhar os jogos do campeonato brasileiro de futebol via streaming, mas a plataforma que exibe os jogos não configurou os horários e datas para convertê-los de acordo com o navegador do cliente. Provavelmente, perderá os seus jogos preferidos porque ficou sem a orientação correta do fuso horário.
Fonte: tenor
Além dessas questões, outras situações podem surgir com um impacto ainda maior em seus projetos, e por isso é importante entendermos alguns aspectos relevantes sobre essas normas.
E como tratamos essas convenções em nossos projetos com JavaScript? Uma solução é converter as informações!
Neste artigo vamos utilizar a linguagem JavaScript para trabalharmos com as soluções e, para isso, precisamos relembrar brevemente alguns pontos sobre o objeto Date
. Em seguida vamos estabelecer as conversões para garantir a internacionalização de informações via método toLocale()
e entender como a API de internacionalização Intl
pode ser utilizada para este fim, ambas soluções nativas do JavaScript.
Vamos lá?
Internacionalização com objetos Intl
e Date
O objeto global Date
funciona como um construtor para datas em JavaScript. Todas as vezes que você criar um new Date()
surgirá uma nova instância com data, horário, fuso horário e time-zone. É possível trabalhar isoladamente com meses, horas, minutos, etc. Você pode se aprofundar no assunto com dois artigos: “Trabalhando com datas em JavaScript” e “Objeto Date e formato de datas em JavaScript”.
Mas o importante neste momento é entendermos que há vários métodos nativos do JavaScript para manipular as datas, assim como as localidades associadas ao objeto Global Date. Mas como isso funciona na prática?
No código abaixo podemos conferir um exemplo que cria uma nova data com o new Date()
:
const novaData = new Date(Date.UTC(2023, 09, 20, 10, 11, 08));
console.log(novaData)
console.log(novaData.toLocaleString('pt-BR', { timezone: 'UTC' }));
Perceba que já utilizamos um método para criar a data dentro do padrão UTC, sua sintaxe é a seguinte Date.UTC(ano, mês[, dia[, hora[, minuto[, segundo[, milisegundo]]]]])
. No entanto a saída não ficou muito legível para o padrão brasileiro, confira na sequência:
2023-10-20T10:11:08.000Z
Como podemos resolver esse problema?
Podemos utilizar o método toLocaleString()
para formatar data e hora de acordo com as especificações de localidades, confira no código abaixo:
const novaData = new Date(Date.UTC(2023, 09, 20, 10, 11, 08));
console.log(novaData.toLocaleString('pt-BR', { timezone: 'UTC' }));
A saída será apresentada da seguinte maneira:
20/10/2023 07:11:08
Muito mais legível, não é? Agora conseguimos entender que temos uma data e um horário de acordo com o nosso padrão brasileiro.
Há também outra forma semelhante ao uso dos métodos, que é com o objeto Intl
. Vamos entender com um exemplo:
const novaData = new Date(Date.UTC(2023, 09, 20, 10, 11, 08));
const dataComIntl = new Intl.DateTimeFormat('pt-BR', {
dateStyle: 'short',
timeStyle: 'long',
timeZone: 'America/Belem',
});
console.log(dataComIntl.format(novaData));
O trecho de código acima formata a data criada e sua saída é:
20/10/2023 07:11:08 BRT
Bastante similar ao executado no código com o método toLocaleString()
não é?
Porém, o objeto Intl
é um namespace para a API de Internacionalização e seus métodos de formatação, inclusive seu nome vem de uma abreviação de “Internationalization” (Internacionalização, em tradução livre).
Essa API de internacionalização formata e manipula números, datas e textos (tipos de dados string) de acordo com o padrão de determinada região. Uma de suas propriedades, por exemplo, é a Intl.DateTimeFormat
que formata e apresenta horário e datas de acordo com as convenções de uma localidade específica.
Para manipular datas, horas ou moedas, você deve chamar o namespace Intl
, aplicar a notação de ponto e depois o método desejado para a formatação.
Em seguida há vários argumentos para especificar o locales (o argumento que identifica a localidade), baseado nas Language Tags (BCP 47 , que falando de forma simples são os pt-BR ou en-US para definir a língua e localização) e há também o parâmetro options, que são opções designadas por um objeto que carrega as especificações do tipo de número, moeda, data ou qualquer informação que será formatada.
Como notamos no trecho de código que formata nossa data const dataComIntl
, para formatar uma data e hora com o Intl.DateTimeFormat
nós criamos uma nova data com o construtor new Date()
e depois indicamos as especificações com o método DateTimeFormat()
e seus argumentos locales
e options
. Em seguida há o método format()
, chamado para executar a ação na data criada.
Dessa maneira é possível aplicar a mesma formatação em diferentes datas. Muito legal, não é? Vamos aprofundar com mais exemplos de formatação? Acompanhe o tópico a seguir.
Datas e horas
Há inúmeras formas para formatação de datas e horas em JavaScript, algumas mais complexas e outras mais simples. A ideia é apresentar estratégias nativas do JavaScript para que você não precise formatar dia, ano, mês de forma isolada.
Objeto Date
e formatação
É possível trabalhar inúmeros métodos com objeto Date
para manipular datas e o tempo de acordo com a localidade. Um método muito comum é o toLocaleDateString()
e sua sintaxe é definida com o objeto date, o método e os argumentos locales e options que já estudamos no tópico anterior:
dateObj.toLocaleDateString([locales [, options]])
- Formatação de datas:
Uma dúvida corriqueira é: como criamos uma data e conseguimos formatá-la? Vamos aprender na prática, confira o código abaixo:
//formatação de data atual com locales
const novaData = new Date();
console.log(novaData);// data sem formatação
console.log(novaData.toLocaleDateString('pt-BR'));// data em português dia/mês/ano
console.log(novaData.toLocaleDateString('ko-KR')); //coreano ano.mês.dia.
Também podemos customizar os resultados com o parâmetros options:
//formatação de data atual com options
const opcoes = {
weekday: 'long',
year: 'numeric',
month: 'long',
day: 'numeric',
timezone: 'UTC',
};
console.log(novaData.toLocaleDateString('pt-BR', opcoes));
console.log(novaData.toLocaleDateString('ko-KR', opcoes));
A saída já mostra o dia da semana, dia em números, mês escrito de forma completa (por exemplo: Janeiro, e não Jan) e o ano em números. O primeiro console.log()
em português e o segundo em coreano.
Mas e se eu tiver uma data fixa? Como a data de um aniversário ou a data de uma entrega? Abaixo confira a formatação de data fixa:
//Formatação de data
const meuAniversario = '1988-08-21';
const dataCriada = new Date(meuAniversario);
const dataFormatada = dataCriada.toLocaleDateString('pt-BR', {
timeZone: 'UTC',
});
console.log(`Meu aniversário é ${dataFormatada}`); //Meu aniversário é 21/08/1988
Nota: é importante ressaltar que não se trata de uma tradução para o português, pois a frase em template string, se for escrita em outro idioma, continuará da mesma forma.
Até o momento nós analisamos apenas um método que pode ser trabalhado com o objeto Date
que já possibilita a formatação de datas e horas. Porém há uma variedade de métodos para formatação e você pode realizar os testes e implementações seguindo a documentação: Referência do objeto global Date MDN.
Os métodos do Date
são muito eficientes mas há outra forma de internacionalização, vamos conhecer no próximo tópico!
Objeto Intl
e formatação
Além dos métodos do objeto Date
há a API de internacionalização que também é capaz de formatar datas e horários de acordo com localidade, vamos conferir no código abaixo:
const dataAtual = new Date();
console.log(dataAtual)// Saída será a data atual sem formatação
const dataFormatada = new Intl.DateTimeFormat('pt-BR', {
dateStyle: 'full',
timeStyle: 'long',
timeZone: 'America/Sao_Paulo',
});
console.log(dataFormatada.format(dataAtual));//Saída será a data atual formatada com o horário
O parâmetro locales define o padrão da localização do português brasileiro com o pt-BR
. Depois disso, temos um objeto com as especificações de dataStyle
e timeStyle
que definem o estilo de apresentação das informações.
No exemplo nós optamos pelo dateStyle: ‘full’
, que irá mostrar a data completa em texto com dia da semana, dia, mês e ano
. E da mesma forma o timeStyle: ‘long’
irá apresentar o horário completo com as horas : minutos : segundos
e a especificação da localização, que no código foi especificado pela timeZone: ‘America/Sao_Paulo’
, então vai mostrar o BRT. Caso você não especifique uma timeZone
, o JavaScript captura o horário do runtime.
O método intl.DateTimeFormat
tem o objeto options como parâmetro, o qual você deve especificar as configurações de localização, locale {locale/localidade: ‘pt-BR}
e assim as convenções de cada localidade ficam de acordo com o desejado.
Você também pode formatar a data apresentando apenas uma opção como o ano com ’year/ano’
, dia da semana com ”weekday’
ou a hora com ’hour’
.
Mas essa saída de informações se parece bastante com a fornecida pelo JavaScript através do método toLocaleString()
, correto? Quais são as diferenças então?
A API Intl
retorna um objeto DateTimeFormat
tendo como base as orientações definidas nas options e formatadas com o método format()
. Embora seja bem parecido com o toLocaleString()
, a principal diferença é que no Intl.DateTimeFormat
a data é passada como um argumento no método format()
e o toLocaleString
é aplicado em um objeto que carrega as informações de uma data.
Um ponto de atenção é que você não precisa saber as configurações de todas as localidades ou regiões. Com o Intl.Locale()
você pode estabelecer o ciclo de horas, e visualizar as timeZones
aceitas, confira a seguir:
const portugues = new Intl.Locale('pt-BR', { hourCycle: 'h12' });
console.log(
portugues.language,
portugues.hourCycle,
portugues.region,
portugues.timeZones
);
A saída devolve as informações de região e time zone:
pt h12 BR [
'America/Araguaina',
'America/Bahia',
'America/Belem',
'America/Boa_Vista',
'America/Campo_Grande',
'America/Rio_Branco',
'America/Santarem',
'America/Sao_Paulo'
]
- Tempo relativo:
Há também a possibilidade de atribuir um formato tempo relativo, caso você deseje criar um cronômetro ou aviso de agendamento, por exemplo:
//Formatar tempo relativo com idioma do lugar
const tempoRelativo = new Intl.RelativeTimeFormat('pt-BR', { numeric: 'auto' });
console.log(tempoRelativo.format(2, 'month'));// em 2 meses
A saída passa a informação “em 2 meses”, ou seja, é uma contagem de tempo relativa. Já conseguiu imaginar os possíveis usos? Vamos refletir mais sobre isso a seguir!
Quando devemos usar o Intl
ou Date
?
Uma dúvida que pode surgir é: Qual o objeto mais adequado se ambos atuam de forma parecida?
Em algumas ocasiões, os métodos do objeto Date
, como o toLocaleString()
, tem o benefício da simplicidade de uso. Porém, de acordo com a documentação, quando temos uma quantidade muito grande de números a serem manipulados ou então problemas em relação a exibição pelo navegador, o indicado é utilizar a API Intl
.Além disso, há alguns problemas de versões com, como você pode conferir nessa Issue
do github.
Assim como datas e horas, unidades de medidas em números e a própria moeda não é algo padronizado. Como podemos formatar também os números? Descubra como fazer isso na sequência!
Números e moedas
Imagine que ao acessar uma plataforma de compras online de outro país você se depara com um super desconto e, naquela ansiedade para comprar todas as peças, você compra 4 blusas por 40,00. Mas o que você não notou é que o valor estava em dólares e no seu cartão de crédito a conta chegou em reais (no dia de sua compra, 1,0 dólar estava por volta de 5,20 reais).
fonte: tenor
Um pequeno deslize da equipe de desenvolvimento da plataforma gerou um problema sério para vários clientes. Como resolver essa questão?
Com a conversão de números! Porém, essa resposta pode fomentar outra dúvida: mas números equivalem a moedas?
Sim e não, um dado do tipo Number
isoladamente não é uma moeda, até porque os valores monetários são diferentes dependendo da localidade. Nesse caso, nós utilizamos os números em programação da mesma forma que no mundo real, ou seja, precisamos fazer a conversão dos valores. Isso significa que instruímos o nosso programa, através da linguagem de programação, a realizar a conversão. Por exemplo: “Pegue esse número 3 e transforme em 3,00 reais!”
fonte: gfycat
Vamos entender na prática?
Objeto Intl
e formatação de moedas
O código a seguir faz a formatação de um dado do tipo Number
para moedas, ou seja, um número para as moedas:
const numero = 50.0;
console.log(
new Intl.NumberFormat('pt-BR', { style: 'currency', currency: 'BRL' }).format(
numero
)
);// saída R$ 50,00
console.log(
new Intl.NumberFormat('de-DE', { style: 'currency', currency: 'EUR' }).format(
numero
)
);// saída 50,00 €
Em ambos exemplos ocorre a formatação do valor inicial, que é um dado do tipo Number
para o seu equivalente em Real e Euro. Essa formatação é realizada de acordo com o que desejamos exibir na tela, pois inserimos as propriedades no objeto como argumento do parâmetro options, da mesma forma como trabalhamos com as datas e horas.
Notamos que não se trata da conversão de um valor em real para euro, pois essa conversão pode ser realizada com o consumo de API’s, bibliotecas ou mesmo com o tratamento das informações no código (algo um pouco mais complexo), mas já temos as ferramentas necessárias para exibirmos a informação desejada em nossos projetos.
Também é possível trabalhar com o método toLocaleString()
, confira no próximo tópico.
toLocaleString()
e formatação de moedas
A formatação com o método toLocaleString()
segue a mesma lógica. O código a seguir apresenta o valor da const numero = 50.0;
padronizada para as localidades dos estados unidos e do Japão:
const numero = 50.0;
const formatoEua = numero.toLocaleString('en-US', {
style: 'currency',
currency: 'USD',
});
console.log(formatoEua);// saída $50.00
const formatoJp = numero.toLocaleString('jp-JP', {
style: 'currency',
currency: 'JPY',
});
console.log(formatoJp); // saída JP¥ 50
Percebemos que a saída já contém a identificação da moeda do local e o estilo de exibição. A forma de exibir pode ser estabelecida no objeto, em nosso código o style, que define o estilo de apresentação e está de acordo com a string de valor ’currency’
que significa moeda. Por sua vez, a moeda é o código ISO 4217 de cada localidade, nesse exemplo são: USD
e JPY
.
Podemos ainda definir a exibição das moedas com a propriedade currencyDisplay
, onde vamos apresentar a saída da informação por extenso ou pelo símbolo da moeda, confira:
const formatoBr = numero.toLocaleString('pt-BR', {
style: 'currency',
currency: 'BRL',
currencyDisplay: 'name',
});
console.log(formatoBr);
E a saída será 50,00 Reais brasileiros
. Bem útil, não é?
Provavelmente, a dúvida sobre qual forma utilizar para formatar moedas possa surgir neste momento. E a resposta está relacionada a sua necessidade, pois a recomendação é: se houver um volume grande de números, o ideal é criar um objeto com o Intl.NumberFormat
e formatar com o método Intl.NumberFormat.prototype.format()
.
Lembramos que o método toLocaleString()
pode ser associado ao objeto global Number
, ou seja, é utilizado para formatação de números e não apenas moedas. Por isso é importante definirmos a propriedade style
com o valor currency
, pois assim o dado será formatado como moeda.
Conclusão
Neste artigo entendemos que formatar datas e números em JavaScript não precisa ser um filme de terror. Há várias opções que você pode utilizar. São muitos métodos, objetos e API’s. Mas agora você já tem a base para escolher a melhor forma e aplicá-la dependendo do contexto do seu projeto.
Aprendemos que objeto global Date
é utilizado como construtor em datas JavaScript e vários métodos podem ser associados a ele para formatação de datas, como o toLocaleString()
.
Por outro lado, o Intl.Locale
é um conjunto de regras e convenções para formatar dados, como formatos de data e hora, símbolos de moeda e separadores de números. O objeto Intl fornece uma API de internacionalização em JavaScript que pode ser usada para formatar e exibir datas e horas, números e strings de acordo com as convenções de uma localidade específica.
Bom, agora consegue trabalhar com duas formas para formatação de datas, horas e moedas de acordo com a localidade e assim integrar seu projeto com o padrão de internacionalização.
Além disso, tem o conhecimento essencial para testar outros métodos. Confira exemplos com trechos de código, os famosos snippets no repositório Interactive Examples MDN para realizar novas implementações em seus projetos
Por fim, com todo o seu aprendizado deixo um desafio: crie seu conversor de moedas e melhore ainda mais seu portfólio.
Bons estudos e até mais!
Vamos aprender mais?
- Formação JavaScript para Backend
- Formação iniciante em programação
- Trabalhando com datas em JavaScript
- Format Date e formato de datas em JavaScript
- Node.js documentação API Intl
- MDN Global Objects Date
- MDN Intl Collator
- MDN Date toLocaleString
- MDN Number.toLocaleString
- toLocaleString
- MDN Global Objects Intl
- Intl.getCanonicalLocales()
- The Internationalization API
- ECMAScript Intl Object
- ECMAScript Internalization API
- MDN Global Objects Number
- MDN Intl DateTimeFormat
- RelativeTimeFormat MDN
- MDN Date UTC
- Number methods w3
- JavaScript Number Format
- Formatando numeros e moedas com tolocalestring
- What is tolocalestring in JavaScript?
- Como funciona o Intl.numberFormat
- Intl.getCanonicalLocales()
- Intl
- Intl.Collator
- Obtenha o nome do mês em JavaScript
- Entendendo o tolocaledateSrting
- How to format Number as currency String in JavaScript
- Locale Runtime JavaScript