2011-11-17 19 views
17

¿Cómo puedo obtener el siguiente código para trabajar cuando tengo un mes de febrero? Actualmente está llegando al día y luego se detiene antes de llegar al si para determinar si es un año bisiesto.javascript para encontrar el año bisiesto

if (month == 2) { 
    if (day == 29) { 
     if (year % 4 != 0 || year % 100 == 0 && year % 400 != 0) { 
      field.focus(); 
      field.value = month +'/' + ''; 
     } 
    } 
    else if (day > 28) { 
     field.focus(); 
      field.value = month +'/' + ''; 
    } 
} 
+0

"Parada" ¿cómo? Hay un error? –

+0

nunca evalúa el año para ver si es un año bisiesto que va directamente al campo. Foco y campo. Valora si es un año bisiesto o no –

+0

Sus condiciones se ven un poco raras, ya que actualmente están escritas, solo verifica 'día' para valores de 29 o mayores (basado en las cláusulas' day == 29' y 'day> 28' if). Supongo que quisiste escribir 'día <= 28 ', pero si ese es el caso, podrías soltar la segunda cláusula' else if' y usar una cláusula 'else' directamente. También podría ser más seguro agregar un conjunto adicional de paréntesis a la cláusula de su año bisiesto: 'if (year% 4! = 0 || (year% 100 == 0 && year% 400! = 0))' – JW8

Respuesta

99

Es más seguro utilizar Date objects de fecha y hora para la materia, por ejemplo,

isLeap = new Date(year, 1, 29).getMonth() == 1 

Puesto que la gente sigue preguntando acerca de cómo exactamente funciona esto, esto tiene que ver con la forma en JS calcula el valor de fecha de año-mes-día (detalles here). Básicamente, primero calcula el primero del mes y luego agrega N -1 días. Así que cuando estamos pidiendo el 29 Feb en un año no bisiesto, el resultado será la primera Feb + 28 días = 1 de marzo:

> new Date(2015, 1, 29) 
< Sun Mar 01 2015 00:00:00 GMT+0100 (CET) 

En un año bisiesto, el 1 + 28 = 29o Feb :

> new Date(2016, 1, 29) 
< Mon Feb 29 2016 00:00:00 GMT+0100 (CET) 

En el código anterior, configuré la fecha al 29 de febrero y observo si hubo una transferencia. Si no (el mes sigue siendo 1, es decir, febrero), este es un año bisiesto, de lo contrario no es un salto.

+14

Holy cow. Qué hack. ':)' –

+1

** Demostración en vivo: ** http://jsfiddle.net/bJ4cH/ –

+0

¡gran hack! –

5
isLeap = !(new Date(year, 1, 29).getMonth()-1) 

... restar por uno debe funcionar incluso más rápido que comparar en la mayoría de las arquitecturas de CPU.

+0

Si tuviera que calcular miles de estos por segundo, podría estar de acuerdo, sin embargo, la legibilidad debería superar la velocidad cuando la diferencia de velocidad en cuestión es prácticamente insignificante entre ellos. –

+0

Acaba de ejecutar algunas pruebas de velocidad y 'nueva fecha' es alrededor de 100 veces más lenta que usando lógica booleana (diga algo como'! ((Yr% 4) || (! (Yr% 100) && (año 400))) ')Podrías decir que ahora he lanzado la legibilidad por la ventana con esta por el bien de la velocidad, pero 100 veces puede valer la pena :) –

6

correcta y rápida:

ily = function(yr) { return (yr%400)?((yr%100)?((yr%4)?false:true):false):true; } 

Si se encuentra en un bucle o contar los nanosegundos, esto es dos magnitudes más rápido que el funcionamiento de su año a través de un nuevo() objeto Date. Compare el rendimiento aquí: http://jsperf.com/ily

+2

Como esto es solo la combinación de las comparaciones booleanas con los resultados booleanos, puedes expresar esto sin los operadores con solo && 's, || y cortocircuito. También un 5% más rápido: http://jsperf.com/ily/6 –

1

Utilizo esto porque odio tener que seguir refiriéndome a enero como 0 y febrero como 1. Para mí y PHP y las fechas de lectura, febrero = 2. Sé que realmente no importa, ya que el número nunca cambia, pero solo hace que mi cerebro piense lo mismo en diferentes códigos.

var year = 2012; 
var isLeap = new Date(year,2,1,-1).getDate()==29; 
9

comparación con el uso new Date() se trata es de alrededor de 100 veces más rápido!

Actualización:

Esta última versión utiliza una prueba poco de los 3 bits inferiores (¿es un múltiplo de 4), así como un cheque para el año ser un múltiplo de 16 (parte inferior 4 bits en binario es 15) y de ser un múltiplo de 25.

ily = function(y) {return !(y & 3 || !(y % 25) && y & 15);}; 

http://jsperf.com/ily/15

es ligeramente más rápido de nuevo que mi versión anterior (abajo):

ily = function(yr) {return !((yr % 4) || (!(yr % 100) && (yr % 400)));}; 

http://jsperf.com/ily/7

También es un 5% más rápido, en comparación con la versión operador ya rápido condicionada por Broc.SEIB

velocidad Resultados del ensayo: http://jsperf.com/ily/6

esperados resultados de las pruebas de lógica:

alert(ily(1900)); // false 
alert(ily(2000)); // true 
alert(ily(2001)); // false 
alert(ily(2002)); // false 
alert(ily(2003)); // false 
alert(ily(2004)); // true 
alert(ily(2100)); // false 
alert(ily(2400)); // true 
0

mejor cálculo histórico de los años bisiestos.

El siguiente código tiene en cuenta que los años bisiestos se introdujeron en 45BC con el calendario juliano, y que la mayoría del mundo occidental adoptó el calendario gregoriano en 1582CE, y que 0CE = 1BC.

isLeap = function(yr) { 
    if (yr > 1582) return !((yr % 4) || (!(yr % 100) && (yr % 400))); 
    if (yr >= 0) return !(yr % 4); 
    if (yr >= -45) return !((yr + 1) % 4); 
    return false; 
}; 

Gran Bretaña y sus colonias adoptaron el calendario gregoriano en 1752, por lo que si usted está más centrada en el Anglo esta versión es mejor (Asumiremos Gran Bretaña adoptó el calendario Juliano con la conquista romana a partir de 43CE).

isLeap = function(yr) { 
    if (yr > 1752) return !((yr % 4) || (!(yr % 100) && (yr % 400))); 
    if (yr >= 43) return !(yr % 4); 
    return false; 
}; 
0
year = window.prompt("Input a Year : "); 
x = (year % 100 === 0) ? (year % 400 === 0) : (year % 4 === 0); 
console.log(x); 

esto puede ayudar a conseguir si el año de entrada es un año bisiesto o no.

en forma de true o false

JavaScript Basics w3resource

1

Usted puede hacer que esto funcione llamando .isLeapYear() de momentjs:

var notLeapYear = moment('2018-02-29') 
 
console.log(notLeapYear.isLeapYear()); // false 
 

 
var leapYear = moment('2020-02-29') 
 
console.log(leapYear.isLeapYear()); // true
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.21.0/moment.min.js"></script>

Cuestiones relacionadas