用JavaScript计算每月的最后一天


277

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

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

mozilla上有对此行为的引用。这是可靠的跨浏览器功能还是我应该考虑其他方法?


您不是指指定的月份的最后一天吗?11月有30天,10月有31天。
克里斯·塞拉

16
月在JavaScript中是从零开始的,所以11月是12月
Greg,

2
@TheCloudlessSky-在控制台中尝试...(2008,11,0)是12月的第0天,因此是11月的最后一天– 2011

@Ken-是的-我不知道那里有一个“ 0”:)...太早了。
TheCloudlessSky's

Answers:


424
var month = 0; // January
var d = new Date(2008, month + 1, 0);
alert(d); // 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用作上个月的最后一天,并不意味着它们会继续这样做,或者未列出的浏览器仍会这样做,但是这使人们相信它应该可以正常工作。在每个浏览器中都一样。


19
这似乎工作得很好。出于好奇,您正在使用什么在所有这些引擎上运行javascript?得到了所有设置或某种工具?
neonski

5
您可以使用d.getDate()获取实际日期。
rynop 2012年

35
“仅仅因为浏览器……将0用作上个月的最后一天,并不意味着它们会继续这样做。” 是的,ECMA-262要求这样做。
RobG 2014年

3
请注意,使用new Date如此远远低于其他的计算方法,它甚至不显示了PERF图表jsperf.com/days-in-month-perf-test/6
飘编码

4
在Chrome 48.0.2564.116上对我不起作用。也许,这种方式已不再是“标准”。
xarlymg89 '16

77

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

int_d = new Date(2008, 11+1,1);
d = new Date(int_d - 1);

根据ECMAScript规范,您所指出的使用“日期”构造函数是有效的。按照“ MakeDay”函数指定的算法,它应该可以很好地处理该问题。
Pablo Cabrera

1
这是IMO的最佳解决方案。我尝试了接受的答案,但是在获取当前月份的最后一个时存在一些错误。它返回今天的日期。不知道为什么会这样。
Gogol 2014年

1
我无法复制该错误。这为我提供了所有浏览器的正确日期:today = new Date(); new Date(today.getFullYear(), today.getMonth()+1, 0).toString();
orad 2014年

这将为该月的最后一天创建一个Date对象,并将时间设置为最后毫秒(即23:59:59.999)。最好只在OP中使用该方法并保存多余的步骤和Date对象。
RobG 2014年

@RobG:我同意!尽管我的解决方案可能更容易理解,因为我认为在该月的最后一天使用0的概念有些陈旧。
karlipoppins

72

我发现这是最适合我的解决方案。让Date对象为您计算它。

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

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


1
没关系,我注意到所选答案提出了相同的建议。这是最快,最可靠的方法,并且不管日历的类型如何都可以工作。例如,如果Date实现了除公历之外的其他功能,它将仍然有效。请参见intldate.codeplex.com,以获取Date对象的非格雷戈式实现示例。
orad 2013年

1
@orad:提防声称“最快”,因为这种方法实际上比某些替代方法要慢得多。使用new Date如此慢得多它甚至不显示了PERF图表jsperf.com/days-in-month-perf-test/6
飘编码

@TrueBlueAussie OK。我以为它是本地的所以速度更快。但是你是对的,这并不快。感谢您实际测试。无论如何,此解决方案最适合我,因为它简洁明了且可读,并且与所有其他解决方案不同,它不受公历约束。
orad 2015年

“不同于所有其他解决方案都不受公历约束”!该算法返回的值与我的1-4000年相同。jsfiddle.net/2973x9m3/3您声称这将支持(使用)哪些其他日期范围?:)
Gone Coding 2015年

1
本机JS日期仅使用公历。但是您可以使用其他实现对它进行模拟,以获得其他日历类型。例如,请参见IntlDate。如果您有一个使用Date对象创建月视图的日期选择器,则只要它们具有相同的接口,就不必在意使用哪个Date实现(本机或模拟)。因此,使用共享界面可以在不同的日历类型之间进行切换,而不必知道每个日历上一个月中有多少天。
orad 2015年

25

在计算机术语中,new Date()regular expression解决方案是慢!如果您想要一种超快速(且超级神秘)的衬板,请尝试使用此衬板(假设m采用Jan=1格式)。我一直在尝试不同的代码更改以获得最佳性能。

我当前最快的版本:

在查看了相关问题后,使用按位运算符(惊人的速度)检查了year年检查并发现了25和15的幻数表示什么,我提出了以下优化的答案组合:

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

给定位移,这显然假定您的my参数都是整数,因为将数字作为字符串传递会导致奇怪的结果。

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


它基于我在这里的leap年答案而工作:在此处找到此答案的年javascript 使用按位运算符(惊人的速度)以及以下二进制逻辑对check年进行检查

二进制月份的快速课程:

如果您用二进制解释所需月份的索引(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,XOR位与原^ m,看看结果10 在0位使用& 1。注意:结果+比XOR(^)快一点,并且(m >> 3) + m在位0中得到相同的结果。

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



1
@GitaarLAB:您已经提到了一个话题,众所周知,这从来没有与您完全一样。其他算法的增量更新与“原始算法”不同。我也为这个答案付出了很多努力:P
Gone Coding

@TrueBlueAussie:我只想向未来的读者介绍我们的更多信息宝藏(我将我们的答案都链接了起来,以便任何关心或想要再尝试一遍的人都可以查看我们的编辑历史,以了解我们何时以及为何做)。我仍然热切地记得我们整天的比赛!:)我发布的第一个答案版本的确确实有一组不需要的括号,这些括号已删除(为此我记了一下),因此我们可以剃除某个角色并最终得到这个角色。我仍然为那有趣的一天而感恩,干杯!
GitaarLAB 2015年

1
请注意ym变量必须是整数而不是字符串!它会导致错误的计算,例如2月份返回30。我必须使用parseInt()function使其工作。
而是


16

lebreeze提供的解决方案稍作修改:

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

这应该return new Date(iYear, 1 + iMonth, 0).getDate();等同于@lebreeze的解决方案。
Moos

6

我最近不得不做类似的事情,这是我想出的:

/**
* Returns a date set to the begining of the month
* 
* @param {Date} myDate 
* @returns {Date}
*/
function beginningOfMonth(myDate){    
  let date = new Date(myDate);
  date.setDate(1)
  date.setHours(0);
  date.setMinutes(0);
  date.setSeconds(0);   
  return date;     
}

/**
 * Returns a date set to the end of the month
 * 
 * @param {Date} myDate 
 * @returns {Date}
 */
function endOfMonth(myDate){
  let date = new Date(myDate);
  date.setMonth(date.getMonth() +1)
  date.setDate(0);
  date.setHours(23);
  date.setMinutes(59);
  date.setSeconds(59);
  return date;
}

在日期中传递它,它将返回设置为月初或月末的日期。

begninngOfMonth函数是endOfMonth很容易解释的,但是该函数的作用是将月份增加到下个月,然后setDate(0)将日期回滚到上个月的最后一天,这是该功能的一部分。 setDate规范:

https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Date/setDate https://www.w3schools.com/jsref/jsref_setdate.asp

然后,我将小时/分钟/秒设置为一天的结束时间,这样,如果您使用某种期望日期范围的API,就可以捕获最后一天的全部时间。该部分可能超出了原始帖子的要求,但可以帮助其他人寻找类似的解决方案。

编辑:setMilliseconds()如果您想更加精确,也可以加倍努力并设置毫秒。


4

试试这个。

lastDateofTheMonth = new Date(year, month, 0)

例:

new Date(2012, 8, 0)

输出:

Date {Fri Aug 31 2012 00:00:00 GMT+0900 (Tokyo Standard Time)}

5
不过,请记住,月份是从零开始的,因此将“ 8”作为月份实际上是9月,而不是8月。
史蒂夫·J

3

这对我有用。将提供给定年份和月份的最后一天:

var d = new Date(2012,02,0);
var n = d.getDate();
alert(n);

1
注意“ 2”前面的0,它将被解释为八进制。
Walfrat

1

这个很好用:

Date.prototype.setToLastDateInMonth = function () {

    this.setDate(1);
    this.setMonth(this.getMonth() + 1);
    this.setDate(this.getDate() - 1);

    return this;
}

1

这将为您提供当前月份的第一天和最后一天。

如果您需要更改“年份”,请删除d.getFullYear()并设置您的年份。

如果您需要更改“ month”,请删除d.getMonth()并设置您的年份。

var d = new Date();
var days = ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"];
var fistDayOfMonth = days[(new Date(d.getFullYear(), d.getMonth(), 1).getDay())];
	var LastDayOfMonth = days[(new Date(d.getFullYear(), d.getMonth() + 1, 0).getDay())]; 
console.log("First Day :" + fistDayOfMonth); 
console.log("Last Day:" + LastDayOfMonth);
alert("First Day :" + fistDayOfMonth); 
alert("Last Day:" + LastDayOfMonth);


1

试试这个:

function _getEndOfMonth(time_stamp) {
    let time = new Date(time_stamp * 1000);
    let month = time.getMonth() + 1;
    let year = time.getFullYear();
    let day = time.getDate();
    switch (month) {
        case 1:
        case 3:
        case 5:
        case 7:
        case 8:
        case 10:
        case 12:
            day = 31;
            break;
        case 4:
        case 6:
        case 9:
        case 11:
            day = 30;
            break;
        case 2:
            if (_leapyear(year))
                day = 29;
            else
                day = 28;
            break
    }
    let m = moment(`${year}-${month}-${day}`, 'YYYY-MM-DD')
    return m.unix() + constants.DAY - 1;
}

function _leapyear(year) {
    return (year % 100 === 0) ? (year % 400 === 0) : (year % 4 === 0);
}

1

下面的函数给出了该月的最后一天:

function getLstDayOfMonFnc(date) {
  return new Date(date.getFullYear(), date.getMonth(), 0).getDate()
}

console.log(getLstDayOfMonFnc(new Date(2016, 2, 15))) // Output : 29
console.log(getLstDayOfMonFnc(new Date(2017, 2, 15))) // Output : 28
console.log(getLstDayOfMonFnc(new Date(2017, 11, 15))) // Output : 30
console.log(getLstDayOfMonFnc(new Date(2017, 12, 15))) // Output : 31

同样,我们可以得到每月的第一天:

function getFstDayOfMonFnc(date) {
  return new Date(date.getFullYear(), date.getMonth(), 1).getDate()
}

console.log(getFstDayOfMonFnc(new Date(2016, 2, 15))) // Output : 1


0
function getLastDay(y, m) {
   return 30 + (m <= 7 ? ((m % 2) ? 1 : 0) : (!(m % 2) ? 1 : 0)) - (m == 2) - (m == 2 && y % 4 != 0 || !(y % 100 == 0 && y % 400 == 0)); 
}

0
const today = new Date();

let beginDate = new Date();

let endDate = new Date();

// fist date of montg

beginDate = new Date(

  `${today.getFullYear()}-${today.getMonth() + 1}-01 00:00:00`

);

// end date of month 

// set next Month first Date

endDate = new Date(

  `${today.getFullYear()}-${today.getMonth() + 2}-01 :23:59:59`

);

// deducting 1 day

endDate.setDate(0);

0

设置您需要日期的月份,然后将日期设置为零,因此月份在日期函数中从1-31开始,然后获得最后一天^^

var last = new Date(new Date(new Date().setMonth(7)).setDate(0)).getDate();
console.log(last);


0

这是节省格林尼治标准时间和初始日期时间的答案

var date = new Date();

var first_date = new Date(date); //Make a copy of the date we want the first and last days from
first_date.setUTCDate(1); //Set the day as the first of the month

var last_date = new Date(first_date); //Make a copy of the calculated first day
last_date.setUTCMonth(last_date.getUTCMonth() + 1); //Add a month
last_date.setUTCDate(0); //Set the date to 0, this goes to the last day of the previous month

console.log(first_date.toJSON().substring(0, 10), last_date.toJSON().substring(0, 10)); //Log the dates with the format yyyy-mm-dd


0

我知道这只是语义问题,但最终我以这种形式使用了它。

var lastDay = new Date(new Date(2008, 11+1,1) - 1).getDate();
console.log(lastDay);

由于函数是从内部参数向外解析的,因此其作用相同。

然后,您可以只用所需的详细信息替换年份和月份,而不管它是从当前日期开始。或特定的月份/年份。


0

如果您需要以毫秒为单位的确切月底(例如时间戳记):

d = new Date()
console.log(d.toString())
d.setDate(1)
d.setHours(23, 59, 59, 999)
d.setMonth(d.getMonth() + 1)
d.setDate(d.getDate() - 1)
console.log(d.toString())

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.