2011-11-17 88 views
17

如何獲取下面的代碼以便在有一個月的二月份時工作?目前它已經到了一天,然後在確定是否是閏年之前停下來。javascript找到閏年

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

「停止」 怎麼樣?有錯誤嗎? –

+0

它從來沒有評估一年,看看它是否是一個閏年,它直接進入field.focus和field.value,不管它是閏年 –

+0

你的情況看起來有點奇怪 - 因爲他們現在正在寫,你只能檢查'天'的值是29或更大(基於'天== 29'和'天> 28'條款)。我假設你打算寫'day <= 28',但如果是這樣的話,你可以放棄第二個'else if'子句並直接使用'else'子句。在閏年條款中增加一組括號可能會更安全:'if(year%4!= 0 ||(year%100 == 0 && year%400!= 0))' – JW8

回答

99

使用Date objects作爲日期時間的東西比較安全,例如,

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

由於不斷有人詢問究竟如何工作的,它與JS如何計算從年 - 月 - 日(細節here)的日期值做。基本上,它首先計算本月的第一天,然後再增加N-1天。所以,當我們要求在二月二十九日在非閏年,其結果將是2月1日+ 28天= 3月1日:

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

在一個閏年,第1 + 28 =二月二十九日:

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

在上面的代碼中,我將日期設置爲2月29日並查看是否發生翻轉。如果不是(該月仍然是1,即2月),則這是閏年,否則是閏年。

+14

聖牛。什麼黑客。 ':)' –

+1

**現場演示:** http://jsfiddle.net/bJ4cH/ –

+0

非常棒的破解! – 2013-03-28 02:03:02

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

......一個人的減法應該比大多數CPU架構上的比較更快。

+0

如果你需要計算這些每秒1000秒我可能會同意,但是當它們之間的速度差異幾乎可以忽略不計時,可讀性應該超過速度。 –

+0

只是跑了一些速度測試,'新日期'比使用布爾邏輯慢100倍左右(比如說'!((yr%4)||(!(yr%100)&&(yr%400))''' )。你可以說我現在已經把這個可讀性拋出窗口了,但爲了提高速度,但是100次可能是值得的:) –

6

正確和快速:

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

如果你是在一個循環或計數納秒,這是不是通過一個新的Date()對象中運行的一年更快兩個幅度。比較這裏的表現:http://jsperf.com/ily

+2

由於這只是將布爾比較與布爾結果相結合,所以你可以在沒有條件運算的情況下表達它,但是隻是&&'s,||和短路。也快5%左右:http://jsperf.com/ily/6 –

1

我使用這個,因爲我討厭不得不一直提到一月爲0,二月爲1. 對我和PHP和可讀日期,二月= 2。我知道這並不重要,因爲這個數字永遠不會改變,但它讓我的大腦在不同的代碼中思考相同。

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

與使用new Date()這是大約快100倍!

更新:

最新版本採用了底部3位的位測試(是4的倍數),以及全年是16的倍數的檢查(底部4在二進制位爲15)和存在25

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

http://jsperf.com/ily/15

多是比我以前的版本(下同)再次稍快:

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

http://jsperf.com/ily/7

這也是快5%,相比於布羅克已經快有條件的運營商版本。seib

速度測試結果:http://jsperf.com/ily/6

預期的邏輯測試結果:

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

更好的閏年曆史計算。

以下代碼考慮到閏年在儒略曆中引入45BC,並且西方世界的大部分在1582CE採納了公曆,並且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; 
}; 

英國及其殖民地在1752年採用公曆,所以如果你是更盎格魯中心的這個版本是更好的(我們假設英國採用的儒略曆與羅馬征服開始在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); 

這可以幫助你得到,如果輸入的年份是閏年。

truefalse

JavaScript Basics w3resource

1

形式可以很容易地使這個工作從調用momentjs.isLeapYear()

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>