Como faço para usar javascript para calcular o dia do ano, de 1 a 366? Por exemplo:
- 3 de janeiro deve ser 3 .
- 1º de fevereiro deve ser 32 .
javascript
Kirk Woll
fonte
fonte
var days = new Date().getFullYear() % 4 == 0 ? 366 : 365;
Respostas:
Após a edição do OP:
Editar: O código acima falhará quando
now
for uma data entre 26 de março e 29 de outubro enow
a hora for anterior à 1h (por exemplo, 00:59:59). Isso ocorre porque o código não leva em consideração o horário de verão. Você deve compensar por isso:fonte
Math.floor
consistentemente me deu um resultado de 1 dia a menos do que o esperado após um determinado dia de abril.Math.ceil
funcionou conforme o esperado, mas vi que é aconselhável que você use emMath.round
vez de qualquer um.new Date(2014, 0, 1)
, e nãonew Date(2014, 0, 0)
como aqui. Isso é intencional? Talvez seja isso o que explica estar um dia fora, poisnew Date(2014, 0, 0)
vai voltar12/31/2013
..setUTCHours
eDate.UTC()
para uma solução mais confiável.ceil
vez defloor
, isso lhe dará um sistema de numeração onde 1º de janeiro = 1. Se você quiser 1º de janeiro = 0 (comofloor
lhe daria), apenas subtraia 1 de seu resultado final.var diff = now - start + (start.getTimezoneOffset() - now.getTimezoneOffset()) * 60 * 1000;
Isso funciona em todas as mudanças do horário de verão em todos os países (o "meio-dia" acima não funciona na Austrália):
fonte
getDay()
precisa ser alterado paragetDate()
. O primeiro retorna o dia da semana (0 = domingo..6 = sábado), não o dia.Acho muito interessante que ninguém pensou em usar UTC, uma vez que não está sujeito ao DST. Portanto, proponho o seguinte:
Você pode testá-lo com o seguinte:
Quais resultados para o ano bissexto de 2016 (verificado usando http://www.epochconverter.com/days/2016 ):
fonte
function doyToDate(doy, year) { return new Date(year, 0, doy); }
new Date(8640000000000000)
, que ainda é menor queNumber.MAX_SAFE_INTEGER
. veja esta resposta: stackoverflow.com/a/11526569/18511fonte
Felizmente esta questão não especifica se o número do dia atual é obrigatório, deixando espaço para esta resposta.
Além disso, algumas respostas (também sobre outras questões) tiveram problemas de ano bissexto ou usaram o objeto Data. Embora o javascript
Date object
cubra aproximadamente 285616 anos (100 milhões de dias) em ambos os lados de 1º de janeiro de 1970, eu estava farto de todos os tipos de inconsistências de data inesperadas em navegadores diferentes (principalmente do ano 0 a 99). Eu também estava curioso para saber como calculá-lo.Então eu escrevi um algoritmo simples e, acima de tudo, pequeno para calcular o dia do ano correto ( Proléptico Gregoriano / Astronômico / ISO 8601: 2004 (cláusula 4.3.2.1), então ano
0
existe e é um ano bissexto e anos negativos são suportados ) com base no ano , mês e dia .Observe que, em
AD/BC
notação, o ano 0 AD / BC não existe: em vez disso, o ano1 BC
é o ano bissexto! SE você precisar contabilizar a notação BC, simplesmente subtraia um ano do valor do ano (caso contrário positivo) primeiro !!Modifiquei (para javascript) o algoritmo bitmask-módulo leapYear de curto-circuito e criei um número mágico para fazer uma pesquisa bit a bit de offsets (que exclui jan e feb, portanto, precisando de 10 * 3 bits (30 bits é menor que 31 bits, para que possamos salvar com segurança outro caractere no bitshift em vez de
>>>
)).Observe que nem o mês nem o dia podem ser
0
. Isso significa que se você precisa dessa equação apenas para o dia atual (alimentando-a usando.getMonth()
), você só precisa remover o--
de--m
.Observe que isso pressupõe uma data válida (embora a verificação de erros seja apenas mais alguns caracteres).
Aqui está a versão com validação de intervalo correta .
Novamente, uma linha, mas eu dividi em 3 linhas para facilitar a leitura (e a explicação seguinte).
A última linha é idêntica à função acima, no entanto, o algoritmo leapYear (idêntico) é movido para uma seção de curto-circuito anterior (antes do cálculo do número do dia), porque também é necessário saber quantos dias um mês tem em um dado ano (bissexto).
A linha do meio calcula o número de deslocamento correto (para o número máximo de dias) para um determinado mês em um determinado ano (bissexto) usando outro número mágico: como
31-28=3
e3
tem apenas 2 bits, então12*2=24
bits, podemos armazenar todos os 12 meses. Como a adição pode ser mais rápida do que a subtração, adicionamos o deslocamento (em vez de subtraí-lo31
). Para evitar um ramo de decisão de ano bissexto para fevereiro, modificamos esse número de pesquisa mágico instantaneamente.Isso nos deixa com a (bastante óbvia) primeira linha: ela verifica se o mês e a data estão dentro dos limites válidos e nos garante um
false
valor de retorno no erro de intervalo (observe que esta função também não deve ser capaz de retornar 0, porque 1 jan 0000 ainda é dia 1.), proporcionando fácil verificação de erros:if(r=dayNo(/*y, m, d*/)){}
.Se usado desta forma (onde mês e dia podem não ser
0
), então um pode mudar--m>=0 && m<12
param>0 && --m<12
(salvando outro caractere).O motivo pelo qual digitei o snippet em sua forma atual é que para valores de mês baseados em 0, basta remover o
--
de--m
.Extra:
Nota, não use este algoritmo de dias por mês se você precisa apenas de no máximo dias por mês. Nesse caso existe um algoritmo mais eficiente (porque só precisamos do leepYear quando o mês é fevereiro). Postei como resposta a esta pergunta: Qual é a melhor forma de determinar o número de dias de um mês com javascript? .
fonte
Date.prototype.dayNo = function(){ var y = this.getFullYear(); var m = this.getMonth()+1; var d = this.getDate(); return --m*31-(m>1?(1054267675>>m*3-6&7)-(y&3||!(y%25)&&y&15?0:1):0)+d; };
+1
dethis.getMonth()+1
se remover a--
partir--m
. EDITAR Então, eu faria (para uma biblioteca):Date.prototype.dayNo = function(){ var y=this.getFullYear(), m=this.getMonth(); return m*31-(m>1?(1054267675>>m*3-6&7)-(y&3||!(y%25)&&y&15?0:1):0)+this.getDate(); };
2^31 - 2016
anos, o js provavelmente estará um pouco desatualizado.:)
Mas até então, pelo menos dará resultados previsíveis e consistentes haha. EDITAR , apenas por uma questão de teoria, usando o algoritmo de módulo convencional mais lento para ano bissexto, o intervalo pode ser estendido para 2 ^ 53. O algoritmo de pesquisa de mês não é o fator limitante.Se não quiser reinventar a roda, você pode usar a excelente biblioteca date-fns (node.js):
fonte
Bem, se bem entendi, você quer 366 em um ano bissexto, 365 caso contrário, certo? Um ano é um ano bissexto se for igualmente divisível por 4, mas não por 100, a menos que também seja divisível por 400:
Editar após atualização:
Nesse caso, não acho que haja um método embutido; você precisará fazer isso:
(Sim, na verdade fiz isso sem copiar ou colar. Se houver uma maneira fácil, ficarei bravo)
fonte
:)
Esta é uma maneira simples de encontrar o dia atual do ano e deve representar os anos bissextos sem problemas:
Javascript:
Math.round((new Date().setHours(23) - new Date(new Date().getYear()+1900, 0, 1, 0, 0, 0))/1000/60/60/24);
Javascript no Google Apps Script:
Math.round((new Date().setHours(23) - new Date(new Date().getYear(), 0, 1, 0, 0, 0))/1000/60/60/24);
A principal ação desse código é encontrar o número de milissegundos decorridos no ano atual e, em seguida, converter esse número em dias. O número de milissegundos decorridos no ano atual pode ser encontrado subtraindo o número de milissegundos do primeiro segundo do primeiro dia do ano atual, que é obtido com
new Date(new Date().getYear()+1900, 0, 1, 0, 0, 0)
(Javascript) ounew Date(new Date().getYear(), 0, 1, 0, 0, 0)
(Google Apps Script), dos milissegundos da 23ª hora do dia atual, que foi encontrado comnew Date().setHours(23)
. O objetivo de definir a data atual para a 23ª hora é garantir que o dia do ano seja arredondado corretamente porMath.round()
.Assim que tiver o número de milissegundos do ano atual, você pode converter esse tempo em dias dividindo por 1000 para converter milissegundos em segundos, depois dividindo por 60 para converter segundos em minutos e dividindo por 60 para converter minutos em horas, e finalmente dividindo por 24 para converter horas em dias.
Observação: esta postagem foi editada para explicar as diferenças entre JavaScript e JavaScript implementado no Google Apps Script. Além disso, mais contexto foi adicionado para a resposta.
fonte
.setHours
método no primeiro objeto de data e especifiquei a hora do dia com o segundo objeto de data, uma alteração de 1 hora do horário de verão não afetará os horários dos objetos Date usados neste cálculo.Acho que é mais simples:
fonte
Este método leva em consideração a questão do fuso horário e o horário de verão
(tirado daqui )
Veja também este violino
fonte
Math.round ((new Date (). SetHours (23) - new Date (new Date (). GetFullYear (), 0, 1, 0, 0, 0)) / 1000/86400);
otimiza ainda mais a resposta.
Além disso, alterando setHours (23) ou o last-but-two zero posteriormente para outro valor pode fornecer o dia do ano relacionado a outro fuso horário. Por exemplo, para recuperar da Europa um recurso localizado na América.
fonte
esta é a minha solução
fonte
Fiz um que é legível e fará o truque muito rapidamente, além de lidar com objetos JS Date com fusos horários diferentes.
Incluí alguns casos de teste para fusos horários, DST, segundos bissextos e anos bissextos.
PS ECMA-262 ignora segundos bissextos, ao contrário do UTC. Se você converter isso para uma linguagem que usa UTC real, poderá apenas adicionar 1 a
oneDay
.fonte
Gostaria de fornecer uma solução que faça cálculos somando os dias de cada mês anterior:
Dessa forma, você não precisa gerenciar os detalhes dos anos bissextos e do horário de verão.
fonte
Uma alternativa usando carimbos de data / hora UTC. Além disso, como outros observaram, o dia que indica o primeiro do mês é 1 em vez de 0. No entanto, o mês começa em 0.
fonte
Você pode passar o parâmetro como número de data na
setDate
função:fonte
Isso pode ser útil para aqueles que precisam do dia do ano como uma string e têm o jQuery UI disponível.
Você pode usar o jQuery UI Datepicker:
Embaixo funciona da mesma forma que algumas das respostas já mencionadas (
(date_ms - first_date_of_year_ms) / ms_per_day
):fonte
Para aqueles entre nós que desejam uma solução alternativa rápida.
O tamanho dos meses do ano e a maneira como os anos bissextos funcionam se encaixam perfeitamente em manter nosso tempo no caminho com o sol. Caramba, funciona tão perfeitamente que tudo o que fazemos é apenas ajustar meros segundos aqui e ali . Nosso sistema atual de anos bissextos está em vigor desde 24 de fevereiro de 1582 e provavelmente permanecerá em vigor no futuro próximo.
O DST, no entanto, está muito sujeito a alterações. Pode ser que, daqui a 20 anos, algum país possa compensar o tempo em um dia inteiro ou algum outro extremo para o DST. Um dia inteiro de horário de verão quase certamente nunca acontecerá, mas o horário de verão ainda está muito no ar e indeciso. Portanto, a solução acima é à prova de futuro, além de ser muito rápida.
O trecho de código acima é executado muito rápido. Meu computador pode processar 65536 datas em ~ 52ms no Chrome.
fonte
fonte
Esta é uma solução que evita os problemas de objeto Date e fuso horário, requer que a data de entrada esteja no formato "aaaa-dd-mm". Se você quiser alterar o formato, modifique a função date_str_to_parts:
fonte
Sempre fico preocupado quando misturo matemática com funções de data (é tão fácil perder algum outro detalhe do ano bissexto). Diga que você tem:
Eu sugeriria usar o seguinte, os dias serão salvos em
day
:Não consigo ver nenhuma razão para que isso não funcione bem (e eu não ficaria tão preocupado com as poucas iterações, já que isso não será usado tão intensamente).
fonte
/ * USE ESTE SCRIPT * /
fonte