Skip to content

Instantly share code, notes, and snippets.

@john-yuan
Last active June 15, 2019 01:48
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save john-yuan/63d461e2e2de9afbde47e966f2c8c900 to your computer and use it in GitHub Desktop.
Save john-yuan/63d461e2e2de9afbde47e966f2c8c900 to your computer and use it in GitHub Desktop.
获取指定月份日历视图中的 42 个日期对象。
/**
* 获取指定月份日历视图中的 42 个日期对象。
*
* @param {number} year 完整的年份数字,如 `2019` 即代表 2019 年。
* @param {number} month 月份数字,如 `11` 即代表 11 月。
* @param {number} [startWeekDay=0] 可选的参数,默认为 `0`(星期日),表示日历中的第一列为星期几(一般为星期日或者星期一)。其中 `0` 表
* 示星期日,`1` 表示星期一,后面以此类推。
* @returns {Date[]} 返回一个数组,包含 42 个 `Date` 对象。
*/
function getCalendarDateList(year, month, startWeekDay) {
// 一个日历视图中有 42 个日期,每一行有 7 个日期,一共有 6 行,一共有 42 个格子。
// 为了找到这 42 个日期,我们只需找到日历中第一个日期即可,后面的日期均可由第一个日期推导出来。
// 为了方便描述,我们把日历中不属于本月的日期(如上个月的 31 号和下个月的 1 号等)的格子称为灰色格子。
// 为了找到本月日历中的第一个日期对象,我们需要先求得本月日历前面有多少个灰色格子,现在假设前面的灰色格子数量为 x 个。
// 根据已知条件 year 和 month,我们可以求得本月 1 号为星期几,并将结果保存到变量 firstDateWeekDay 中。
// 如果 firstDateWeekDay 大于等于 startWeekDay,那么 x = firstDateWeekDay - startWeekDay。
// 如果 firstDateWeekDay 小于 startWeekDay,那么 x = firstDateWeekDay + 7 - startWeekDay。
// 以上便可以求出 x 的值,用本月 1 号的日期对象来减去 x 天即可得到日历中的第一个格子的日期。
var x; // 日历中前面的灰色格子数量
var firstDate; // 本月 1 号日期
var firstDateWeekDay; // 本月 1 号为星期几,范围是 { 0, 1, 2, 3, 4, 5, 6 }
var calendarDate; // 日历中第一个格子对应的日期对象
var calendarDateList = []; // 日历日期列表
// 处理默认参数 startWeekDay
if (!startWeekDay) {
startWeekDay = 0;
} else if (typeof startWeekDay !== 'number') {
startWeekDay = parseInt(startWeekDay, 10);
}
if (isNaN(startWeekDay)) {
startWeekDay = 0;
}
// 确保 startWeekDay 大于等于 0
while (startWeekDay < 0) {
startWeekDay += 7;
}
// 确保 startWeekDay 小于等于 6
while (startWeekDay > 6) {
startWeekDay -= 7;
}
firstDate = new Date(year, month - 1, 1, 8); // 本月 1 号早上 8 点
firstDateWeekDay = firstDate.getDay();
if (firstDateWeekDay >= startWeekDay) {
x = firstDateWeekDay - startWeekDay;
} else {
x = firstDateWeekDay + 7 - startWeekDay;
}
calendarDate = new Date(firstDate.getTime() - x * 86400000); // firstDate 减去 x 天
while (calendarDateList.length < 42) {
calendarDateList.push(calendarDate);
calendarDate = new Date(calendarDate.getTime() + 86400000); // 计算下一天
}
return calendarDateList;
}
/**********************************************************************************************************************/
// 以下为测试:
function testGetCalendarList(year, month, startWeekDay, expected) {
var firstCalendarDate = getCalendarDateList(year, month, startWeekDay)[0];
var year = firstCalendarDate.getFullYear();
var month = firstCalendarDate.getMonth() + 1;
var date = firstCalendarDate.getDate();
var actual = year + '/' + month + '/' + date;
var passed = actual === expected;
var throwErrorAsync = function (err) {
setTimeout(function () {
throw err;
});
};
console.log('----------- T E S T -----------');
console.log('year: ' + year);
console.log('month: ' + month);
console.log('startWeekDay: ' + startWeekDay);
console.log('expected: ' + expected);
console.log('actual: ' + actual);
if (passed) {
console.log('test passed: ' + passed);
} else {
console.error('test passed: ' + passed);
throwErrorAsync(new Error('testGetCalendarList(' +
year + ', ' +
month + ', ' +
startWeekDay + ', "' +
expected + '"): ' +
actual + ' (actual) is not equal to ' +
expected + ' (expected)'));
}
console.log('');
}
// 以星期天开头的日历测试
testGetCalendarList(2019, 6, 0, '2019/5/26');
testGetCalendarList(2019, 1, 0, '2018/12/30');
testGetCalendarList(2018, 7, 0, '2018/7/1'); // 特殊日期,第一个格子为本月 1 号
// 以星期一开头的日历测试
testGetCalendarList(2019, 6, 1, '2019/5/27');
testGetCalendarList(2019, 1, 1, '2018/12/31');
testGetCalendarList(2019, 4, 1, '2019/4/1'); // 特殊日期,第一个格子为本月 1 号
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment