日期 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

日期时间库

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();
Last Updated:
Contributors: 709992523, Eshen