Como formatar datas, horas e moedas em JavaScript?

Como formatar datas, horas e moedas em JavaScript?
Camila Pessôa
Camila Pessôa

Compartilhe

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.

O gif em repetição mostra um trecho de vídeo que viralizou na copa mundial de 2014. Há um senhor com aparentemente 55 anos, caucasiano e possui um bigode. Está assistindo a um jogo do Brasil em um estádio e usa uma camisa da seleção brasileira na cor amarela e verde, assim como os outros torcedores que aparecem ao fundo. Ele está abraçado a uma réplica da taça da copa do mundo fazendo uma expressão de profunda tristeza.

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á?

Imersão dev Back-end: mergulhe em programação hoje, com a Alura e o Google Gemini. Domine o desenvolvimento back-end e crie o seu primeiro projeto com Node.js na prática. O evento é 100% gratuito e com certificado de participação. O período de inscrição vai de 18 de novembro de 2024 a 22 de novembro de 2024. Inscreva-se já!

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).

Mostra o personagem do desenho animado japonês Naruto Uzumaki, ele tem cabelos amarelos pontiagudos, pele clara, usa uma bandana na testa com o símbolo em espiral que representa sua aldeia da folha. Ele está com os olho semicerrados as sobrancelhas tensas e lágrimas caem pelo seu rosto repetidamente.

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!”

O trecho de vídeo em repetição apresenta duas mulheres. A esquerda está uma mulher de pele negra, com os cabelos escuros e presos, ela veste um vestido branco. Ao lado direito está uma mulher de pele clara, cabelos claros e com um vestido estampado. Uma legenda apresenta a fala da mulher de vestido branco:  - “custou 3 reais”. A mulher de vestido estampado se mostra surpresa e fala “3 reais? Vocês acreditam? 3 reais?”. Depois disso as duas mulheres falam “3 reais” várias vezes.

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?

Camila Pessôa
Camila Pessôa

Oi oi, sou a Camila ! Ingressei na área de tecnologia por meio da robótica educacional e comecei os estudos em programação com desenvolvimento web e foco Back-end com Node.js. Adoro ler, assistir séries/filmes, animes, jogar e passear ao ar livre com minha filhota.Tenho tenho grande paixão por educação e tecnologia, pois acredito que essa combinação é transformadora! :)

Veja outros artigos sobre Programação