用 Date 对象查找一个月中的所有日子?

Posted

技术标签:

【中文标题】用 Date 对象查找一个月中的所有日子?【英文标题】:Find all the days in a month with Date object? 【发布时间】:2012-10-20 05:32:20 【问题描述】:

有没有办法拥有一个月或一年的所有日子?我正在寻找这个以禁用日期选择器中的某些特定日期,我将在后台有一个页面来选择要禁用的这些日子。

所以我需要显示一个月中的所有日子,并在每一天下方添加一个“激活或停用”按钮。有没有办法用 Date 对象找到这些日子?我找到了这个链接,例如:Displaying all the days of a month ,但我不太明白,而且它是 Java,我正在尝试在 javascript 中找到解决方案。

感谢您的帮助

【问题讨论】:

“找到这些日子”或“拥有这些日子”的真正含义是什么?目标不明确 【参考方案1】:

要获取一个月中所有天的列表,您可以在一个月的第一天以Date 开头,增加天数直到月份发生变化。

/**
 * @param int The month number, 0 based
 * @param int The year, not zero based, required to account for leap years
 * @return Date[] List with date objects for each day of the month
 */
function getDaysInMonth(month, year) 
  var date = new Date(year, month, 1);
  var days = [];
  while (date.getMonth() === month) 
    days.push(new Date(date));
    date.setDate(date.getDate() + 1);
  
  return days;

UTC 版本

针对某些 cmets,我创建了一个使用 UTC 方法的版本,以防您想要调用 UTC 方法而不是返回本地化时区的标准方法。

我怀疑这是 cmets 说这不起作用的罪魁祸首。如果您使用 Date.UTC 实例化它,您通常希望确保调用 getUTCMonth/Day/Hours 方法,反之亦然,除非您尝试转换时区并显示差异。

function getDaysInMonthUTC(month, year) 
  var date = new Date(Date.UTC(year, month, 1));
  var days = [];
  while (date.getUTCMonth() === month) 
    days.push(new Date(date));
    date.setUTCDate(date.getUTCDate() + 1);
  
  return days;

编辑此答案

如果您认为此脚本有问题,请随时:

首先查看下面的现有单元测试 编写一个测试用例来证明它已损坏。 修复代码,确保现有测试通过。

单元测试

/**
 * @param int The month number, 0 based
 * @param int The year, not zero based, required to account for leap years
 * @return Date[] List with date objects for each day of the month
 */
function getDaysInMonthUTC(month, year) 
  var date = new Date(Date.UTC(year, month, 1));
  var days = [];
  while (date.getUTCMonth() === month) 
    days.push(new Date(date));
    date.setUTCDate(date.getUTCDate() + 1);
  
  return days;


function getDaysInMonth(month, year) 
  var date = new Date(year, month, 1);
  var days = [];
  while (date.getMonth() === month) 
    days.push(new Date(date));
    date.setDate(date.getDate() + 1);
  
  return days;


const days2020 = [31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];
const days2021 = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];

describe("getDaysInMonthUTC", function() 
  it("gets day counts for leap years", function() 
    const actual = days2020.map(
      (day, index) => getDaysInMonthUTC(index, 2020).length
    );
    expect(actual).toEqual(days2020);
  );

  it("gets day counts for non-leap years", function() 
    const actual = days2021.map(
      (day, index) => getDaysInMonthUTC(index, 2021).length
    );
    expect(actual).toEqual(days2021);
  );
);


describe("getDaysInMonth", function() 
  it("gets day counts for leap years", function() 
    const actual = days2020.map(
      (day, index) => getDaysInMonth(index, 2020).length
    );
    expect(actual).toEqual(days2020);
  );

  it("gets day counts for non-leap years", function() 
    const actual = days2021.map(
      (day, index) => getDaysInMonth(index, 2021).length
    );
    expect(actual).toEqual(days2021);
  );
);

// load jasmine htmlReporter
(function() 
  var env = jasmine.getEnv();
  env.addReporter(new jasmine.HtmlReporter());
  env.execute();
());
<script src="https://cdn.jsdelivr.net/jasmine/1.3.1/jasmine.js"></script>
<script src="https://cdn.jsdelivr.net/jasmine/1.3.1/jasmine-html.js"></script>
<link href="https://cdn.jsdelivr.net/jasmine/1.3.1/jasmine.css" rel="stylesheet"/>

【讨论】:

对代码的小修正 date.setDate(date.getDate() + 1);应该在 date.push 数组调用之前进行 @Timothy 这不起作用的测试用例是什么? @Timothy 仅当您想排除第一天(1 月 1 日或您开始脚本的任何地方)时。 @Timothy 说得对,脚本并不总是有效。它仅适用于某些时区。我已经编辑了答案来修复它。 @DiegoFaria 您的修复使问题变得更糟,您和 Timothy 都误解了一些东西 :) 您忘记更新 setDategetDate 以也使用 UTC 方法。我知道使用 UTC 方法通常是最好的选择。通常,如果您在UTCness 方面保持通话一致。我写了一些测试来证明这一点。随意进入并创建新的测试用例来解释您在哪里看到了问题。我相信在实例化 Date 的方式上保持一致会使其工作,因此请使用正确的 getDays,具体取决于您调用的方法【参考方案2】:

一个班轮获取一个月内的所有日期作为日期对象

const getDaysInMonth = (month, year) => (new Array(31)).fill('').map((v,i)=>new Date(year,month-1,i+1)).filter(v=>v.getMonth()===month-1)

【讨论】:

【参考方案3】:

从你的描述中我不确定标准的禁用日期日期选择器是否适用于你,所以我会直接回答你的问题。

您可以通过以下操作相当轻松地构造一个月的天数数组:

var numOfDays = new Date(2012, 10, 0).getDate(); //use 0 here and the actual month
var days = new Array();

//This will construct an array with all the elements represent the day of the week 
//(i.e. Oct 30th would be days[30-1] or days[29]) and the value would be the actual 
//day of the week (i.e. Tuesday which is representing by the number 2)
for(var i=0;i<=numOfDays;i++)

    days[i] = new Date(2012,9,i+1).getDay(); //use month-1 here            

//This will give you a number from 0 - 6 which represents (Sunday - Saturday)
alert(days[29]); 

​ 使用这一系列日期,您几乎可以随心所欲地做任何事情,并且还可以知道一周中的哪一天。

【讨论】:

【参考方案4】:

带 ES6 的快速简单的单线器

您可以get the number of days in a specified month,然后使用该长度填充一个新数组。

const getAllDaysInMonth = (month, year) =>
  Array.from(
    length: new Date(year, month, 0).getDate(),
    (_, i) => new Date(year, month - 1, i + 1)
  );

堆栈片段中的演示

const getAllDaysInMonth = (month, year) =>
  Array.from(
    length: new Date(year, month, 0).getDate(), // get next month, zeroth's (previous) day
    (_, i) => new Date(year, month - 1, i + 1)    // get current month (0 based index)
  );

const allDatesInOctober = getAllDaysInMonth(10, 2021)

console.log(allDatesInOctober.map(x => x.toLocaleDateString([],  month: "short", day: "numeric" )))

// ['Oct 1', 'Oct 2', 'Oct 3', 'Oct 4', 'Oct 5', 'Oct 6', 'Oct 7', 'Oct 8', 'Oct 9', 'Oct 10', 'Oct 11', 'Oct 12', 'Oct 13', 'Oct 14', 'Oct 15', 'Oct 16', 'Oct 17', 'Oct 18', 'Oct 19', 'Oct 20', 'Oct 21', 'Oct 22', 'Oct 23', 'Oct 24', 'Oct 25', 'Oct 26', 'Oct 27', 'Oct 28', 'Oct 29', 'Oct 30', 'Oct 31']

【讨论】:

不起作用,2021 年 10 月试了 29 天 十月有31天。我认为长度:-1 是造成这种情况的原因 感谢您的评论,是的,那里有一些奇怪的逻辑 - 日期月份从零开始总是让我明白【参考方案5】:

这是一个贯穿每个月的循环,以确定该月的最后一天。 Javascript Date 对象索引从零开始的月份,如果您将日期设置为零,它会恢复到上个月的最后一天。方便确定 2 月的闰年最后一天

Date( 2012, 12, 0) 将于 2012 年 12 月 31 日返回

Date (2012,0,0) 将于 2011 年 12 月 31 日返回

要弄清楚的最重要的是二月

Date ( 2012,3,0)今年闰年2月29日返回

var mos=['jan','feb','mar','apr','may','jun','jul','aug','sep','oct','nov','dec']

for (i = 0; i < 12; i++) 
    var lastDate = new Date(2012, i+1, 0);
    $('body').append('Last day of ' + mos[i] + ' is ' + lastDate.getDate()+'<br>')

演示:http://jsfiddle.net/5k8sn/1/

【讨论】:

【参考方案6】:

我已经使用 jQuery 日期选择器实现了您要求的功能。

首先,将后台选择的所有要禁用的日期添加到一个数组中

// format yyyy-mm-dd
var disabledDates = [
    "2012-10-01",
    "2012-10-02",
    "2012-10-30",
    "2012-09-12"
];

其次,用两个函数指定日期选择器

$("#datepicker").datepicker(

    // only enable date if dateEnabled returns [true]
    beforeShowDay: dateEnabled,

    // once a date has been selected call dateSelected
    onSelect: dateSelected
);

这里是所需函数的定义

function dateEnabled( d ) 

    // if date found in array disable date
    if( disabledDates.indexOf( getDate( d ) ) > -1 ) 

        return [false];

     else 

        return [true] ;

    
  

将日期转换为字符串,以便与数组中的日期进行比较

function getDate( d ) 
    var day,
        month,
        year;

    day = d.getDate( );
    month = d.getMonth( ) + 1; // add 1 as getMonth returns 0 - 11
    year = d.getFullYear( );

    if( month < 10 ) month = "0" + month;
    if( day < 10 ) day = "0" + day;
    return year + "-" + month + "-" + day;

选择日期后处理它

function dateSelected( d )  
   // do stuff with string representation of date                                          

这是一个小提琴http://jsfiddle.net/KYzaR/7/

只是认为值得一提的是 Array.indexOf 是 ECMA-262 标准的最新补充,因此在 IE7 和 IE8 的情况下不支持它。以下 MDN 页面提供了为这些浏览器实现 Array.indexOf 的代码https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/Array/indexOf

【讨论】:

@Juan Mendes 不太明白你的意思,不使用 indexOf 怎么办?【参考方案7】:

要禁用日期选择器中的日期,您可以使用此处描述的答案:https://***.com/a/12061715/48082

要选择多个日期(如在后台应用中),您可以使用此插件:http://multidatespickr.sourceforge.net/

【讨论】:

【参考方案8】:

我有一个解决方案。快乐编码❤️ !! 注:0=1 月,1=2 月等。 example w3schools

const getDays = (month, year) => 
    let date = new Date(`$year-$parseInt(month)+1-01`);
    let days = [];
    while (date.getMonth() === parseInt(month)) 
        days.push(date.getDate());
        date.setDate(date.getDate() + 1);
    
    return days;

【讨论】:

请为您的答案添加一些解释 @louisHoang - 很好地冒险写下你的第一个答案!这个答案似乎与接受的答案重复。请你能说清楚你的答案有什么不同吗? 我觉得我在下面添加了以下文件的文本更容易让您阅读【参考方案9】:

你为什么不把一个月中的所有日子都放在这样的数组中。

 const getDaysInMonth = (month,year,index=1,result=[]) =>
            const date = new Date(year,month,index)
            return month == date.getMonth() ? getDaysInMonth(month,year,index+1,[...result,date]) : result
        

然后数一数

const countDaysOfMonth = daysInMonth => daysInMonth.reduce((acc,value) => acc+1 ,0)

然后使用 Math.ceil 7 将总数除以得到周数的行数

const countWeeksInMonth = numberOfDays => Math.ceil(numberOfDays / 7)

【讨论】:

【参考方案10】:

这部分“新日期(年,月,0)”将获得一个月的最后一天,因此您只需从这一天开始迭代,创建从 1 到最后一天的所有天。

public getAllDaysOfMonth(year:number, month: number)
   const lastDayOfMonth = new Date(year, month , 0).getDate();
   for (let i = 1; i < lastDayOfMonth + 1; i++) 
     console.log('day', new Date(year, month - 1, i)) //Here will print all days
   

【讨论】:

以上是关于用 Date 对象查找一个月中的所有日子?的主要内容,如果未能解决你的问题,请参考以下文章

JavaScript中的Date对象

每天的 SQL 计数并在接下来的所有日子里加在一起

如何获得两天之间的所有日子的数组,并将其显示在一个列表中?

JavaScript Date对象方法详细总结

JavaScriptJavaScript中的时间函数

JavaScriptJavaScript中的时间函数