socialgekon.com
  • Principal
  • Eventos Coisas Para Fazer
  • Editando
  • Vida Designer
  • De Outros
Processo Interno

O Guia Definitivo para Manipulação DateTime

Como desenvolvedor de software, você não pode fugir da manipulação de datas. Quase todo aplicativo que um desenvolvedor constrói terá algum componente em que a data / hora precisa ser obtida do usuário, armazenada em um banco de dados e exibida de volta ao usuário.

Pergunte a qualquer programador sobre sua experiência em lidar com datas e fusos horários e eles provavelmente compartilharão algumas histórias de guerra. Manipular campos de data e hora certamente não é uma ciência espacial, mas pode ser entediante e sujeito a erros.

Existem centenas de artigos sobre o assunto por aí, no entanto, a maioria ou é muito acadêmica, com foco em detalhes essenciais, ou é muito irregular, fornecendo pequenos trechos de código sem muitas explicações que os acompanham. Este guia detalhado para manipulação de DateTime deve ajudá-lo a entender os conceitos de programação e as melhores práticas relevantes para hora e data, sem ter que navegar por um mar de informações sobre este tópico.



Neste artigo, irei ajudá-lo a pensar com clareza sobre os campos de data e hora e sugerir algumas práticas recomendadas que podem ajudá-lo a evitar o inferno de data / hora. Aqui, exploraremos alguns dos principais conceitos necessários para manipular valores de data e hora corretamente, formatos que são convenientes para armazenar valores DateTime e transferi-los por meio de APIs e muito mais.

Para começar, a resposta certa para o código de produção é quase sempre usar uma biblioteca adequada em vez de criar a sua própria. As possíveis dificuldades com o cálculo de DateTime discutidas neste artigo são apenas a ponta do iceberg, mas ainda é útil saber sobre elas, com ou sem uma biblioteca.

Bibliotecas DateTime ajudam se você entendê-las corretamente

Bibliotecas de datas ajudam de várias maneiras a tornar sua vida mais fácil. Eles simplificam muito a análise de datas, operações aritméticas e lógicas de datas e formatação de datas. Você pode encontrar uma biblioteca de datas confiável para o front-end e o back-end para fazer a maior parte do trabalho pesado para você.

No entanto, costumamos usar bibliotecas de datas sem pensar em como a data / hora realmente funciona. Data / hora é um conceito complexo. Os bugs que surgem devido ao seu entendimento incorreto podem ser extremamente difíceis de entender e corrigir, mesmo com a ajuda de bibliotecas de dados. Como um programador, você precisa entender os fundamentos e ser capaz de avaliar os problemas que as bibliotecas de datas resolvem para tirar o máximo proveito deles.

Além disso, as bibliotecas de data / hora só podem levá-lo até certo ponto. Todas as bibliotecas de data funcionam dando a você acesso a estruturas de dados convenientes para representar um DateTime. Se você estiver enviando e recebendo dados por meio de uma API REST, eventualmente precisará converter a data em uma string e vice-versa, porque JSON não tem uma estrutura de dados nativa para representar DateTime. Os conceitos que delineei aqui irão ajudá-lo a evitar alguns dos problemas comuns que podem surgir ao fazer essas transformações data-a-string e string-to-date.

Nota: Mesmo que eu tenha usado JavaScript como a linguagem de programação discutida neste artigo, esses são conceitos gerais que se aplicam, em grande medida, a praticamente todas as linguagens de programação e suas bibliotecas de datas. Portanto, mesmo que você nunca tenha escrito uma linha de JavaScript antes, fique à vontade para continuar lendo, pois dificilmente presumo qualquer conhecimento prévio de JavaScript no artigo.

Padronizando o Tempo

Um DateTime é um momento muito específico. Vamos pensar sobre isso. Enquanto rabisco este artigo, o relógio do meu laptop mostra 21 de julho 13h29. É o que chamamos de “hora local”, a hora que vejo nos relógios de parede ao meu redor e no meu relógio de pulso.

Mais ou menos alguns minutos, se eu pedir a minha amiga para me encontrar em um café próximo às 15h, posso esperar encontrá-la lá mais ou menos nessa hora. Da mesma forma, não haveria nenhuma confusão se, em vez disso, eu dissesse, por exemplo, 'vamos nos encontrar em uma hora e meia'. Costumamos falar sobre o tempo dessa maneira com pessoas que moram na mesma cidade ou fuso horário.

Vamos pensar em um cenário diferente: quero dizer a um amigo que mora em Uppsala, na Suécia, que quero falar com ele às 17h. Envio a ele uma mensagem: “Ei, Anton, vamos conversar às 17h”. Eu recebo imediatamente a resposta: 'Seu tempo ou meu tempo?'

Anton me disse que mora no fuso horário da Europa Central, que é UTC + 01: 00. Eu moro na UTC + 05: 45. Isso significa que quando são 17h onde eu moro, são 17h - 05h45 = 11h15 UTC, o que se traduz em 11h15 UTC + 1h = 12h15 em Uppsala, perfeito para ambos de nós.

Além disso, esteja ciente da diferença entre o fuso horário (Horário da Europa Central) e a diferença de fuso horário (UTC + 05: 45). Os países também podem decidir alterar suas compensações de fuso horário para o horário de verão por razões políticas. Quase todos os anos há uma mudança nas regras em pelo menos um país, o que significa que qualquer código com essas regras incorporadas deve ser mantido atualizado - vale a pena considerar o que sua base de código depende para isso para cada camada de seu aplicativo.

Esse é outro bom motivo pelo qual recomendamos que apenas o front end lide com fusos horários na maioria dos casos. Quando isso não acontece, o que acontece quando as regras que seu mecanismo de banco de dados usa não correspondem às de seu front end ou back end?

Esse problema de gerenciar duas versões diferentes do tempo, em relação ao usuário e em relação a um padrão universalmente aceito, é difícil, ainda mais no mundo da programação onde a precisão é fundamental e até mesmo um segundo pode fazer uma grande diferença. A primeira etapa para resolver esses problemas é armazenar DateTime em UTC.

Padronizando o formato

Padronizar o horário é maravilhoso porque eu só preciso armazenar o horário UTC e, desde que eu conheça o fuso horário do usuário, sempre posso converter para o horário dele. Por outro lado, se eu souber a hora local de um usuário e seu fuso horário, posso converter para UTC.

Mas as datas e horas podem ser especificadas em muitos formatos diferentes. Para a data, você pode escrever “30 de julho” ou “30 de julho” ou “30/07” (ou 30/7, dependendo de onde você mora). Por enquanto, você pode escrever “21:30” ou “2130”.

Cientistas de todo o mundo se reuniram para resolver este problema e decidiram por um formato para descrever o tempo que os programadores realmente gostam porque é curto e preciso. Gostamos de chamá-lo de “formato de data ISO”, que é uma versão simplificada do formato estendido ISO-8601 e tem a seguinte aparência:

Uma imagem que mostra uma versão simplificada do formato estendido ISO-8601, denominado formato de data ISO.

Para 00:00 ou UTC, usamos “Z”, o que significa hora Zulu, outro nome para UTC.

Manipulação de data e aritmética em JavaScript

Antes de começarmos com as práticas recomendadas, aprenderemos sobre a manipulação de datas usando JavaScript para obter uma compreensão da sintaxe e dos conceitos gerais. Embora usemos JavaScript, você pode adaptar facilmente essas informações à sua linguagem de programação favorita.

Usaremos aritmética de data para resolver problemas comuns relacionados a datas que a maioria dos desenvolvedores encontra.

Meu objetivo é deixá-lo confortável ao criar um objeto de data a partir de uma string e extrair componentes de uma. Isso é algo em que uma biblioteca de datas pode ajudá-lo, mas é sempre melhor entender como isso é feito nos bastidores.

Depois de sujar as mãos com data / hora, é mais fácil pensar sobre os problemas que enfrentamos, extrair as melhores práticas e seguir em frente. Se você quiser pular para as práticas recomendadas, fique à vontade para fazê-lo, mas eu recomendo fortemente que você pelo menos dê uma olhada na seção de aritmética de data abaixo.

O objeto JavaScript Date

As linguagens de programação contêm construções úteis para tornar nossas vidas mais fáceis. O JavaScript Date objeto é uma dessas coisas. Ele oferece métodos convenientes para obter a data e hora atuais, armazenar uma data em uma variável, realizar aritmética de data e formatar a data com base na localidade do usuário.

Devido às diferenças entre as implementações do navegador e o manuseio incorreto do horário de verão (DST), dependendo do objeto Date para aplicativos de missão crítica não é recomendado e você provavelmente deve usar uma biblioteca DateTime como Luxon, data-fns ou dayjs . (O que quer que você use, evite o Moment.js que já foi popular - muitas vezes simplesmente chamado de moment, conforme aparece no código - uma vez que agora está obsoleto.)

Mas, para fins educacionais, usaremos os métodos que o objeto Date () fornece para aprender como JavaScript lida com DateTime.

Obtendo a Data Atual

const currentDate = new Date();

Se você não passar nada para o construtor Date, o objeto de data retornado conterá a data e a hora atuais.

Você pode então formatá-lo para extrair apenas a parte da data da seguinte maneira:

const currentDate = new Date(); const currentDayOfMonth = currentDate.getDate(); const currentMonth = currentDate.getMonth(); // Be careful! January is 0, not 1 const currentYear = currentDate.getFullYear(); const dateString = currentDayOfMonth + '-' + (currentMonth + 1) + '-' + currentYear; // '27-11-2020'

Nota: a armadilha “Janeiro é 0” é comum, mas não universal. Vale a pena verificar a documentação de qualquer idioma (ou formato de configuração: por exemplo, cron é baseado em 1) antes de começar a usá-lo.

Obtendo o carimbo de hora atual

Se, em vez disso, você deseja obter o carimbo de hora atual, pode criar um novo objeto Date e usar o método getTime ().

const currentDate = new Date(); const timestamp = currentDate.getTime();

Em JavaScript, um registro de data e hora é o número de milissegundos que se passaram desde 1º de janeiro de 1970.

Se você não pretende apoiar

Analisando uma Data

A conversão de uma string em um objeto de data JavaScript é feita de maneiras diferentes.

O construtor do objeto Date aceita uma ampla variedade de formatos de data:

Date.now()

Observe que você não precisa incluir o dia da semana porque JS pode determinar o dia da semana para qualquer data.

Você também pode passar o ano, mês, dia, horas, minutos e segundos como argumentos separados:

const date1 = new Date('Wed, 27 July 2016 13:30:00'); const date2 = new Date('Wed, 27 July 2016 07:45:00 UTC'); const date3 = new Date('27 July 2016 13:30:00 UTC+05:45');

Claro, você sempre pode usar o formato de data ISO:

const date = new Date(2016, 6, 27, 13, 30, 0);

No entanto, você pode ter problemas se não fornecer o fuso horário explicitamente!

const date = new Date('2016-07-27T07:45:00Z');

Qualquer um deles dará a você 25 de julho de 2016, 00:00:00, hora local.

Se você usar o formato ISO, mesmo que forneça apenas a data e não a hora e o fuso horário, ele aceitará automaticamente o fuso horário como UTC.

Isso significa que:

const date1 = new Date('25 July 2016'); const date2 = new Date('July 25, 2016');

Formatando uma Data

Felizmente, o JavaScript moderno tem algumas funções de internacionalização convenientes integradas ao padrão new Date('25 July 2016').getTime() !== new Date('2016-07-25').getTime() new Date('2016-07-25').getTime() === new Date('2016-07-25T00:00:00Z').getTime() namespace que torna a formatação de data uma operação simples.

Para isso, precisaremos de dois objetos: a Intl e um Date, inicializado com nossas preferências de saída. Supondo que gostaríamos de usar o formato americano (M / D / AAAA), ficaria assim:

Intl.DateTimeFormat

Se, em vez disso, quiséssemos o formato holandês (D / M / AAAA), apenas passaríamos um código de cultura diferente para o const firstValentineOfTheDecade = new Date(2020, 1, 14); // 1 for February const enUSFormatter = new Intl.DateTimeFormat('en-US'); console.log(enUSFormatter.format(firstValentineOfTheDecade)); // 2/14/2020 construtor:

DateTimeFormat

Ou uma forma mais longa do formato americano, com o nome do mês soletrado:

const nlBEFormatter = new Intl.DateTimeFormat('nl-BE'); console.log(nlBEFormatter.format(firstValentineOfTheDecade)); // 14/2/2020

Agora, se quisermos um formato ordinal adequado no dia do mês, ou seja, “14º” em vez de apenas “14”, isso infelizmente precisa de uma solução alternativa, porque const longEnUSFormatter = new Intl.DateTimeFormat('en-US', { year: 'numeric', month: 'long', day: 'numeric', }); console.log(longEnUSFormatter.format(firstValentineOfTheDecade)); // February 14, 2020 são apenas valores válidos como desta escrita são day ou 'numeric'. Pedindo emprestado Versão de Flavio Copes do Código de Mathias Bynens para alavancar outra parte de '2-digit' para isso, podemos personalizar a saída do dia do mês via Intl:

formatToParts()

Infelizmente, const pluralRules = new Intl.PluralRules('en-US', { type: 'ordinal' }) const suffixes = { 'one': 'st', 'two': 'nd', 'few': 'rd', 'other': 'th' } const convertToOrdinal = (number) => `${number}${suffixes[pluralRules.select(number)]}` // At this point: // convertToOrdinal('1') === '1st' // convertToOrdinal('2') === '2nd' // etc. const extractValueAndCustomizeDayOfMonth = (part) => { if (part.type === 'day') { return convertToOrdinal(part.value); } return part.value; }; console.log( longEnUSFormatter.formatToParts(firstValentineOfTheDecade) .map(extractValueAndCustomizeDayOfMonth) .join('') ); // February 14th, 2020 não é compatível com o Internet Explorer (IE) até o momento em que este livro foi escrito, mas todas as outras tecnologias de desktop, celular e back-end (ou seja, Node.js) tem suporte . Para aqueles que precisam suportar o IE e absolutamente precisam de ordinais, a nota abaixo (ou melhor, uma biblioteca de datas adequada) fornece uma resposta.

Se você precisar oferecer suporte a navegadores mais antigos como o IE antes da versão 11, a formatação de data em JavaScript é mais difícil porque não havia funções de formatação de data padrão como formatToParts em Python ou PHP.

No PHP, por exemplo, a função strftime dá a você strftime('Today is %b %d %Y %X', mktime(5,10,0,12,30,99)).

Você pode usar um combinação diferente de letras precedido por Today is Dec 30 1999 05:10:00 para obter a data em diferentes formatos. (Cuidado, nem todos os idiomas atribuem o mesmo significado a cada letra - particularmente, 'M' e 'm' podem ser trocados por minutos e meses.)

Se você tiver certeza do formato que deseja usar, é melhor extrair bits individuais usando as funções JavaScript que abordamos acima e criar uma string você mesmo.

%

Podemos obter a data no formato MM / DD / AAAA como

var currentDate = new Date(); var date = currentDate.getDate(); var month = currentDate.getMonth(); var year = currentDate.getFullYear();

O problema com essa solução é que ela pode dar um comprimento inconsistente às datas porque alguns meses e dias do mês têm um dígito e outros dois dígitos. Isso pode ser problemático, por exemplo, se você estiver exibindo a data em uma coluna da tabela, porque as datas não se alinham.

Podemos resolver isso usando uma função “pad” que adiciona um 0 à esquerda.

var monthDateYear = (month+1) + '/' + date + '/' + year;

Agora, obtemos a data correta no formato MM / DD / AAAA usando:

function pad(n) { return n<10 ? '0'+n : n; }

Se preferirmos DD-MM-AAAA, o processo é semelhante:

var mmddyyyy = pad(month + 1) + '/' + pad(date) + '/' + year;

Vamos começar e tentar imprimir a data no formato 'Mês, Data, Ano'. Precisaremos de um mapeamento de índices de meses para nomes:

var ddmmyyyy = pad(date) + '-' + pad(month + 1) + '-' + year;

Algumas pessoas gostam de exibir a data como 1º de janeiro de 2013. Sem problemas, tudo o que precisamos é uma função auxiliar var monthNames = [ 'January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December' ]; var dateWithFullMonthName = monthNames[month] + ' ' + pad(date) + ', ' + year; que retorna 1º para 1, 12º para 12 e 103º para 103 etc., e o resto é simples:

ordinal

É fácil determinar o dia da semana a partir do objeto de data, então vamos adicionar isso em:

var ordinalDate = ordinal(date) + ' ' + monthNames[month] + ', ' + year;

O ponto principal aqui é que, depois de extrair os números da data, a formatação está principalmente relacionada a strings.

Mudando o formato da data

Depois de saber como analisar uma data e formatá-la, alterar uma data de um formato para outro é apenas uma questão de combinar os dois.

Por exemplo, se você tem uma data no formato 21 de julho de 2013 e deseja alterar o formato para 21-07-2013, isso pode ser feito assim:

var daysOfWeek = ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat']; ordinalDateWithDayOfWeek = daysOfWeek[currentDate.getDay()] + ', ' + ordinalDate;

Usando funções de localização do objeto JavaScript Date

Os métodos de formatação de data que discutimos acima devem funcionar na maioria dos aplicativos, mas se você realmente deseja localizar a formatação da data, sugiro que use o const myDate = new Date('Jul 21, 2013'); const dayOfMonth = myDate.getDate(); const month = myDate.getMonth(); const year = myDate.getFullYear(); function pad(n) { return n<10 ? '0'+n : n } const ddmmyyyy = pad(dayOfMonth) + '-' + pad(month + 1) + '-' + year; // '21-07-2013' do objeto Date método:

toLocaleDateString()

… Nos dá algo como const today = new Date().toLocaleDateString('en-GB', { day: 'numeric', month: 'short', year: 'numeric', }); .

Alterar o local para 'en-US' resulta em '26 de julho de 2016'. Observe como a formatação mudou, mas as opções de exibição ainda eram as mesmas - um recurso muito útil. Conforme mostrado na seção anterior, a técnica mais recente baseada em 26 Jul 2016 funciona de maneira muito semelhante a esta, mas permite reutilizar um objeto formatador de forma que você só precise definir as opções uma vez.

Com Intl.DateTimeFormat, é um bom hábito sempre passar as opções de formatação, mesmo se a saída parecer boa em seu computador. Isso pode proteger a IU de interromper em localidades inesperadas com nomes de meses muito longos ou parecer estranha por causa de nomes curtos.

Se eu quiser o mês inteiro “julho”, tudo o que faço é alterar o parâmetro do mês nas opções para “longo”. JavaScript trata de tudo para mim. Para en-US, agora recebo 26 de julho de 2016.

Observação: se você quiser que o navegador use automaticamente a localidade do usuário, pode passar 'indefinido' como o primeiro parâmetro.

Se você quiser mostrar a versão numérica da data e não quiser se preocupar com MM / DD / AAAA vs. DD / MM / AAAA para diferentes localidades, sugiro a seguinte solução simples:

toLocaleDateString()

No meu computador, isso gera const today = new Date().toLocaleDateString(undefined, { day: 'numeric', month: 'numeric', year: 'numeric', }); . Se você quiser ter certeza de que o mês e a data têm dois dígitos, basta alterar as opções:

7/26/2016

Isso resulta em const today = new Date().toLocaleDateString(undefined, { day: '2-digit', month: '2-digit', year: 'numeric', }); . Exatamente o que queríamos!

Você também pode usar algumas outras funções relacionadas para localizar a forma como a hora e a data são exibidas:

CódigoResultadoDescrição
07/26/2016 '4:21:38 AM' Exibir versão localizada do único tempo
now.toLocaleTimeString() '04: 21: 38 AM ' Exibir a hora localizada com base nas opções fornecidas
now.toLocaleTimeString(undefined, { hour: '2-digit', minute: '2-digit', second: '2-digit', }); '22/07/2016, 4:21:38 AM' Exibir data e hora para a localidade do usuário
now.toLocaleString() '22/07/2016, 04:21' Exibir data e hora localizadas com base nas opções fornecidas

Cálculo de datas e horários relativos

Aqui está um exemplo de adição de 20 dias a uma data de JavaScript (ou seja, descobrir a data 20 dias após uma data conhecida):

now.toLocaleString(undefined, { day: 'numeric', month: 'numeric', year: 'numeric', hour: '2-digit', minute: '2-digit', });

O objeto de data original agora representa uma data 20 dias após 20 de julho e const myDate = new Date('July 20, 2016 15:00:00'); const nextDayOfMonth = myDate.getDate() + 20; myDate.setDate(nextDayOfMonth); const newDate = myDate.toLocaleString(); contém uma string localizada que representa essa data. No meu navegador, newDate contém “09/08/2016, 3:00:00 PM”.

Para calcular os carimbos de hora relativos com uma diferença mais precisa do que dias inteiros, você pode usar newDate e Date.getTime() para trabalhar com números inteiros que representam o número de milissegundos desde uma certa época, ou seja, 1 ° de janeiro de 1970. Por exemplo, se você quiser saber quando são 17 horas agora:

Date.setTime()

Comparando datas

Assim como tudo o mais relacionado à data, comparar datas tem suas próprias pegadinhas.

Primeiro, precisamos criar objetos de data. Felizmente, = todos funcionam. Portanto, comparar 19 de julho de 2014 e 18 de julho de 2014 é tão fácil quanto:

const msSinceEpoch = (new Date()).getTime(); const seventeenHoursLater = new Date(msSinceEpoch + 17 * 60 * 60 * 1000);

Verificar a igualdade é mais complicado, pois dois objetos de data representando a mesma data ainda são dois objetos de data diferentes e não serão iguais. Comparar strings de data é uma má ideia porque, por exemplo, “20 de julho de 2014” e “20 de julho de 2014” representam a mesma data, mas têm diferentes representações de string. O snippet abaixo ilustra o primeiro ponto:

const date1 = new Date('July 19, 2014'); const date2 = new Date('July 28, 2014'); if(date1 > date2) { console.log('First date is more recent'); } else { console.log('Second date is more recent'); }

Isso produzirá const date1 = new Date('June 10, 2003'); const date2 = new Date(date1); const equalOrNot = date1 == date2 ? 'equal' : 'not equal'; console.log(equalOrNot); .

Este caso particular pode ser corrigido comparando os equivalentes inteiros das datas (seus carimbos de hora) da seguinte forma:

not equal

Já vi este exemplo em muitos lugares, mas não gosto porque você não cria um objeto de data a partir de outro objeto de data normalmente. Então eu acho que o exemplo é importante apenas do ponto de vista acadêmico. Além disso, isso requer que os dois objetos Date se refiram exatamente ao mesmo segundo, enquanto você pode querer apenas saber se eles se referem ao mesmo dia, hora ou minuto.

Vejamos um exemplo mais prático. Você está tentando comparar se o aniversário que o usuário inseriu é o mesmo que a data de sorte que você obteve de uma API.

date1.getTime() == date2.getTime()

Ambos representaram a mesma data, mas infelizmente seu usuário não receberá o milhão de dólares.

Aqui está o problema: JavaScript sempre assume que o fuso horário é aquele fornecido pelo navegador, a menos que seja explicitamente especificado de outra forma.

Isso significa, para mim, const userEnteredString = '12/20/1989'; // MM/DD/YYYY format const dateStringFromAPI = '1989-12-20T00:00:00Z'; const dateFromUserEnteredString = new Date(userEnteredString) const dateFromAPIString = new Date(dateStringFromAPI); if (dateFromUserEnteredString.getTime() == dateFromAPIString.getTime()) { transferOneMillionDollarsToUserAccount(); } else { doNothing(); } criará uma data 1989-12-20T00: 00: 00 + 5: 45 ou 1989-12-19T18: 15: 00Z que não é o mesmo que 1989-12-20T00: 00: 00Z em termos de carimbo de hora.

Não é possível alterar apenas o fuso horário de um objeto de data existente, então nosso objetivo agora é criar um novo objeto de data, mas com UTC em vez do fuso horário local.

Ignoraremos o fuso horário do usuário e usaremos UTC ao criar o objeto de data. Existem duas maneiras de fazer isso:

  1. Crie uma string de data formatada ISO a partir da data de entrada do usuário e use-a para criar um objeto Date. Usar um formato de data ISO válido para criar um objeto Date enquanto torna a intenção de UTC versus local muito clara.
new Date ('12/20/1989')

Isso também funciona se você não especificar o horário, pois o padrão será meia-noite (ou seja, 00: 00: 00Z):

const userEnteredDate = '12/20/1989'; const parts = userEnteredDate.split('/'); const userEnteredDateISO = parts[2] + '-' + parts[0] + '-' + parts[1]; const userEnteredDateObj = new Date(userEnteredDateISO + 'T00:00:00Z'); const dateFromAPI = new Date('1989-12-20T00:00:00Z'); const result = userEnteredDateObj.getTime() == dateFromAPI.getTime(); // true

Lembre-se: se o construtor de data receber uma string no formato de data ISO correto de AAAA-MM-DD, ele assumirá o UTC automaticamente.

  1. JavaScript fornece uma função Date.UTC () bacana que você pode usar para obter o carimbo de hora UTC de uma data. Extraímos os componentes da data e os passamos para a função.
const userEnteredDate = new Date('1989-12-20'); const dateFromAPI = new Date('1989-12-20T00:00:00Z'); const result = userEnteredDate.getTime() == dateFromAPI.getTime(); // true

Encontrando a diferença entre duas datas

Um cenário comum que você encontrará é encontrar a diferença entre duas datas.

Discutimos dois casos de uso:

Encontrando o Número de Dias entre Duas Datas

Converta ambas as datas para o carimbo de hora UTC, encontre a diferença em milissegundos e encontre os dias equivalentes.

const userEnteredDate = new Date('12/20/1989'); const userEnteredDateTimeStamp = Date.UTC(userEnteredDate.getFullYear(), userEnteredDate.getMonth(), userEnteredDate.getDate(), 0, 0, 0); const dateFromAPI = new Date('1989-12-20T00:00:00Z'); const result = userEnteredDateTimeStamp == dateFromAPI.getTime(); // true ...

Encontrar a idade do usuário a partir da data de nascimento

const dateFromAPI = '2016-02-10T00:00:00Z'; const now = new Date(); const datefromAPITimeStamp = (new Date(dateFromAPI)).getTime(); const nowTimeStamp = now.getTime(); const microSecondsDiff = Math.abs(datefromAPITimeStamp - nowTimeStamp); // Math.round is used instead of Math.floor to account for certain DST cases // Number of milliseconds per day = // 24 hrs/day * 60 minutes/hour * 60 seconds/minute * 1000 ms/second const daysDiff = Math.round(microSecondsDiff / (1000 * 60 * 60 * 24)); console.log(daysDiff);

Nota: Temos um formato não padronizado. Leia o documento da API para determinar se isso significa 12 de outubro ou 10 de dezembro. Mude para o formato ISO de acordo.

const birthDateFromAPI = '12/10/1989';

Sei que existem maneiras mais concisas de escrever esse código, mas gosto de escrevê-lo dessa forma por causa da clareza absoluta da lógica.

Sugestões para evitar encontros infernais

Agora que estamos confortáveis ​​com a aritmética de data, podemos entender as melhores práticas a serem seguidas e os motivos para segui-las.

Obtendo DateTime do usuário

Se você estiver obtendo a data e a hora do usuário, provavelmente está procurando o DateTime local. Vimos na seção aritmética de data que const parts = birthDateFromAPI.split('/'); const birthDateISO = parts[2] + '-' + parts[0] + '-' + parts[1]; const birthDate = new Date(birthDateISO); const today = new Date(); let age = today.getFullYear() - birthDate.getFullYear(); if(today.getMonth() o construtor pode aceitar a data de várias maneiras diferentes.

Para remover qualquer confusão, sempre sugiro criar uma data usando Date formato mesmo se você já tiver a data em um formato analisável válido. Se todos os programadores em sua equipe seguirem esta regra simples, será extremamente fácil manter o código a longo prazo, uma vez que é tão explícito quanto você pode ser com o new Date(year, month, day, hours, minutes, seconds, milliseconds) construtor.

A parte legal é que você pode usar as variações que permitem omitir qualquer um dos quatro últimos parâmetros se eles forem zero; ou seja, Date é igual a new Date(2012, 10, 12) porque os parâmetros não especificados são padronizados para zero.

Por exemplo, se você estiver usando um selecionador de data e hora que fornece a data 2012-10-12 e hora 12:30, você pode extrair as partes e criar um novo objeto Date da seguinte maneira:

new Date(2012, 10, 12, 0, 0, 0, 0)

Tente evitar criar uma data a partir de uma string, a menos que esteja no formato de data ISO. Use o método Data (ano, mês, data, horas, minutos, segundos, microssegundos).

Obtendo apenas a data

Se você estiver obtendo apenas a data, a data de nascimento de um usuário, por exemplo, é melhor converter o formato para um formato de data ISO válido para eliminar qualquer informação de fuso horário que possa fazer com que a data avance ou retroceda quando convertida para UTC. Por exemplo:

const dateFromPicker = '2012-10-12'; const timeFromPicker = '12:30'; const dateParts = dateFromPicker.split('-'); const timeParts = timeFromPicker.split(':'); const localDate = new Date(dateParts[0], dateParts[1]-1, dateParts[2], timeParts[0], timeParts[1]);

Caso você tenha esquecido, se você criar um const dateFromPicker = '12/20/2012'; const dateParts = dateFromPicker.split('/'); const ISODate = dateParts[2] + '-' + dateParts[0] + '-' + dateParts[1]; const birthDate = new Date(ISODate).toISOString(); objeto com a entrada em um formato de data ISO válido (AAAA-MM-DD), o padrão será UTC em vez do fuso horário do navegador.

Armazenando a Data

Sempre armazene o DateTime em UTC. Sempre envie uma string de data ISO ou um carimbo de hora para o back end.

Gerações de programadores de computador perceberam essa verdade simples depois de experiências amargas tentando mostrar a hora local correta para o usuário. Armazenar a hora local no back end é uma má ideia, é melhor deixar o navegador lidar com a conversão para a hora local no front end.

Além disso, deve ficar claro que você nunca deve enviar uma string DateTime como “20 de julho de 1989 12:10” para o backend. Mesmo se você enviar o fuso horário também, estará aumentando o esforço para que outros programadores entendam suas intenções e analisem e armazenem a data corretamente.

Use o Date ou toISOString() métodos do objeto Date para converter o DateTime local em UTC.

toJSON()

Exibindo a data e hora

  1. Obtenha o carimbo de data / hora ou a data formatada por ISO de uma API REST.
  2. Crie um const dateFromUI = '12-13-2012'; const timeFromUI = '10:20'; const dateParts = dateFromUI.split('-'); const timeParts = timeFromUI.split(':'); const date = new Date(dateParts[2], dateParts[0]-1, dateParts[1], timeParts[0], timeParts[1]); const dateISO = date.toISOString(); $.post('http://example.com/', {date: dateISO}, ...) objeto.
  3. Use o Date ou toLocaleString() e toLocaleDateString() métodos ou uma biblioteca de data para exibir a hora local.
toLocaleTimeString()

Quando você deve armazenar a hora local também?

“Às vezes é importante saber o fuso horário em que um evento ocorreu, e a conversão para um único fuso horário oblitera irrevogavelmente essa informação.

“Se você está fazendo uma promoção de marketing e quer saber quais clientes fizeram pedidos na hora do almoço, um pedido que parece ter sido feito ao meio-dia GMT não é muito útil quando realmente foi feito durante o café da manhã em Nova York.”

Se você se deparar com esse tipo de situação, seria mais sensato economizar também a hora local. Como de costume, gostaríamos de criar a data no formato ISO, mas primeiro temos que encontrar a diferença de fuso horário.

O objeto Date é const dateFromAPI = '2016-01-02T12:30:00Z'; const localDate = new Date(dateFromAPI); const localDateString = localDate.toLocaleDateString(undefined, { day: 'numeric', month: 'short', year: 'numeric', }); const localTimeString = localDate.toLocaleTimeString(undefined, { hour: '2-digit', minute: '2-digit', second: '2-digit', }); A função nos diz o número de minutos que, quando adicionado a uma determinada hora local, dá a hora UTC equivalente. Sugiro convertê-lo para o formato (+ -) hh: mm porque torna mais óbvio que é um deslocamento de fuso horário.

getTimeZoneOffset()

Para meu fuso horário +05: 45, obtenho -345, este não é apenas o sinal oposto, mas um número como -345 pode ser completamente desconcertante para um desenvolvedor de back-end. Portanto, convertemos isso para +05: 45.

const now = new Date(); const tz = now.gettime zoneOffset();

Agora, obtemos o restante dos valores e criamos uma string ISO válida que representa o DateTime local.

const sign = tz > 0 ? '-' : '+'; const hours = pad(Math.floor(Math.abs(tz)/60)); const minutes = pad(Math.abs(tz)%60); const tzOffset = sign + hours + ':' + minutes;

Se desejar, você pode agrupar as datas UTC e locais em um objeto.

const localDateTime = now.getFullYear() + '-' + pad(now.getMonth()+1) + '-' + pad(now.getDate()) + 'T' + pad(now.getHours()) + ':' + pad(now.getMinutes()) + ':' + pad(now.getSeconds());

Agora, no backend, se você quiser saber se o evento ocorreu antes do meio-dia, horário local, você pode analisar a data e simplesmente usar o const eventDate = { utc: now.toISOString(), local: localDateTime, tzOffset: tzOffset, } função.

getHours()

Não usamos o const localDateString = eventDate.local; const localDate = new Date(localDateString); if(localDate.getHours() <12) { console.log('Event happened before noon local time'); } aqui, mas ainda o armazenamos porque podemos precisar dele no futuro para fins de depuração. Na verdade, você poderia apenas enviar a diferença de fuso horário e a hora UTC apenas. Mas eu gosto de armazenar a hora local também porque você eventualmente terá que armazenar a data em um banco de dados e ter a hora local armazenada separadamente permite que você faça uma consulta direta com base em um campo em vez de ter que realizar cálculos para obter a data local.

Às vezes, mesmo com o fuso horário local armazenado, você desejará exibir datas em um fuso horário específico. Por exemplo, os horários dos eventos podem fazer mais sentido no fuso horário do usuário atual se eles forem virtuais, ou no fuso horário onde ocorrerão fisicamente, se não forem. Em qualquer caso, vale a pena olhar de antemão soluções estabelecidas para formatação com nomes de fusos horários explícitos.

Configuração de servidor e banco de dados

Sempre configure seus servidores e bancos de dados para usar o fuso horário UTC. (Observe que UTC e GMT são não é a mesma coisa —GMT, por exemplo, pode implicar uma mudança para BST durante o verão, enquanto UTC nunca irá.)

Já vimos o quanto as conversões de fuso horário podem ser problemáticas, especialmente quando não são intencionais. Sempre enviar DateTime UTC e configurar seus servidores para estarem no fuso horário UTC pode tornar sua vida mais fácil. Seu código de back-end será muito mais simples e limpo, pois não precisa fazer nenhuma conversão de fuso horário. Os dados DateTime vindos de servidores em todo o mundo podem ser comparados e classificados sem esforço.

O código no back end deve ser capaz de assumir o fuso horário do servidor como UTC (mas ainda deve ter uma verificação no local para ter certeza). Uma simples verificação de configuração evita ter que pensar e codificar para conversões sempre que um novo código DateTime é escrito.

É hora de um melhor manuseio de datas

A manipulação de datas é um problema difícil. Os conceitos por trás dos exemplos práticos neste artigo se aplicam além do JavaScript e são apenas o começo quando se trata de lidar adequadamente com dados e cálculos DateTime. Além disso, cada biblioteca auxiliar virá com seu próprio conjunto de nuances.

O resultado final é: Use ISO no back-end e deixe o front-end para formatar as coisas adequadamente para o usuário. Os programadores profissionais estarão cientes de algumas das nuances e (ainda mais decididamente) usarão bibliotecas DateTime bem suportadas tanto no back end quanto no front end. Funções integradas no lado do banco de dados são outra história, mas espero que este artigo forneça informações suficientes para tomar decisões mais sábias nesse contexto também.

Relacionado: Código de JavaScript com erros: os 10 erros mais comuns que os desenvolvedores de JavaScript cometem

Conheça o seu monumento: ‘Taj de Haryana’, a tumba de Sheikh Chilli

Eventos Coisas Para Fazer

Conheça o seu monumento: ‘Taj de Haryana’, a tumba de Sheikh Chilli
Como fazer a transição de UX Designer para UX Consultant

Como fazer a transição de UX Designer para UX Consultant

Vida Designer

Publicações Populares
Dados persistentes em recarregamentos de página: cookies, IndexedDB e tudo que está entre eles
Dados persistentes em recarregamentos de página: cookies, IndexedDB e tudo que está entre eles
Tutorial de gerenciamento de estado de exibição React.js
Tutorial de gerenciamento de estado de exibição React.js
Como Executar um Design Sprint Eficaz
Como Executar um Design Sprint Eficaz
Como tirar uma captura de tela no iPhone: 5 maneiras de capturar sua tela
Como tirar uma captura de tela no iPhone: 5 maneiras de capturar sua tela
Blues da indústria de kits de refeição: Como o avental azul pode aliviar seu mal-estar?
Blues da indústria de kits de refeição: Como o avental azul pode aliviar seu mal-estar?
 
Web Design Brutalista, Web Design Minimalista e o Futuro da UX da Web
Web Design Brutalista, Web Design Minimalista e o Futuro da UX da Web
Conselhos sobre som: um guia rápido para projetar sons de experiência do usuário
Conselhos sobre som: um guia rápido para projetar sons de experiência do usuário
Cadeias de protótipos de JavaScript, cadeias de escopo e desempenho: o que você precisa saber
Cadeias de protótipos de JavaScript, cadeias de escopo e desempenho: o que você precisa saber
Vasos virais: cinco navios que transportavam doenças
Vasos virais: cinco navios que transportavam doenças
Como organizar fotos no seu iPhone
Como organizar fotos no seu iPhone
Categorias
Talento ÁgilArmazenandoReceita E CrescimentoEstilo De VidaPessoas E EquipesNoticias Do MundoCiência De Dados E Bancos De DadosPesquisarBlogTendências

© 2023 | Todos Os Direitos Reservados

socialgekon.com