在计算机方面,new Date() 和 regular expression 解决方案很慢!如果你想要一个超快速(和超神秘)的单线,试试这个(假设 m根据问题采用Jan=1 格式):
唯一真正的速度竞争来自@GitaarLab,所以我创建了一个面对面的 JSPerf 供我们测试:http://jsperf.com/days-in-month-head-to-head/5
我不断尝试不同的代码更改以获得最佳性能。
当前版本
在查看了这个相关问题 Leap year check using bitwise operators (amazing speed) 并发现 25 和 15 幻数代表什么之后,我想出了这个经过优化的混合答案:
function getDaysInMonth(m, y) {
return m===2 ? y & 3 || !(y % 25) && y & 15 ? 28 : 29 : 30 + (m +(m >> 3) & 1);
}
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);
}
这个删除了所有不必要的括号:
function getDaysInMonth2(m, y) {
return m === 2 ? !(y % 4 || !(y % 100) && (y % 400)) ? 29 : 28 : 30 + (m + (m >> 3) & 1);
}
这个是 + 比 XOR (^) 快一点
function getDaysInMonth(m, y) {
return (m === 2) ? (!((y % 4) || (!(y % 100) && (y % 400))) ? 29 : 28) : 30 + ((m + (m >> 3)) & 1);
}
这是我最初的尝试:
function getDaysInMonth(m, y) {
return m == 2 ? (!((y % 4) || (!(y % 100) && (y % 400))) ? 29 : 28) : (30 + ((m >> 3 ^ m) & 1));
}
它的工作原理基于我的闰年答案:javascript to find leap year 这个答案在这里Leap year check using bitwise operators (amazing speed) 以及以下二进制逻辑。
二元月速成课:
如果您解释所需月份的索引(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
这意味着您可以将值与 >> 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 年到第 4000 年所有年份的所有月份:http://jsfiddle.net/TrueBlueAussie/8Lmpnpz4/6/。除了@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];
}
JSPerf: http://jsperf.com/days-in-month-head-to-head/5