日期 Date
重要通知
类目简介
基本概况
new Date()对象
- 四种方式初始化日期:
new Date(); // 2023-09-12T15:06:37.473Z
new Date(value); // 参数为毫秒
new Date(dateString); // dateString 参数表示日期的字符串值
new Date(
year, // 年,0000。用本地时间表示。
monthIndex [, // 设置 Date 对象中月份 (0 ~ 11)。
day [, // 设置 Date 对象中月的某一天 (1 ~ 31)。
hours [, // 设置 Date 对象中的小时 (0 ~ 23)。
minutes [, // 设置 Date 对象中的分钟 (0 ~ 59)。
seconds [, // 设置 Date 对象中的分钟 (0 ~ 59)。
milliseconds]]]]] // milliseconds 参数是一个 Unix 时间戳(Unix Time Stamp),它是一个整数值,表示自 1970 年 1 月 1 日 00:00:00 UTC(the Unix epoch)以来的毫秒数。
);
- 设置日期
const date = new Date();
// 设置 Date 对象中的年份(四位数字,0000)。
date.setFullYear(
year, // 必需。表示年份的四位整数。用本地时间表示。
month, // 可选。表示月份的数值。用本地时间表示。介于 0 到 11 之间的整数值,表示从一月到十二月。-1 为去年的最后一个月,12 为明年的第一个月,13 为明年的第二个月。
day // 可选。表示月中某一天的数值。用本地时间表示。介于 1 ~ 31 之间。0 为上个月最后一天,-1 为上个月最后一天之前的天数。如果当月有31天,32 为下个月的第一天。如果当月有30天,32 为下一个月的第二天。
);
date.setMonth(); // 设置 Date 对象中月份 (0 ~ 11)。
date.setDate(); // 设置 Date 对象中月的某一天 (1 ~ 31)。
date.setHours(); // 设置 Date 对象中的小时 (0 ~ 23)。
date.setMilliseconds(); // 设置 Date 对象中的毫秒 (0 ~ 999)。
date.setMinutes(); // 设置 Date 对象中的分钟 (0 ~ 59)。
date.setSeconds(); // 设置 Date 对象中的秒钟 (0 ~ 59)。
date.setTime(); // setTime() 方法以毫秒设置 Date 对象。
- 获取指定年月中当前月份的总天数,例如: 获取2023年01月的当月总天数
/**
* 获取指定年月中当前月份的总天数,例如: 获取2023年01月的当月总天数
* @param {*} year: 0000
* @param {*} month: 值范围 1~12,不能为0~11,否则会出现错乱
*/
function getYMDays(year, month) {
const _year = Number(year);
const _month = Number(month);
return new Date(_year, _month, 0).getDate();
}
const days = getYMDays(2023, 1);
console.info('days: ', days); // 一月份共 31天
- 获取指定年月中当前月份的第一天对应星期几,例如: 获取2023年01月的第一天属于星期几
/**
* 获取指定年月中当前月份的第一天对应星期几,例如: 获取2023年01月的第一天属于星期几
* @param {*} year: 0000
* @param {*} month: 值范围 1~12,不能为0~11,否则会出现错乱
*/
function getYMFDWeek(year, month) {
const _year = Number(year);
const _month = Number(month);
const date = new Date();
date.setFullYear(_year);
date.setMonth(_month - 1);
date.setDate(1);
return date.getDay();
}
const firstDay = getYMFDWeek(2023, 1);
console.info('firstDay: ', firstDay); // 属于 星期日
- 获取指定年月中当前月份的最后一天对应星期几,例如: 获取2023年01月的最后一天属于星期几
/**
* 获取指定年月中当前月份的最后一天对应星期几,例如: 获取2023年01月的最后一天属于星期几
* @param {*} year: 0000
* @param {*} month: 值范围 1~12,不能为0~11,否则会出现错乱
*/
function getYMLDWeek(year, month) {
const _year = Number(year);
const _month = Number(month);
const days = getYMDays(_year, _month);
const date = new Date();
date.setFullYear(_year);
date.setMonth(_month - 1);
date.setDate(days);
return date.getDay();
}
const lastDay = getYMLDWeek(2023, 1);
console.info('lastDay: ', lastDay); // 属于 星期二
- 获取指定年月日的未来往前几天的日期
/**
* 获取指定年月日的未来往前几天的日期
*/
function getNextDaysDate(days = 1) {
const date = new Date();
date.setDate(date.getDate() + days);
return date;
}
- 获取指定年月日的历史往后几天的日期
/**
* 获取指定年月日的历史往后几天的日期
*/
function getPrevDaysDate(days = 1) {
const date = new Date();
date.setDate(-days);
return date;
}
- 获取指定年月的上一个月份
/**
* 获取指定年月的上一个月份
* @param {*} year: 0000
* @param {*} month: 值范围 1~12,不能为0~11,否则会出现错乱
*/
function getPrevMonthDate(year, month) {
const _year = Number(year);
const _month = Number(month);
const toYear = _month === 1 ? _year - 1 : _year;
const toMonth = _month === 1 ? 11 : _month - 2;
const date = new Date();
date.setFullYear(toYear);
date.setMonth(toMonth);
return date;
}
const prevMDate = getPrevMonthDate(2023, 1);
console.info(prevMDate); // 2022-12-13T03:49:25.832Z
- 获取指定年月的下一个月份
/**
* 获取指定年月的下一个月份
* @param {*} year: 0000
* @param {*} month: 值范围 1~12,不能为0~11,否则会出现错乱
*/
function getNextMonthDate(year, month) {
const _year = Number(year);
const _month = Number(month);
const toYear = _month === 12 ? _year + 1 : _year;
const toMonth = _month === 12 ? 0 : _month;
const date = new Date();
date.setFullYear(toYear);
date.setMonth(toMonth);
return date;
}
const nextMDate = getNextMonthDate(2023, 1);
console.info(nextMDate); // 2023-02-13T07:51:33.195Z
- 公元前日期
年:使用四位数年份,比如2000。如果写成两位数或个位数,则加上1900,即10代表1910年。如果是负数,表示公元前。
const date = new Date();
date.setFullYear(-10);
console.info(date); // -000010-09-13T03:26:17.597Z
console.info(date.getFullYear()); // -10
- 返回指定日期年月"0000-00"中当月的天数与星期排列数组(按照一个星期矩阵数据结构)
/**
* 返回指定日期年月"0000-00"中当月的天数与星期排列数组(按照一个星期矩阵数据结构)
* @param {*} year: 0000
* @param {*} month: 值范围 1~12,不能为0~11,否则会出现错乱
*/
export function initMonthWeekList(year: number, month: number) {
const _year = Number(year);
const _month = Number(month);
// 获取指定年月中当前月份的总天数
const days = getYMDays(_year, _month);
// 获取指定年月中当前月份的第一天对应星期几
const firstDayWeek = getYMFDWeek(_year, _month);
// 获取指定年月中当前月份的最后一天对应星期几
const lastDayWeek = getYMLDWeek(_year, _month);
const firstDay = 1; // 当月第一天
const lastDay = days; // 当月最后一天
const weekDays = 7; // 一周存在七天
const saturday = 6; // 星期六
const sunday = 0; // 星期日
// 指定年月中当前月份的星期数组
const daysWeekList = [];
// 当前月份的第一个星期的星期日所对应的是第几天
const firstWeekDays = firstDayWeek === sunday ? firstDay : weekDays - firstDayWeek + 1;
// 当前月份的最后一个星期的星期六所对应的是第几天
const lastWeekDays = lastDayWeek === saturday ? days : days - lastDayWeek - 1;
// 日志输出
// console.warn(`原始日期:${_year} ${_month}`, `总天数:${days} ${firstWeekDays} ${lastWeekDays}`);
// 当月的第一天不是星期日
if (firstWeekDays !== firstDay) {
// 获取指定年月中的上一月
const prevMDate = getPrevMonthDate(_year, _month);
const prevMYear = prevMDate.getFullYear();
const prevM = prevMDate.getMonth();
const prevMDays = getYMDays(prevMYear, prevM + 1);
const weekDayList = [];
// 上个月最后几天
for (let i = prevMDays - firstDayWeek + 1; i <= prevMDays; i++) {
weekDayList.push({ y: prevMYear, m: prevM + 1, d: i, type: 'prev' });
}
// 当月前几天
for (let i = 1; i < firstWeekDays; i++) {
weekDayList.push({ y: _year, m: _month, d: i, type: 'current' });
}
daysWeekList.unshift(weekDayList);
}
// 其他中间范围周
const middleWeeks = lastWeekDays - firstWeekDays + 1;
const times = middleWeeks / weekDays;
for (let i = 0; i < times; i++) {
const weekDayList = [];
for (let j = 0; j < weekDays; j++) {
const curDay = firstWeekDays + j + weekDays * i;
weekDayList.push({ y: _year, m: _month, d: curDay, type: 'current' });
}
daysWeekList.push(weekDayList);
}
// 当月的最后一天不是星期六
if (lastWeekDays !== lastDay) {
const weekDayList = [];
// 当月最后几天
for (let i = lastWeekDays + 1; i <= days; i++) {
weekDayList.push({ y: _year, m: _month, d: i, type: 'current' });
}
// 下个月前几天
const nextMDate = getNextMonthDate(_year, _month);
const nextMYear = nextMDate.getFullYear();
const nextM = nextMDate.getMonth();
for (let i = 1; i <= weekDays - lastDayWeek - 1; i++) {
weekDayList.push({ y: nextMYear, m: nextM + 1, d: i, type: 'next' });
}
daysWeekList.push(weekDayList);
}
return daysWeekList;
}
https://www.w3school.com.cn/jsref/jsref_obj_date.asp https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Date https://day.js.org/docs/zh-CN/display/format
基础函数
Date.now():返回自 1970 年 1 月 1 日 00:00:00 (UTC) 到当前时间的毫秒数。
1970-01-01 08:00:00 时间由来 是因为起源于UNIX系统,以Unix诞生的时间为参照确定的,UNIX认为1970年1月1日0点是时间纪元,现代计算机(电话,电子设备)时间以1970 年 1 月 1 日的 08:00为基准, 在时间转换时,或者时间重置时都会出现这个时间值,unix时间戳零点是 1970年1月1日0点整(utc),北京是gmt 8所以变成八点。
Date.now()、new Date('1970-01-01T00:00:00')与new Date('1970-01-01T08:00:00')的区别
// 统一时区
function getStandardDate(beijing = -480) {
const date = new Date();
const timezoneOffset = date.getTimezoneOffset();
const milliseconds = timezoneOffset * 60 * 1000;
const currentTime = date.getTime(); // 返回从 1970 年 1 月 1 日至今的毫秒数。
const currentDate = new Date(currentTime + milliseconds - beijing * 60 * 1000);
// console.info('currentDate:', currentDate);
return currentDate;
}
const date = getStandardDate();
const year = date.getFullYear(); // 年(0000)
const month = date.getMonth(); // 月份(0-11)
const day = date.getDate(); // 天数(1--31)
const hours = date.getHours(); // 0 ~ 23
const minutes = date.getMinutes(); // 0 ~ 59
const seconds = date.getSeconds(); // 0 ~ 59
const date = Date.now();
console.log(date.toString('yyyy-MM-dd HH:mm:ss fff'));
// (Date.now()).toString('yyyy-MM-dd')
//
let day = (new Date('2019', '2', 0)).getDate();
console.log(day);
const date1 = new Date('December 17, 1995 03:24:00');
// Sun Dec 17 1995 03:24:00 GMT+0800 (中国标准时间)
const date2 = new Date('1995-12-17T03:24:00');
// Sun Dec 17 1995 03:24:00 GMT+0800 (中国标准时间)
let date = new Date(); // 时间戳, 13位
console.log(date.getTime()); // 1571648859693 返回从 1970 年 1 月 1 日至今的毫秒数。
console.log(date); // 2019-10-21T09:07:39.693Z
console.log(new Date(date.getTime())); // 2019-10-21T09:07:39.693Z 返回从 1970 年 1 月 1 日至今的毫秒数。
// 10位
date.getTime() // 1000 返回从 1970 年 1 月 1 日至今的毫秒数。
// Date:日期对象
new Date(); // 返回:Thu May 26 2016 09:46:50 GMT+0800 (中国标准时间)
new Date(str);
new Date(year,month,day,hours,minutes,seconds,milliseconds);
将日期对象转换为字符串
date.toString() //将日期对象转换为字符串,采用本地时间,显示格式:Sat Sep 17 2016 11:17:04 GMT+0800 (中国标准时间)
date.toLocaleString() //将日期对象转换为字符串,采用本地时间,将日期显示为地方日期的格式,显示格式:2016/9/17 上午11:16:33
date.toUTCString() //将日期对象转换为字符串,采用世界时间,UTC(协调世界时),显示格式:Sat, 17 Sep 2016 03:17:31 GMT
date.toGMTString() //将日期对象转换为字符串,采用GMT时间,GMT(格林尼治时),显示格式:Sat, 17 Sep 2016 03:17:54 GMT
将日期对象中的日期和时间转换为字符串
//将日期对象中的日期部分转换为字符串,采用本地时间,显示格式:Sat Sep 17 2016
date.toDateString()
//将日期对象中的日期部分转换为字符串,采用本地时间,将日期显示为地方日期的格式,显示格式:2016/9/17
date.toLocaleDateString()
//将日期对象中的时间部分转换为字符串,采用本地时间,显示格式:11:19:59 GMT+0800 (中国标准时间)
date.toTimeString()
//将日期对象中的时间部分转换为字符串,采用本地时间,将日期显示为地方日期的格式,显示格式:上午11:20:49
date.toLocaleTimeString()
获取日期对象中的日期
date.getYear() //返回日期对象中的年份,采用本地时间,显示2007年
date.getFullYear() //返回日期对象中的年份,采用本地时间,以4位数显示,2007年
date.getMonth() //返回日期对象中的月份,采用本地时间, 返回值: 0-11,1月份返回0
date.getDate() //根据本地时间,返回一个指定的日期对象为一个月中的哪一日(从1--31)。
date.getDay() //返回日期对象中的日期是一周中的第几天,采用本地时间, 返回值: 0-6,即周日-周六
date.getUTCFullYear() //返回日期对象中的年份,采用世界时间,以4位数显示,显示格式:2007
date.getUTCMonth() //返回日期对象中的月份,采用世界时间,其值范围为0-11,1月份返回0
date.getUTCDate() //返回日期对象中的天数,采用世界时间,即一个月之的某一天
date.getUTCDay() //返回日期对象中的日期是一周中的第几天,采用UTC时间,其值为0-6
获取日期对象中的时间
date.getHours() //返回日期对象中的小时部分,采用本地时间, 返回值: 0 ~ 23
date.getMinutes() //返回日期对象中的分钟部分,采用本地时间, 返回值: 0 ~ 59
date.getSeconds() //返回日期对象中的秒钟部分,采用本地时间, 返回值: 0 ~ 59
date.getMilliseconds() // 返回日期对象中的毫秒部分,采用本地时间, 返回值: 0 ~ 999
date.getTime() // 返回日期对象中的时间与1970年1月0时0分0秒所间隔的毫秒数,采用本地时间,1毫秒(ms)=0.001秒(s)
date.getUTCHours() //返回日期对象中的小时部分,采用UTC时间
date.getUTCMinutes() //返回日期对象中的分钟部分,采用UTC时间
date.getUTCSeconds() //返回日期对象中的秒钟部分,采用UTC时间
date.getUTCMilliseconds() //返回日期对象中的毫秒部分,采用UTC时间
date.getUTCTime() //返回日期对象中的时间与1970年1月0时0分0秒所间隔的毫秒数,采用UTC时间
date.getUTCTimezoneOffset() //返回日期对象中的本地时间与UTC之间的时差数(单位为秒)部分,采用UTC时间
统一世界时区,以北京时区为基准
1884年在华盛顿召开的一次国际经度会议上,规定将全球划分为24个时区。每个时区横跨经度15度,时间正好是1小时。最后的东、西第12区各跨经度7.5度,以东、西经180度为界。 中时区(零时区):UTC/GMT 东1-12区:UTC+1 - UTC+12 西1-12区:UTC-1 - UTC-12 东12区与西12区同属一个时区
国际日期变更线(180°经线)
作为地球上“今天”和“昨天”的分界线。从东向西越过这条界线时,日期要加一天,从西向东越过这条界线时,日期要减去一天。 又叫“人为日界线”。
new Date().getHours()
new Date().getTimezoneOffset()
// 时区为 GMT+2, 将返回-120 。
date.getTimezoneOffset() //返回日期对象中的本地时间与UTC之间的时差数(单位为分钟)部分,采用本地时间
格式化日期
function dateFormat(date, format) {
// format: 'yyyy-MM-dd hh:mm:ss' | 'yyyy/MM/dd'
}
判断是否为闰年
闰年共有366天(1月~12月分别为31天、29天、31天、30天、31天、30天、31天、31天、30天、31天、30天、31天)
// 年份能被4整除,但不能被100整除 | 年份能被400整除
function isLeapYear(year) {
return (year % 4 === 0 && year % 100 !== 0) || (year % 400 === 0);
}
根据0000/00数据结构转换为0000/00/01 ~ 0000/00/31
const startDateText = '2022/01';
const endDateText = '2022/04';
const dateList = [];
const startDateArray = startDateText.split('/');
const endDateArray = endDateText.split('/');
const sdYear = parseInt(startDateArray[0]);
const sdMonth = parseInt(startDateArray[1]);
const edYear = parseInt(endDateArray[0]);
const edMonth = parseInt(endDateArray[1]);
if (edYear === sdYear) {
for (let i = 0; i < edMonth - sdMonth + 1; i++) {
const month = sdMonth + i;
const date = getStandardDate();
date.setFullYear(sdYear);
date.setMonth(month);
date.setDate(0);
const days = date.getDate();
dateList.push({
reportStartDate: `${sdYear}/${month > 9 ? month : '0' + month}/01`,
reportEndDate: `${sdYear}/${month > 9 ? month : '0' + month}/${days}`
});
}
} else {
for (let i = 0; i < edYear - sdYear + 1; i++) {
if (i === 0) {
for (let j = 0; j < 12 - sdMonth + 1; j++) {
const month = sdMonth + j;
const date = getStandardDate();
date.setFullYear(sdYear);
date.setMonth(month);
date.setDate(0);
const days = date.getDate();
dateList.push({
reportStartDate: `${sdYear}/${month > 9 ? month : '0' + month}/01`,
reportEndDate: `${sdYear}/${month > 9 ? month : '0' + month}/${days}`
});
}
} else if (i < edYear - sdYear) {
for (let j = 1; j <= 12; j++) {
const month = j;
const date = getStandardDate();
date.setFullYear(sdYear + i + 1);
date.setMonth(month);
date.setDate(0);
const days = date.getDate();
dateList.push({
reportStartDate: `${sdYear + i}/${month > 9 ? month : '0' + month}/01`,
reportEndDate: `${sdYear + i}/${month > 9 ? month : '0' + month}/${days}`
});
}
} else {
for (let j = 1; j <= edMonth; j++) {
const month = j;
const date = getStandardDate();
date.setFullYear(edYear);
date.setMonth(month);
date.setDate(0);
const days = date.getDate();
dateList.push({
reportStartDate: `${edYear}/${month > 9 ? month : '0' + month}/01`,
reportEndDate: `${edYear}/${month > 9 ? month : '0' + month}/${days}`
});
}
}
}
}
console.info(dateList);
日期时间第三方库
日期时间 dayjs
日期时间库
- 中文文档:https://dayjs.gitee.io/zh-CN/
- 官网:https://day.js.org/
- GitHub:https://github.com/iamkun/dayjs
- 最新版: https://www.jsdelivr.com/package/npm/dayjs
- 日期包:https://day.js.org/docs/zh-CN/display/format
moment-mini与Moment.js
在 JavaScript 中解析、验证、操作和显示日期和时间。
缺陷
- Moment 对象是可变的,这容易导致前后对象内容出现变化。
- Moment 不能很好地与现代 “tree shaking” 算法配合使用,因此它往往会增加 Web 应用程序包的大小。
- 如果需要国际化或时区支持,Moment 可能会变得相当大。
代码示例
// https://momentjs.com/downloads/moment.js
import miment from 'moment-mini';
miment().format('YYYY-MM-DD');
miment().format('YYYY-MM-DD');
import moment from 'moment';
// 具体语法
moment(String, String);
moment(String, String, String);
moment(String, String, String[]);
moment(String, String, Boolean);
moment(String, String, String, Boolean);
const nativeDate = moment().toDate(); // 等同于 new Date()
console.log(nativeDate instanceof Date); // true
// 很重要,避免后续操作会改变原始moment
const _moment = moment().clone();
// 建议不要创建moment()对象引用,避免出现改变原始moment,而是直接每次使用moment()即可
console.log(moment());
console.log(moment().format("YYYY-MM-DD"));
console.log(moment().format("YYYY-MM-DD HH:MM:SS"));
// 加法
键 速记
年数 y
季度 Q
月数 M
周数 w
天数 d
小时数 h
分钟数 m
秒数 s
毫秒数 ms
moment().add(Number, String);
moment().add(Duration);
moment().add(Object);
moment().add(7, 'days');
moment().add(7, 'd');
// 很重要,避免后续操作会改变原始moment
const _moment = moment().clone();
console.log(moment());
console.log(moment().format("YYYY-MM-DD")); // 2024-11-08
console.log(moment().format("YYYY-MM-DD HH:MM:SS")); // 2024-11-08 18:11:44
console.log(moment().hour()); // 18
console.log(moment().hours()); // 18
console.log(moment().minute()); // 28
console.log(moment().minutes()); // 28
console.log(moment().second()); // 10
console.log(moment().seconds()); // 10
console.log(moment().millisecond()); // 445
console.log(moment().milliseconds()); // 445
console.log(moment().date()); // 8
// 第一个日期时间戳
const start = startDate.getTime();
// 第一个日期 上一年 时间戳
const nowLastYear = miment(startDate).subtract(365, "days").valueOf(); // 类似于 Date.now()与 (new Date()).getTime()
// 第一个日期 上一年 时间戳
const nowNextYear = miment(startDate).add(365, "days").valueOf();
// 添加: 年
console.log(moment().add(1, "y").format("YYYY-MM-DD")); // 2025-11-08
console.log(moment().add(-1, "y").format("YYYY-MM-DD")); // 2023-11-08
// 添加: 月
console.log(moment().add(1, "M").format("YYYY-MM-DD")); // 2024-12-08
// 添加: 日
console.log(moment().add(1, "d").format("YYYY-MM-DD")); // 2024-11-09
// 添加: 时
console.log(moment().add(1, "h").format("YYYY-MM-DD HH:MM:SS")); // 2024-11-08 18:11:44
// 添加: 分
console.log(moment().add(1, "m").format("YYYY-MM-DD HH:MM:SS")); // 2024-11-08 18:11:44
// 添加: 秒
console.log(moment().add(10, "s").format("YYYY-MM-DD HH:MM:SS")); // 2024-11-08 18:11:44
// 添加: 季度
console.log(moment().add(1, "Q").format("YYYY-MM-DD")); // 2025-02-08
// 添加: 周
console.log(moment().add(1, "w").format("YYYY-MM-DD")); // 2024-11-15
// 因为使用moment(),所以没有对原始moment影响
console.log(moment().format("YYYY-MM-DD")); // 2024-11-08
console.log();
// 加法
// 选择今天之前的时间
moment().isAfter(moment(new Date()).subtract(1, "days"));
// 选择今天之后的时间
moment().isBefore(moment(new Date()).subtract(1, "days"));
// 限制不能选择今天之后的时间,同时不能选择今天之前超过365天的时间
const min = moment(new Date()).subtract(365, "days");
const max = moment(new Date());
const disabledDate = (time) => !moment(time).isBetween(min, max, "day");
const m = moment();
const cloneM = m.clone();
const copyM = m.clone();
console.log(m);
console.log(m.format()); // 2024-10-29T18:02:36+08:00
console.log(m.calendar()); // Today at 6:25 PM
console.log();
console.log();
console.log();
console.log();
console.log();
console.log();
console.log();
console.log();
console.log();
console.log();