2011-11-17 90 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>