Jam*_*mes 51
function getDaysInMonth(m, y) {
return /8|3|5|10/.test(--m)?30:m==1?(!(y%4)&&y%100)||!(y%400)?29:28:31;
}
Run Code Online (Sandbox Code Playgroud)
Cal*_*leb 45
试试这个:
function numberOfDays(year, month) {
var d = new Date(year, month, 0);
return d.getDate();
}
Run Code Online (Sandbox Code Playgroud)
因为闰年你也需要过年.
Bru*_*uno 13
喜欢詹姆斯的回答.对那些感兴趣的人稍微重新格式化.
function getDaysInMonth(m, y)
{
// months in JavaScript start at 0 so decrement by 1 e.g. 11 = Dec
--m;
// if month is Sept, Apr, Jun, Nov return 30 days
if( /8|3|5|10/.test( m ) ) return 30;
// if month is not Feb return 31 days
if( m != 1 ) return 31;
// To get this far month must be Feb ( 1 )
// if the year is a leap year then Feb has 29 days
if( ( y % 4 == 0 && y % 100 != 0 ) || y % 400 == 0 ) return 29;
// Not a leap year. Feb has 28 days.
return 28;
}
Run Code Online (Sandbox Code Playgroud)
在这里小提琴
大家都知道,计数Chuck的一拳击败单纯的诗歌中的任何一天一周一个月..

如果你不能编译和运行(如诗歌),那么请继续阅读.
没有正则表达式和减2 模数余数运算,也没有闰年问题或Date-object.
虽然javascript Date object在1970年1月1日的两边都覆盖了大约285616年(100,000,000天),但我厌倦了不同浏览器中的各种意外日期不一致(最明显的是0到99年).我也很好奇如何计算它.
所以我写了一个简单的,最重要的,小算法(轻松击败詹姆斯的答案)来计算正确的(Proleptic Gregorian/Astronomical/ISO 8601:2004(第4.3.2.1节),所以年份0存在并且是闰年和负数年支持)给定月份和年份的天数.
它使用短路位掩码 - 模数leapYear算法(略微修改为js)和常见的mod- 8月算法(再次修改以获得最短路径).
请注意,在AD/BC表示法中,第0年AD/BC不存在:相反年份1 BC是闰年!
如果您需要考虑BC符号,那么只需减去一年(否则为正)年值!(或者将年份减去1进一步的年度计算.)
function daysInMonth(m, y){
return m===2?y&3||!(y%25)&&y&15?28:29:30+(m+(m>>3)&1);
}Run Code Online (Sandbox Code Playgroud)
<!-- example for the snippet -->
<input type="text" placeholder="enter year" onblur="
for( var r='', i=0, y=+this.value
; 12>i++
; r+= 'Month: ' + i + ' has ' + daysInMonth(i, y) + ' days<br>'
);
this.nextSibling.innerHTML=r;
" /><div></div>Run Code Online (Sandbox Code Playgroud)
注意,月份必须是1个(根据要求提出的问题)!
注意,这是一个不同的算法,然后我在我的Javascript中使用的幻数查找计算一年中的日期(1 - 366)答案,因为这里闰年的额外分支仅在2月需要.
编辑(历史):
我解除了修改后的mod8个月算法
return(m===2?y&3||!(y%25)&&y&15?28:29:30)+(m+(m>>3)&1); //algo 1
Run Code Online (Sandbox Code Playgroud)
到三元并删除了现在不需要的外括号(好的调用,TrueBlueAussie):
return m===2?y&3||!(y%25)&&y&15?28:29:30+(m+(m>>3)&1); //algo 2
Run Code Online (Sandbox Code Playgroud)
经过严格的测试后,结果证明这是最快的算法(感谢TrueBlueAussie的测试,我为缓存jsperf设置进行了测试).我们猜测这比我的(更短且看似更快)算法3(下面的神奇数字按位查找)更快的原因是,现代浏览器可能可以预先优化常量位移m>>3.
我想......好吧......"为什么我不再这样做?:"
return m===2?y&3||!(y%25)&&y&15?28:29:30+(5546>>m&1); // algo 3
Run Code Online (Sandbox Code Playgroud)
它使用一个"幻数"来进行偏移的简单逐位查找:
DNOSAJJMAMFJ* = Months (right to left) CBA9876543210 = Month === bit position in hex (we never use pos 0: January is 1) 1010110101010 = offset from 30 = binary === 5546 decimal
13位小于31位,因此我们可以安全地在bitshift上保存另一个字符而不是>>>(因为我们不需要强制无符号32位).
这消除了一个内存调用(var m),一个加法和一个优先级!(它的一个字符更短)
有人会认为:显然这3个额外的优化击败了我的第一个/第二个算法(正如TrueBlueAussie评论的那样,已经是最快的了)......
但正如我已经提到的,事实证明这个(算法3)在现代并不快浏览器(我知道,相当意外),我们认为这是因为引擎无法再优化比特移位.
我会把它留在这里,也许有一天它会更快,谁知道..
事实证明我的算法2是最快的(除了TrueBlueAussie的完整2D阵列,当然,虽然需要更多的内存并且仍然需要快速的算法来构建它的客户端),我遵循TrueBlueAussie的建议来恢复我使用算法的答案2.
我仍然有一个爆炸合作,并感谢重新审视我的答案!
在计算机术语中,new Date()和regular expression解决方案是慢!如果你想要一个超高速(和超神秘)的一行,试试这个(假设m是Jan=1格式按问题):
唯一真正的速度竞争来自@GitaarLab,所以我创建了一个头对头的JSPerf供我们测试:http://jsperf.com/days-in-month-head-to-head/5
我一直在尝试不同的代码更改以获得最佳性能.
当前版本
在查看这个相关问题闰年检查使用按位运算符(惊人的速度)并发现25和15幻数代表什么,我已经提出了这种优化的答案混合:
function getDaysInMonth(m, y) {
return m===2 ? y & 3 || !(y % 25) && y & 15 ? 28 : 29 : 30 + (m +(m >> 3) & 1);
}
Run Code Online (Sandbox Code Playgroud)
JSFiddle: http ://jsfiddle.net/TrueBlueAussie/H89X3/22/
JSPerf结果: http ://jsperf.com/days-in-month-head-to-head/5
出于某种原因,(m+(m>>3)&1)是不是更有效(5546>>m&1)上几乎所有的浏览器.
之前的版本:
这个!通过反转值(略微增加)删除了一个测试:
function getDaysInMonth(m, y) {
return m === 2 ? (y % 4 || !(y % 100) && (y % 400)) ? 28 : 29 : 30 + (m + (m >> 3) & 1);
}
Run Code Online (Sandbox Code Playgroud)
这个删除了任何不必要的括号:
function getDaysInMonth2(m, y) {
return m === 2 ? !(y % 4 || !(y % 100) && (y % 400)) ? 29 : 28 : 30 + (m + (m >> 3) & 1);
}
Run Code Online (Sandbox Code Playgroud)
这个+比XOR(^)快一点
function getDaysInMonth(m, y) {
return (m === 2) ? (!((y % 4) || (!(y % 100) && (y % 400))) ? 29 : 28) : 30 + ((m + (m >> 3)) & 1);
}
Run Code Online (Sandbox Code Playgroud)
这是我最初的尝试:
function getDaysInMonth(m, y) {
return m == 2 ? (!((y % 4) || (!(y % 100) && (y % 400))) ? 29 : 28) : (30 + ((m >> 3 ^ m) & 1));
}
Run Code Online (Sandbox Code Playgroud)
它基于我的闰年答案在这里工作:javascript找到闰年这个答案在这里闰年检查使用按位运算符(惊人的速度)以及以下二进制逻辑.
二进制月的快速教训:
如果您以二进制形式解释所需月份(Jan = 1)的索引,您会注意到31天的月份有3位清除和位0设置,或位3设置和位0清除.
Jan = 1 = 0001 : 31 days
Feb = 2 = 0010
Mar = 3 = 0011 : 31 days
Apr = 4 = 0100
May = 5 = 0101 : 31 days
Jun = 6 = 0110
Jul = 7 = 0111 : 31 days
Aug = 8 = 1000 : 31 days
Sep = 9 = 1001
Oct = 10 = 1010 : 31 days
Nov = 11 = 1011
Dec = 12 = 1100 : 31 days
Run Code Online (Sandbox Code Playgroud)
这意味着您可以将值移位3个位置>> 3,将位与原始位置进行异或,^ m并查看结果是否在位1或0 0位置使用& 1.注意:事实证明它+比XOR(^)略快,并且(m >> 3) + m在第0位给出相同的结果.
JSPerf结果:http://jsperf.com/days-in-month-perf-test/6(比接受的答案快23倍).
更新:我对前两个答案+最新(@ James,@ Caleb和@GitaarLAB)进行了对比,以确保它们给出了一致的结果,并且所有4个从1年到1年的所有年份都返回相同的值4000:http://jsfiddle.net/TrueBlueAussie/8Lmpnpz4/6/.除了@Caleb之外,除了@Caleb之外,0年级是相同的.
另一个更新:
如果绝对速度是唯一的目标,并且您不介意浪费内存,那么将结果存储在给定的年度内,在二维表中可能是最快的方式:
function DIM(m, y) { //TrueBlueAussie
return m===2?(y%4||!(y%100)&&(y%400))?28:29:30+(m+(m>>3)&1);
}
array = new Array(4000);
for (var y = 1; y < 4000; y++){
array[y] = [];
for (var m = 1; m < 13; m++)
{
array[y][m] = DIM(m, y);
}
}
// This just does a lookup into the primed table - wasteful, but fast
function getDaysInMonth2(m, y){
return array[y][m];
}
Run Code Online (Sandbox Code Playgroud)
JSPerf: http ://jsperf.com/days-in-month-head-to-head/5
| 归档时间: |
|
| 查看次数: |
30514 次 |
| 最近记录: |