JS 日期

UTC 和 GMT

UTC,协调世界时,又称世界统一时间,世界标准时间,国际协调时间。

在设置和获取日期时,如果不规定时区,则 JavaScript 会使用浏览器的时区。

换句话说,假如日期/时间以 GMT(格林威治标准时间)创建,该日期/时间将被转换为 CST(中国标准时间),如果用户从中国进行浏览。

如果以 UTC 创建,则用世界统一时间(一般不用)。

UTC 时间用大写 Z 来定义,比如 2020-11-23T06:53:35.672Z,代表 2020-11-23 14:53:35

时区

在设置日期时,如果不规定时区,则 JavaScript 会使用浏览器的时区。

当获取日期时,如果不规定时区,则结果会被转换为浏览器时区。

换句话说,假如日期/时间以 GMT(格林威治标准时间)创建,该日期/时间将被转换为 CST(中国标准时间),如果用户从中国进行浏览。

创建 Date 的四个构造函数

  • new Date()
    • +new Date() 直接返回时间戳,+ 号用来转换为数字
  • new Date(year, month, day, hours, minutes, seconds, milliseconds)
  • new Date(milliseconds)
  • new Date(datestring)
// new Date()
var d1 = new Date();
// 2020-11-25T03:00:44.769Z
console.log("d1 = " + d1);

// new Date(year, month, day, hours, minutes, seconds, milliseconds)
// 如果只传前几个参数,但不能只传年,会被视为毫秒
// 如果年只传 1 或 2 位数,例如 99、9,会被解释为上个世纪1909年
var d2 = new Date(2020, 11, 25);
// Fri Dec 25 2020 00:00:00 GMT+0800 (GMT+08:00)
console.log("d2 = " + d2);

// new Date(milliseconds)
// 传入自 1970 年 1 月 1 日的毫秒值,得到一个日期
var d3 = new Date(86400000);
// Fri Jan 02 1970 08:00:00 GMT+0800 (GMT+08:00)
console.log("d3 = " + d3);

// new Date(datestring)
// 从日期字符串创建一个新的日期对象
// datestring 怎么写将在下面讲解
var d4 = new Date("2018-02-09");
// Fri Feb 09 2018 08:00:00 GMT+0800 (GMT+08:00)
console.log("d4 = " + d4);

JS 的日期格式

类型 实例
ISO 日期 “2018-02-19” (国际标准)
短日期 “02/19/2018” 或者 “2018/02/19”
长日期 “Feb 19 2018” 或者 “19 Feb 2019”
完整日期 “Monday February 25 2015”

ISO

// 在某些浏览器中,不带前导零的月也许会产生错误
var d1 = new Date("2015-03-02");
var d1_2 = new Date("2015-03");
var d1_3 = new Date("2015");
// Mon Mar 02 2015 08:00:00 GMT+0800 (GMT+08:00)
console.log("d1 = " + d1);

// 若加时分秒的话,用 T 隔开,秒不可省略
// 在日期-时间字符串中省略 T,在不同浏览器中会产生不同结果。
var d2 = new Date("2018-02-19T12:00:00");
// Mon Feb 19 2018 12:00:00 GMT+0800 (GMT+08:00)
console.log("d2 = " + d2);

// 如果非要使用 UTC 时间
var d3 = new Date("2018-02-19T12:00:00+08:00");
// Mon Feb 19 2018 12:00:00 GMT+0800 (GMT+08:00)
console.log("d3 = " + d3);

短日期

// MM/DD/YYYY
// 月份的前导 0 省略,可能出现问题
var d1 = new Date("02/19/2018");
// Mon Feb 19 2018 00:00:00 GMT+0800 (GMT+08:00)
console.log("d1 = " + d1);

长日期

// 长日期通常以 "MMM DD YYYY" 这样的语法来写:
var d1 = new Date("Feb 19 2018");
// Mon Feb 19 2018 00:00:00 GMT+0800 (GMT+08:00)
console.log("d1 = " + d1);

// 月和天能够以任意顺序出现:
var d2 = new Date("19 Feb 2018");
// Mon Feb 19 2018 00:00:00 GMT+0800 (GMT+08:00)
console.log("d2 = " + d2);

// 并且,月能够以全称 (January) 或缩写 (Jan) 来写:
var d3 = new Date("February 19 2018");
// Mon Feb 19 2018 00:00:00 GMT+0800 (GMT+08:00)
console.log("d3 = " + d3);

// 逗号会被忽略,且对大小写不敏感:
var d4 = new Date("FEBRUARY, 25, 2015");
// Wed Feb 25 2015 00:00:00 GMT+0800 (GMT+08:00)
console.log("d4 = " + d4);

完整日期

// JavaScript 接受“完整 JavaScript 格式”的日期字符串
var d1 = new Date("Mon Feb 19 2018 06:55:23 GMT+0100 (W. Europe Standard Time)");
// Mon Feb 19 2018 13:55:23 GMT+0800 (GMT+08:00)
console.log("d1 = " + d1);

// JavaScript 会忽略日期名称和时间括号中的错误
var d2 = new Date("Fri Mar 26 2018 09:56:24 GMT+0100 (Tokyo Time)");
// Mon Mar 26 2018 16:56:24 GMT+0800 (GMT+08:00)
console.log("d2 = " + d2);

总结

经测试,日期格式可以为以下,自由组合:

  • 2020-11-25
  • 2020/11/25
  • 2020,11,25
  • 2020-11-25 15:20:20

获取 Date 对象日期

方法 描述
getDate() 以数值返回天(1-31)
getDay() 以数值获取周名(0-6)
getFullYear() 获取四位的年(yyyy)
getHours() 获取小时(0-23)
getMilliseconds() 获取毫秒(0-999)
getMinutes() 获取分(0-59)
getMonth() 获取月(0-11)
getSeconds() 获取秒(0-59)
getTime() 获取时间戳(从 1970 年 1 月 1 日至今)

UTC 相关:

方法 描述
getUTCDate() 等于 getDate(),但返回 UTC 日期
getUTCDay() 等于 getDay(),但返回 UTC 日
getUTCFullYear() 等于 getFullYear(),但返回 UTC 年
getUTCHours() 等于 getHours(),但返回 UTC 小时
getUTCMilliseconds() 等于 getMilliseconds(),但返回 UTC 毫秒
getUTCMinutes() 等于 getMinutes(),但返回 UTC 分
getUTCMonth() 等于 getMonth(),但返回 UTC 月
getUTCSeconds() 等于 getSeconds(),但返回 UTC 秒

设置 Date 对象日期

方法 描述
setDate() 以数值(1-31)设置日
setFullYear() 设置年(可选月和日 (2020,11,25))
setHours() 设置小时(0-23)
setMilliseconds() 设置毫秒(0-999)
setMinutes() 设置分(0-59)
setMonth() 设置月(0-11)
setSeconds() 设置秒(0-59)
setTime() 设置时间(从 1970 年 1 月 1 日至今的毫秒数)

其他日期方法

方法 描述
toUTCString() 将日期转换为 UTC 字符串(Wed, 25 Nov 2020 05:41:47 GMT)
toDateString() 将日期转换为更易读的格式(Wed Nov 25 2020)
parse() 静态方法,返回时间戳,参数为 datestring
toTimeString() 把 Date 对象的时间部分转换为字符串(14:39:02 GMT+0800 (中国标准时间))
toDateString() 把 Date 对象的日期部分转换为字符串(Wed Nov 25 2020)
toLocaleDateString() 根据本地时间格式,把 Date 对象的日期部分转换为字符串(2020/11/25)
toLocaleTimeString() 根据本地时间格式,把 Date 对象的时间部分转换为字符串(下午2:39:28)
valueOf() date 的毫秒表示。返回值和方法 Date.getTime 返回的值相等。

常用函数总结

虽然现在处理日期方面已经有了很成熟的也很好用的库,例如 date-fns,但是在实际开发中,我们有时候可能并不需要整个库。总结一些方法。

获取当前时间戳

var t1 = Date.parse(new Date()); //精确到秒
var t2 = new Date().valueOf(); //精确到毫秒
var t3 = new Date().getTime(); //精确到毫秒
var t4 = +new Date(); //精确到毫秒
var t5 = Date.now(); //精确到毫秒

获取指定时间戳

var t1 = new Date("2019/10/24 08:00:00").getTime();
var t2 = new Date("2019-10-24 08:00:00").getTime();

获取当前时间的前一天/后一天的时间戳

var timestamp = +new Date() - 24*60*60*1000;
var timestamp = +new Date() + 24*60*60*1000;

今日零点时间戳

var timestamp = new Date(new Date().toLocaleDateString()).getTime();

今日最晚时间 23:59:59的时间戳

let timestamp = new Date(new Date().toLocaleDateString()).getTime()+24*60*60*1000-1;

获取当前时间的n天后的时间戳

/**
 * @param {number} n 天数
 * @returns {Number} 返回值为时间毫秒值
 */
function toNextTimes(n){
    let timestamp = +new Date() + n * 86400000;
    return timestamp;
}

本周第一天

/***
 *  @return {Date} WeekFirstDay 返回本周第一天的时间,时间和当前时间一样,日期为第一天
 *  2020-11-23T06:53:35.672Z
 */
function showWeekFirstDay() {
    let Nowdate = new Date();
    let WeekFirstDay = new Date(Nowdate - (Nowdate.getDay() - 1) * 86400000);
    return WeekFirstDay;
}

本周最后一天

/***
 *  @return {Date} WeekLastDay 返回本周最后一天的时间,时分秒还是当前时分秒
 */
function showWeekLastDay() {
    let Nowdate = new Date();
    let WeekFirstDay = new Date(Nowdate - (Nowdate.getDay() - 1) * 86400000);
    let WeekLastDay = new Date((WeekFirstDay / 1000 + 6 * 86400) * 1000);
    return WeekLastDay;
}

本月第一天

/***
 *  @return {Date} MonthFirstDay 返回本月第一天的时间,时分秒都为0
 */
function showMonthFirstDay() {
    let Nowdate = new Date();
    let MonthFirstDay = new Date(Nowdate.getFullYear(), Nowdate.getMonth());
    return MonthFirstDay;
}

本月最后一天

/***
 *  @return {Date} MonthLastDay 返回本月最后一天的时间
 */
function showMonthLastDay() {
    let Nowdate = new Date();
    let MonthNextFirstDay = new Date(Nowdate.getFullYear(), Nowdate.getMonth() + 1);
    let MonthLastDay = new Date(MonthNextFirstDay - 86400000);
    return MonthLastDay;
}

日期转时间戳

/**
 * @param {String} time - 日期字符串,如'2018-8-8','2018,8,8','2018/8/8', '2018-8-8 15:20:20'
 * @returns {Number} 返回值为时间毫秒值
 */
function timeToTimestamp(time) {
    let date = new Date(time);
    let timestamp = date.getTime();
    return timestamp;
}

格式化当前时间

/***
 *  @return {string} timeText 返回系统时间字符串
 *  2020年11月25日 星期三 15:13:41
 *  2020年1月2日 星期三 15:13:41
 */
function getdataTimeSec() {
    let time = new Date();
    let weekDay;
    let year = time.getFullYear();
    let month = time.getMonth() + 1;
    // month = check(month);
    let day = time.getDate();
    // day = check(day);
    //获取时分秒
    let h = time.getHours();
    let m = time.getMinutes();
    let s = time.getSeconds();
    //检查是否小于10
    h = check(h);
    m = check(m);
    s = check(s);
    let now_day = time.getDay();
    switch (now_day) {
        case 0: {
            weekDay = "星期日"
        }
            break;
        case 1: {
            weekDay = "星期一"
        }
            break;
        case 2: {
            weekDay = "星期二"
        }
            break;
        case 3: {
            weekDay = "星期三"
        }
            break;
        case 4: {
            weekDay = "星期四"
        }
            break;
        case 5: {
            weekDay = "星期五"
        }
            break;
        case 6: {
            weekDay = "星期六"
        }
            break;
        case 7: {
            weekDay = "星期日"
        }
            break;
    }
    // 2020年11月25日 星期三 15:13:41
    let timeText = year + "年" + month + "月" + day + "日" + " " + weekDay + " " + h + ":" + m +":" + s;
    return timeText;
}

//时间数字小于10,则在之前加个“0”补位。
function check(i) {   
    let num;  
    i < 10 ? num = "0" + i : num = i; 
    return num;
}

返回指定时间戳之间的时间间隔

/**
 *  @param {Number} startTime 开始时间的时间戳
 *  @param {Number} endTime 结束时间的时间戳
 *  @return {string} str 返回时间字符串
 *  前2年1月2天3时5分6秒
 *  前1月2天3时5分6秒
 */
function getTimeInterval(startTime, endTime) {
    let runTime = parseInt((endTime - startTime) / 1000);
    let year = Math.floor(runTime / 86400 / 365);
    runTime = runTime % (86400 * 365);
    let month = Math.floor(runTime / 86400 / 30);
    runTime = runTime % (86400 * 30);
    let day = Math.floor(runTime / 86400);
    runTime = runTime % 86400;
    let hour = Math.floor(runTime / 3600);
    runTime = runTime % 3600;
    let minute = Math.floor(runTime / 60);
    runTime = runTime % 60;
    let second = runTime;
    let str = '';
    if (year > 0) {
        str = year + '年';
    }
    if (year <= 0 && month > 0) {
        str = month + '月';
    }
    if (year <= 0 && month <= 0 && day > 0) {
        str = day + '天';
    }
    if (year <= 0 && month <= 0 && day <= 0 && hour > 0) {
        str = hour + '小时';
    }
    if (year <= 0 && month <= 0 && day <= 0 && hour <= 0 && minute > 0) {
        str = minute + '分钟';
    }
    if (year <= 0 && month <= 0 && day <= 0 && hour <= 0 && minute <= 0 && second > 0) {
        str += second + '秒';
    }
    str += '前';
    return str;
}

按类型格式化日期

/**
 * @param {*} date 具体日期变量
 * @param {string} dateType 需要返回类型
 * @return {string} dateText 返回为指定格式的日期字符串
 * date 取值与 new Date() 参数一样
 * dateType 可取值为: 
 *   yyyy-mm-dd
 *   yyyy.mm.dd
 *   yyyy-mm-dd MM:mm:ss
 *   mm-dd MM:mm:ss
 *   yyyy年mm月dd日 MM:mm:ss
 */
function getFormatDate(date, dateType) {
    let dateObj = new Date(date);
    let month = dateObj.getMonth() + 1;
    let strDate = dateObj.getDate();
    let hours = dateObj.getHours();
    let minutes = dateObj.getMinutes();
    let seconds = dateObj.getSeconds();
    if (month >= 1 && month <= 9) {
        month = "0" + month;
    }
    if (strDate >= 0 && strDate <= 9) {
        strDate = "0" + strDate;

    }
    if (hours >= 0 && hours <= 9) {
        hours = "0" + hours
    }
    if (minutes >= 0 && minutes <= 9) {
        minutes = "0" + minutes
    }
    if (seconds >= 0 && seconds <= 9) {
        seconds = "0" + seconds
    }

    let dateText = dateObj.getFullYear() + '年' + (dateObj.getMonth() + 1) + '月' + dateObj.getDate() + '日';
    if (dateType == "yyyy-mm-dd") {
        dateText = dateObj.getFullYear() + '-' + (dateObj.getMonth() + 1) + '-' + dateObj.getDate();
    }
    if (dateType == "yyyy.mm.dd") {
        dateText = dateObj.getFullYear() + '.' + (dateObj.getMonth() + 1) + '.' + dateObj.getDate();
    }
    if (dateType == "yyyy-mm-dd MM:mm:ss") {
        dateText = dateObj.getFullYear() + '-' + month + '-' + strDate + ' ' + hours + ":" + minutes + ":" + seconds;
    }
    if (dateType == "mm-dd MM:mm:ss") {
        dateText = month + '-' + strDate + ' ' + hours + ":" + minutes + ":" + seconds;
    }
    if (dateType == "yyyy年mm月dd日 MM:mm:ss") {
        dateText = dateObj.getFullYear() + '年' + month + '月' + strDate + '日' + ' ' + hours + ":" + minutes + ":" + seconds;
    }
    return dateText;
}
export function formatDate(date, fmt) {
  if (/(y+)/.test(fmt)) {
    fmt = fmt.replace(RegExp.$1, (date.getFullYear() + '').substr(4 - RegExp.$1.length));
  }
  let o = {
    'M+': date.getMonth() + 1,
    'd+': date.getDate(),
    'h+': date.getHours(),
    'm+': date.getMinutes(),
    's+': date.getSeconds()
  };
  for (let k in o) {
    if (new RegExp(`(${k})`).test(fmt)) {
      let str = o[k] + '';
      fmt = fmt.replace(RegExp.$1, (RegExp.$1.length === 1) ? str : padLeftZero(str));
    }
  }
  return fmt;
};

判断是否为闰年

/**
 * @param  {number} year 要判断的年份
 * @return {boolean} 返回布尔值
 */
function leapYear(year) {
    return !(year % (year % 100 ? 4 : 400));
}

返回两个年份之间的闰年

/**
 * @param  {number} start 开始年份
 * @param  {number} end 结束年份
 * @return {array}  arr 返回符合闰年的数组
 */
function leapYears(start, end) {
    let arr = [];
    for (var i = start; i < end; i++) {
        if (leapYear(i)) {
            arr.push(i);
        }
    }
    return arr;
}

判断时间格式是否有效

/**
 * 短时间,如 (10:24:06),一位或两位都行
 * @param  {string} str 需要验证的短时间
 * @return {boolean} 返回布尔值
 */
function isTime(str) {
    var a = str.match(/^(\d{1,2})(:)(\d{1,2})\2(\d{1,2})$/);
    if (a == null) {
        return false;
    }
    if (a[1] >= 24 || a[3] >= 60 || a[4] >= 60) {
        return false
    }
    return true;
}

/**
 * 短日期,形如 (2019-10-24,2020/11/12)
 * @param  {string} str 需要验证的短时间
 * @return {boolean} 返回布尔值
 */
function strDateTime(str) {
    var result = str.match(/^(\d{1,4})(-|\/)(\d{1,2})\2(\d{1,2})$/);
    if (result == null) return false;
    var d = new Date(result[1], result[3] - 1, result[4]);
    return (d.getFullYear() == result[1] && d.getMonth() + 1 == result[3] && d.getDate() == result[4]);
}

/**
 * 长日期时间,形如 (2019-10-24 10:24:06)
 * @param  {string} str 需要验证的短时间
 * @return {boolean} 返回布尔值
 */
function strDateTime(str) {
    var result = str.match(/^(\d{4})(-|\/)(\d{1,2})\2(\d{1,2}) (\d{1,2}):(\d{1,2}):(\d{1,2})$/);
    if (result == null) return false;
    var d = new Date(result[1], result[3] - 1, result[4], result[5], result[6], result[7]);
    return (d.getFullYear() == result[1] && (d.getMonth() + 1) == result[3] && d.getDate() == result[4] && d.getHours() == result[5] && d.getMinutes() == result[6] && d.getSeconds() == result[7]);
}

验证日期大小

/**
* 例:"2019-10-24" 和 "2019-10-25"
* @param  {string} d1需要验证的日期1
* @param  {string} d2需要验证的日期2
* @return {boolean} 返回布尔值
*/
function compareDate(d1, d2) {
    return ((new Date(d1.replace(/-/g, "\/"))) < (new Date(d2.replace(/-/g, "\/"))));
}

验证是不是今天

/**
 * @param  {*} val 需要验证的日期,new Date() 的参数
 * @return {boolean} 返回布尔值
 */
function isToday(val) {
    return new Date().toLocaleDateString() == new Date(val).toLocaleDateString();
}

验证传入的日期是否是昨天

/**
 * @param  {string} val 需要验证的日期,new Date() 的参数
 * @return {boolean} 返回布尔值
 */
function isYesterday(val) {
    var today = new Date();
    var yesterday = new Date(now - 1000 * 60 * 60 * 24);
    var test = new Date(val);
    if (yesterday.getYear() === test.getYear() && yesterday.getMonth() === test.getMonth() && yesterday.getDate() === test.getDate()) {
        return true;
    } else {
        return false;
    }
}

设置几天后的日期

/**
 * @param  {*} date 起始日期,new Date() 参数
 * @param  {number} day 向后的天数
 * @return {string} 返回想要得到的日期,2020-02-01
 */
function convertDate(date, day) {
    let tempDate = new Date(date);
    tempDate.setDate(tempDate.getDate() + day);
    let Y = tempDate.getFullYear();
    let M = tempDate.getMonth() + 1 < 10 ? '0' + (tempDate.getMonth() + 1) : tempDate.getMonth() + 1;
    let D = tempDate.getDate() < 10 ? '0' + (tempDate.getDate()) : tempDate.getDate();
    let result = Y + "-" + M + "-" + D
    return result;
}