计算一个月的最后一天

IT技术 javascript date
2021-02-04 17:07:04

如果您提供0dayValueDate.setFullYear你上一个月的最后一天:

d = new Date(); d.setFullYear(2008, 11, 0); //  Sun Nov 30 2008

mozilla 上参考了这种行为这是一个可靠的跨浏览器功能还是我应该查看替代方法?

6个回答

var month = 0; // January
var d = new Date(2008, month + 1, 0);
console.log(d.toString()); // last day in January

IE 6:                     Thu Jan 31 00:00:00 CST 2008
IE 7:                     Thu Jan 31 00:00:00 CST 2008
IE 8: Beta 2:             Thu Jan 31 00:00:00 CST 2008
Opera 8.54:               Thu, 31 Jan 2008 00:00:00 GMT-0600
Opera 9.27:               Thu, 31 Jan 2008 00:00:00 GMT-0600
Opera 9.60:               Thu Jan 31 2008 00:00:00 GMT-0600
Firefox 2.0.0.17:         Thu Jan 31 2008 00:00:00 GMT-0600 (Canada Central Standard Time)
Firefox 3.0.3:            Thu Jan 31 2008 00:00:00 GMT-0600 (Canada Central Standard Time)
Google Chrome 0.2.149.30: Thu Jan 31 2008 00:00:00 GMT-0600 (Canada Central Standard Time)
Safari for Windows 3.1.2: Thu Jan 31 2008 00:00:00 GMT-0600 (Canada Central Standard Time)

输出差异是由于实现的差异toString(),而不是因为日期不同。

当然,仅仅因为上面标识的浏览器使用 0 作为上个月的最后一天并不意味着它们会继续这样做,或者没有列出的浏览器会这样做,但它为相信它应该工作的信念提供了可信度在每个浏览器中以相同的方式。

它在 Chrome 48.0.2564.116 上对我不起作用。或许,这种方式已经不再是“标准”了。
2021-03-13 17:07:04
“仅仅因为浏览器……使用 0 作为上个月的最后一天并不意味着他们会继续这样做”。是的,ECMA-262 要求他们这样做。
2021-03-30 17:07:04
这似乎工作得很好。出于好奇,您使用什么在所有这些引擎上运行 javascript?有所有设置或某种工具吗?
2021-04-01 17:07:04
您可以使用 d.getDate() 获取实际日期。
2021-04-01 17:07:04
请注意,使用new Date如此比其他的计算方法要慢得多,它甚至不显示了PERF图表jsperf.com/days-in-month-perf-test/6
2021-04-10 17:07:04

我发现这对我来说是最好的解决方案。让 Date 对象为您计算。

var today = new Date();
var lastDayOfMonth = new Date(today.getFullYear(), today.getMonth()+1, 0);

将 day 参数设置为 0 表示比上个月的最后一天的月份的第一天少一天。

@orad:当心声称某些东西“是最快的”,因为这种方法实际上比某些替代方法慢得多。使用new Date如此慢得多它甚至不显示了PERF图表jsperf.com/days-in-month-perf-test/6
2021-03-12 17:07:04
没关系,我注意到所选答案的建议相同。这是最快和最可靠的方法,无论日历类型如何都有效。例如,如果 Date 实现了格里高利历以外的其他东西,它仍然可以工作。请参阅intldate.codeplex.com以获取 Date 对象的非公历实现示例。
2021-03-29 17:07:04
Native JS Date 仅使用公历。但是您可以使用其他一些实现来模拟它以获得其他日历类型。例如见IntlDate如果您有一个使用 Date 对象创建月度视图的日期选择器,它并不关心它使用的是哪个 Date 实现(本机或模拟),只要它们具有相同的接口即可。因此,使用共享界面允许在不同的日历类型之间切换,而无需知道每个日历上一个月有多少天。
2021-03-30 17:07:04
@TrueBlueAussie 好的。我原以为它更快,因为它是原生的。但你是对的,它并不快。感谢您实际测试它。无论如何,这个解决方案最适合我,因为它简洁易读,并且与所有其他解决方案不同,它不受公历的约束。
2021-04-04 17:07:04
@GoneCoding—— jsperf 链接坏了,你有更新吗?很高兴看到替代方案以及速度差异是否持续存在(或者即使它很重要)。:-)
2021-04-07 17:07:04

我将使用下个月第一天的中间日期,并返回前一天的日期:

int_d = new Date(2008, 11+1,1);
d = new Date(int_d - 1);
我无法重现该错误。这给了我在所有浏览器中正确的日期:today = new Date(); new Date(today.getFullYear(), today.getMonth()+1, 0).toString();
2021-03-22 17:07:04
这会为该月的最后一天创建一个 Date 对象,时间设置为最后一毫秒(即 23:59:59.999)。最好只使用 OP 中的方法并保存额外的步骤和日期对象。
2021-03-26 17:07:04
@TrueBlueAussie 我很确定,如果您的 web 应用程序存在性能问题,您应该从速度以外的其他地方开始寻找new Date:)
2021-03-27 17:07:04
根据ECMAScript 规范,使用您指出的“日期”构造函数是有效的。按照“MakeDay”函数指定的算法,它应该可以很好地处理这个问题。
2021-04-01 17:07:04
这是 IMO 的最佳解决方案。我尝试了接受的答案,但在获取当月的最后一个时它有一些错误。它返回今天的日期。不知道为什么会发生这种情况。
2021-04-07 17:07:04

在计算机术语中,new Date()regular expression解决方案是慢!如果你想要一个超快(和超神秘)的单线,试试这个(假设mJan=1格式)。我不断尝试不同的代码更改以获得最佳性能。

我目前最快的版本:

在查看了这个相关问题Leap year check using bitwise operators(惊人的速度)并发现 25 和 15 幻数代表什么之后,我想出了这个优化的混合答案:

function getDaysInMonth(m, y) {
    return m===2 ? y & 3 || !(y%25) && y & 15 ? 28 : 29 : 30 + (m+(m>>3)&1);
}

鉴于位移,这显然假设您的m&y参数都是整数,因为将数字作为字符串传递会导致奇怪的结果。

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)几乎所有的浏览器。

唯一真正的速度竞争来自@GitaarLab,所以我创建了一个头对头的 JSPerf 供我们测试:http ://jsperf.com/days-in-month-head-to-head/5


它基于我的闰年答案在这里工作:javascript to findleap year this answer here Leap year check using bitwise operators(惊人的速度)以及以下二进制逻辑。

二进制月份的快速课程:

如果您以二进制形式解释所需月份 (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个地方转移value>> 3,XOR位与原^ m,看看结果10 在0位使用& 1注意:结果证明+比 XOR ( ^)略快,并且(m >> 3) + m在位 0 中给出相同的结果。

JSPerf 结果http : //jsperf.com/days-in-month-perf-test/6

@TrueBlueAussie:我只想向未来的读者指出我们的更多信息宝藏(我将我们的答案链接起来,以便任何关心或想要再次尝试的人都可以查看我们的编辑历史,了解我们何时做了什么以及为什么)。我仍然记得我们一整天的比赛!:)我发布的第一个答案版本确实有一组不需要的括号,这些括号被删除了(我把它归功于你)所以我们可以剃掉一个字符并最终得到这个字符。我仍然感谢那有趣的一天,干杯!
2021-03-29 17:07:04
@GitaarLAB:正如您所知,您已经提到过,这与您的从未完全相同。彼此算法的增量更新与“原始算法”不同。我也为这个答案付出了很多努力:P
2021-03-30 17:07:04
请注意ym变量必须是整数而不是字符串!它会导致错误的计算,例如二月它返回 30。我不得不使用parseInt()函数来使它工作。
2021-04-02 17:07:04

我的同事偶然发现了以下可能是一个更简单的解决方案

function daysInMonth(iMonth, iYear)
{
    return 32 - new Date(iYear, iMonth, 32).getDate();
}

盗自 http://snippets.dzone.com/posts/show/2099

月份从零开始,即 Jan = 0。与 getMonth() 相同。
2021-03-29 17:07:04
Nigel 将其修改为更简洁的解决方案。看他的帖子。
2021-04-03 17:07:04