¿Cómo uso javascript para calcular el día del año, de 1 a 366? Por ejemplo:
- El 3 de enero debería ser el 3 .
- El 1 de febrero debería ser 32 .
javascript
Kirk Woll
fuente
fuente
var days = new Date().getFullYear() % 4 == 0 ? 366 : 365;
Respuestas:
Siguiendo la edición de OP:
Editar: El código anterior fallará cuando
now
sea una fecha entre el 26 de marzo y el 29 de octubre ynow
la hora sea antes de la 1AM (por ejemplo, 00:59:59). Esto se debe a que el código no tiene en cuenta el horario de verano. Deberías compensar esto:fuente
Math.floor
constantemente me dio un resultado de 1 día menos de lo esperado después de cierto día de abril.Math.ceil
funcionó como se esperaba, pero he visto que se recomienda que use enMath.round
lugar de cualquiera.new Date(2014, 0, 1)
, y nonew Date(2014, 0, 0)
como lo tiene aquí. ¿Es eso intencional? Quizás eso es lo que explica estar fuera por un día comonew Date(2014, 0, 0)
volverá12/31/2013
..setUTCHours
yDate.UTC()
para una solución más confiable.ceil
lugar defloor
, esto le dará un sistema de numeración donde 1 de enero = 1. Si quiere 1 de enero = 0 (comofloor
le daría), simplemente reste 1 de su resultado final.var diff = now - start + (start.getTimezoneOffset() - now.getTimezoneOffset()) * 60 * 1000;
Esto funciona con los cambios del horario de verano en todos los países (el "mediodía" anterior no funciona en Australia):
fuente
getDay()
debe cambiarse agetDate()
. El primero devuelve el día de la semana (0 = domingo..6 = sábado), no el día.Me parece muy interesante que nadie haya considerado usar UTC ya que no está sujeto a DST. Por tanto, propongo lo siguiente:
Puede probarlo con lo siguiente:
Qué salidas para el año bisiesto 2016 (verificado usando http://www.epochconverter.com/days/2016 ):
fuente
function doyToDate(doy, year) { return new Date(year, 0, doy); }
new Date(8640000000000000)
, que aún es menor queNumber.MAX_SAFE_INTEGER
. vea esta respuesta: stackoverflow.com/a/11526569/18511fuente
Afortunadamente, esta pregunta no especifica si se requiere el número del día actual , dejando espacio para esta respuesta.
Además, algunas respuestas (también en otras preguntas) tenían problemas de años bisiestos o usaban el objeto Date. Aunque javascript
Date object
cubre aproximadamente 285616 años (100,000,000 días) a ambos lados del 1 de enero de 1970, estaba harto de todo tipo de inconsistencias de fechas inesperadas en diferentes navegadores (especialmente del año 0 al 99). También tenía curiosidad por saber cómo calcularlo.Así que escribí un algoritmo simple y, sobre todo, pequeño para calcular el día correcto ( Proleptic Gregorian / Astronomical / ISO 8601: 2004 (cláusula 4.3.2.1), por lo que el año
0
existe y es un año bisiesto y se admiten años negativos ) del año basado en año , mes y día .Tenga en cuenta que en la
AD/BC
notación, el año 0 AD / BC no existe: en su lugar, el año1 BC
es el año bisiesto! SI necesita tener en cuenta la notación BC, entonces simplemente reste un año del valor anual (de lo contrario positivo) primero.Modifiqué (para javascript) el algoritmo de cortocircuito bitmask-modulo leapYear y se me ocurrió un número mágico para hacer una búsqueda bit a bit de compensaciones (que excluye jan y feb, por lo que necesita 10 * 3 bits (30 bits es menos que 31 bits, por lo que podemos guardar con seguridad otro carácter en el desplazamiento de bits en lugar de
>>>
)).Tenga en cuenta que ni el mes ni el día pueden serlo
0
. Eso significa que si necesita esta ecuación solo para el día actual (alimentándola usando.getMonth()
) solo necesita quitar la--
de--m
.Tenga en cuenta que esto asume una fecha válida (aunque la verificación de errores es solo algunos caracteres más).
Aquí está la versión con la validación de rango correcta .
Nuevamente, una línea, pero la dividí en 3 líneas para facilitar la lectura (y la siguiente explicación).
La última línea es idéntica a la función anterior, sin embargo, el algoritmo leapYear (idéntico) se mueve a una sección de cortocircuito anterior (antes del cálculo del número de días), porque también es necesario saber cuántos días tiene un mes en un año (bisiesto) dado.
La línea central calcula el número de compensación correcto (para el número máximo de días) para un mes dado en un año (bisiesto) dado usando otro número mágico: dado que
31-28=3
y3
es solo 2 bits, luego12*2=24
bits, podemos almacenar los 12 meses. Como la suma puede ser más rápida que la resta, sumamos el desplazamiento (en lugar de restarlo de31
). Para evitar una rama de decisión de año bisiesto para febrero, modificamos ese número de búsqueda mágico sobre la marcha.Eso nos deja con la primera línea (bastante obvia): verifica que el mes y la fecha estén dentro de los límites válidos y nos asegura un
false
valor de retorno en el error de rango (tenga en cuenta que esta función tampoco debería poder devolver 0, porque el 1 de enero de 0000 sigue siendo el día 1.), que proporciona un fácil comprobación de errores:if(r=dayNo(/*y, m, d*/)){}
.Si se usa de esta manera (donde el mes y el día pueden no serlo
0
), entonces se puede cambiar--m>=0 && m<12
am>0 && --m<12
(guardar otro carácter).La razón por la que escribí el fragmento en su forma actual es que para los valores de mes basados en 0, uno solo necesita eliminar el
--
de--m
.Extra:
Tenga en cuenta que no utilice el algoritmo de este día por mes si solo necesita el máximo de días por mes. En ese caso, hay un algoritmo más eficiente (porque solo necesitamos leepYear cuando el mes es febrero) que publiqué como respuesta a esta pregunta: ¿Cuál es la mejor manera de determinar la cantidad de días en un mes con javascript? .
fuente
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
si se quita el--
de--m
. EDITAR Entonces, haría (para una 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
años a partir de ahora, js probablemente estará un poco desactualizado.:)
Pero hasta entonces, al menos dará resultados predecibles y consistentes jaja. EDITAR , solo por el bien de la teoría, utilizando el algoritmo todo módulo convencional más lento para el año bisiesto, el rango se puede extender a 2 ^ 53. El algoritmo de búsqueda de meses no es el factor limitante.Si no desea reinventar la rueda, puede usar la excelente biblioteca date- fns (node.js):
fuente
Bueno, si te entiendo correctamente, quieres 366 en un año bisiesto, 365 de lo contrario, ¿verdad? Un año es bisiesto si es divisible uniformemente por 4, pero no por 100, a menos que también sea divisible por 400:
Editar después de la actualización:
En ese caso, no creo que haya un método incorporado; necesitarás hacer esto:
(Sí, en realidad hice eso sin copiar ni pegar. Si hay una manera fácil, me enojaré)
fuente
:)
Esta es una forma sencilla de encontrar el día actual del año, y debería contabilizar los años bisiestos sin ningún problema:
Javascript:
Math.round((new Date().setHours(23) - new Date(new Date().getYear()+1900, 0, 1, 0, 0, 0))/1000/60/60/24);
Javascript en Google Apps Script:
Math.round((new Date().setHours(23) - new Date(new Date().getYear(), 0, 1, 0, 0, 0))/1000/60/60/24);
La acción principal de este código es encontrar el número de milisegundos que han transcurrido en el año actual y luego convertir este número en días. La cantidad de milisegundos que han transcurrido en el año en curso se puede encontrar restando la cantidad de milisegundos del primer segundo del primer día del año en curso, que se obtiene con
new Date(new Date().getYear()+1900, 0, 1, 0, 0, 0)
(Javascript) onew Date(new Date().getYear(), 0, 1, 0, 0, 0)
(Google Apps Script), de los milisegundos de la hora 23 del día actual, que se encontró connew Date().setHours(23)
. El propósito de establecer la fecha actual en la hora 23 es garantizar que el día del año se redondea correctamente porMath.round()
.Una vez que tenga la cantidad de milisegundos del año actual, puede convertir este tiempo en días dividiendo por 1000 para convertir milisegundos en segundos, luego dividiendo por 60 para convertir segundos en minutos, luego dividiendo por 60 para convertir minutos en horas. y finalmente dividir por 24 para convertir las horas en días.
Nota: esta publicación se editó para tener en cuenta las diferencias entre JavaScript y JavaScript implementados en Google Apps Script. Además, se agregó más contexto para la respuesta.
fuente
.setHours
método en el primer objeto de fecha y especifiqué la hora del día con el segundo objeto de fecha, un cambio de 1 hora desde el horario de verano no afectará las horas de los objetos de fecha utilizados en este cálculo.Creo que esto es más sencillo:
fuente
Este método tiene en cuenta el problema de la zona horaria y el horario de verano
(tomado de aquí )
Ver también este violín
fuente
Math.round ((nueva fecha (). SetHours (23) - nueva fecha (nueva fecha (). GetFullYear (), 0, 1, 0, 0, 0)) / 1000/86400);
optimiza aún más la respuesta.
Además, al cambiar setHours (23) o el último cero menos dos más adelante a otro valor, puede proporcionar el día del año relacionado con otra zona horaria. Por ejemplo, para recuperar de Europa un recurso ubicado en América.
fuente
esta es mi solucion
fuente
He creado uno que es legible y funcionará muy rápidamente, además de manejar objetos JS Date con zonas horarias dispares.
He incluido bastantes casos de prueba para zonas horarias, DST, segundos bisiestos y años bisiestos.
PS ECMA-262 ignora los segundos intercalares, a diferencia de UTC. Si tuviera que convertir esto a un idioma que usa UTC real, podría simplemente agregar 1 a
oneDay
.fuente
Me gustaría proporcionar una solución que haga cálculos sumando los días de cada mes anterior:
De esta manera, no tiene que administrar los detalles de los años bisiestos y el horario de verano.
fuente
Una alternativa que usa marcas de tiempo UTC. Además, como otros señalaron, el día que indica el primer mes es 1 en lugar de 0. Sin embargo, el mes comienza en 0.
fuente
Puede pasar el parámetro como número de fecha en la
setDate
función:fuente
Esto podría ser útil para aquellos que necesitan el día del año como una cadena y tienen jQuery UI disponible.
Puede usar jQuery UI Datepicker:
Debajo funciona de la misma manera que algunas de las respuestas ya mencionadas (
(date_ms - first_date_of_year_ms) / ms_per_day
):fuente
Para aquellos entre nosotros que quieren una solución alternativa rápida.
El tamaño de los meses del año y la forma en que funcionan los años bisiestos encajan perfectamente para mantener nuestro tiempo encaminado con el sol. Demonios, funciona tan perfectamente que todo lo que hacemos es ajustar unos segundos aquí y allá . Nuestro sistema actual de años bisiestos ha estado en vigor desde el 24 de febrero de 1582. y probablemente permanecerá en vigor en el futuro previsible.
Sin embargo, el horario de verano está muy sujeto a cambios. Puede ser que dentro de 20 años, algún país pueda compensar el tiempo por un día completo o algún otro extremo para el horario de verano. Es casi seguro que nunca sucederá un día completo de DST, pero el DST sigue estando muy en el aire e indeciso. Por lo tanto, la solución anterior está preparada para el futuro, además de ser muy, muy rápida.
El fragmento de código anterior se ejecuta muy rápido. Mi computadora puede procesar 65536 fechas en ~ 52 ms en Chrome.
fuente
fuente
Esta es una solución que evita los problemas problemáticos con el objeto Date y la zona horaria, requiere que la fecha de entrada tenga el formato "aaaa-dd-mm". Si desea cambiar el formato, modifique la función date_str_to_parts:
fuente
Siempre me preocupa cuando se mezclan las matemáticas con las funciones de fecha (es muy fácil pasar por alto algún otro detalle del año bisiesto). Di que tienes:
Sugeriría usar lo siguiente, los días se guardarán en
day
:No veo ninguna razón por la que esto no funcionaría bien (y no estaría tan preocupado por las pocas iteraciones ya que esto no se usará tan intensamente).
fuente
/ * USE ESTE GUIÓN * /
fuente