Javascript Date对象

479 阅读11分钟

Date - 日期

Date对象表示从1970年1月1日(UTC)到某个时刻的时间,提供处理日期和时间的方法(本地时间和UTC时间)。

常见时间

一般在项目开发中主要使用的都是本地时间(计算机所在地的时间),对于我们来说就是北京时间。

UTC

UTC(Universal Time Coordinated) - 协调世界时、世界标准时间: 是以原子时秒长为基础,在时刻上尽量接近于世界时的一种时间计量系统。

ISO

ISO(International Organization for Standardization) - 国际标准组织: 以国际标准ISO 8601表示日期和时间

GMT

GMT(Greenwich Mean Time) - 格林尼治时间:格林尼治所在地的标准时间,也是表示地球自转速率的一种形式。

CST

CST(Chinese standard time) - 北京时间: 北京时间是中国采用国际时区东八时区的区时作为标准时间,中国全境(大陆、港澳、台湾)均采取北京时间(UTC+8),即北京时间比UTC晚8个小时。

构造函数

Date构造函数创建一个Date的实例对象,默认是UTC,UTC早于北京时间8小时。

// 1. 不接收参数时, 创建现在时间的date对象
console.log(new Date()); // 2021-12-25T04:00:00.000Z

// 2. 传入时间戳(毫秒数),计算从1970年1月1日(UTC)以来的时间的毫秒数
console.log(new Date(1640404800000)); // 2021-12-25T04:00:00.000Z

// 3. 传入date对象
const date = new Date();
const copyDate = new Date(date);

// 4. 传入的能被Date.parse的字符串
console.log(new Date('December 25, 2021 12:00:00')); // 2021-12-25T04:00:00.000Z
console.log(new Date('2021-12-25T 12:00:00Z'));      // 2021-12-25T04:00:00.000Z
console.log(new Date('12/25/2021 12:00:00'));        // 2021-12-25T04:00:00.000Z

// 5. new Date(year,monthIndex,[,date,hours,minutes,seconds,milliseconds])
// 除了年、月是必填,其他的是可选
// 0到99会被映射至1900年至1999年
// 注意: 月份的范围是0~11,0是1月,11是12月
// date默认为1, hours、minutes、seconds、milliseconds 默认为0
console.log(new Date(2021,11)); // 2021-11-30T16:00:00.000Z
console.log(new Date(2021,11,25,12,00,00)); // 2021-12-25T04:00:00.000Z

静态方法

// 1. 1970年1月1日(UTC)到当前时间的毫秒数,记住是毫秒数
console.log(Date.now()); // 1640455537359

// 2. Date.parse 解析一个表示某个日期的字符串(符合RFC2822/IETF语法),并返回从1970年1月1日(UTC)到该日期对象(该日期对象的UTC时间)的毫秒数
// 如果日期字符串无法解析, 则返回NaN
// 一般日期字符串都是通过生成的,可以直接使用

// ISO日期格式 - 具体时间可以没有,但是必须有日期
console.log(Date.parse('2021-12-25'));  // 1640390400000
console.log(Date.parse('2021-12-25T12:00:00'));  // 1640404800000

// RFC2822 / IETF 日期格式
console.log(Date.parse('Sat Dec 25 2021 12:00:00 GMT+0800'));    // 1640404800000
console.log(Date.parse('December 25, 2021 12:00:00'));           // 1640404800000

// 3. Date.UTC 获取从1970年1月1日(UTC)到指定时间(UTC时间)的毫秒数
const UTCChristmas = Date.UTC(2021,11,25); 
console.log(new Date(UTCChristmas).toLocaleString()); // 2021/12/25 上午8:00:00

// 记住,构造函数是获取 从1970年1月1日(UTC)到指定时间(本地时间)的毫秒数,对应的UTC时间还得往前8小时
const LocaleChristmas = new Date(2021,11,25).getTime();

console.log(new Date(LocaleChristmas).toLocaleString()); // 2021/12/25 上午12:00:00, 上午12:00表示的就是0点

// 解析: 使用构造函数创建的是本地时间的2021-12-25 00:00:00,对应的UTC时间得往前8小时,也就是 2021-12-24 16:00:00
//      而Date.UTC创建的是UTC时间的2021-12-25 00:00:00,对应的本地时间还得往后8小时,也就是2021-12-25 08:00:00

实例方法

读取时间

实例上有获取时间具体信息的方法,可以获取本地时间,也可以获取UTC时间,以下展示本地时间的获取方式。

const Christmas = new Date(2021,11,25,12,00,00);

// 1. getTime 返回从1970年1月1日0时0分0秒(UTC)到date实例时间的毫秒数
console.log('获取时间毫秒表示:',Christmas.getTime());            // 获取时间毫秒表示: 1640404800000

// 2. getFullYear获取当前时间年份
console.log('获取本地时间年份:',Christmas.getFullYear());        // 获取年份: 2021 

// 3. getMonth获取当前时间月份(0~11,0表示1月,11表示12月,为了正常显示,要+1)
console.log('获取本地时间月份:',Christmas.getMonth()+1);         // 获取月份: 12

// 4. getDate获取当前时间日期
console.log('获取本地时间日期:',Christmas.getDate());            // 获取日期: 25

// 5. getHours获取当前时间的小时
console.log('获取本地时间时钟:',Christmas.getHours());           // 获取时钟: 12

// 6. getMinutes获取当前时间的分钟
console.log('获取本地时间分钟:',Christmas.getMinutes());         // 获取分钟: 0

// 7. getSeconds获取当前时间的秒钟
console.log('获取本地时间秒钟:',Christmas.getSeconds());         // 获取秒钟: 0

// 8. getMilliseconds获取当前时间的毫秒钟
console.log('获取本地时间毫秒钟:',Christmas.getMilliseconds());  // 获取毫秒数: 0

// 9. getDay获取当前时间在这周处于第几天(1~7,也就是周一到周日)
console.log('获取本地时间周几:',Christmas.getDay());             // 获取天数: 6

// 10. getTimezoneOffset获取UTC和当前时间的时差(单位是分钟),我们是北京时间, 和UTC时差为8个小时,也就是480分钟
// 也就是用UTC的时间 - 当前时区的时间
console.log('获取时差:',Christmas.getTimezoneOffset());  // 获取时差: -480

// 获取UTC时间
// 与获取本地时间同理,一定要记住,UTC的时间是早于北京时间8个小时
console.log('获取UTC年份:', Christmas.getUTCFullYear());      // 获取UTC年份: 2021
console.log('获取UTC月份:', Christmas.getUTCMonth());         // 获取UTC月份: 11
console.log('获取UTC日期:', Christmas.getUTCDate());          // 获取UTC日期: 25
console.log('获取UTC时钟:', Christmas.getUTCHours());         // 获取UTC时钟: 4
console.log('获取UTC分钟:', Christmas.getUTCMinutes());       // 获取UTC分钟: 0
console.log('获取UTC秒钟:', Christmas.getUTCSeconds());       // 获取UTC秒钟: 0
console.log('获取UTC周几:', Christmas.getUTCDay());           // 获取UTC周几: 6
console.log('获取UTC毫秒钟:',Christmas.getUTCMilliseconds());  // 获取UTC毫秒钟: 0
设置时间
const Christmas = new Date();
Christmas.setFullYear(2021);              // 设置年份 
Christmas.setMonth(11);                   // 设置月份, 0~11,0是1月,11是12月
Christmas.setDate(25);                    // 设置日期
Christmas.setHours(12);                   // 设置时钟
Christmas.setMinutes(0);                  // 设置分钟
Christmas.setSeconds(0);                  // 设置秒钟
Christmas.setMilliseconds(0);             // 设置毫秒

// 也可以直接设置从从1970年1月1日(UTC)开始的毫秒数, 很少用到
// Christmas.setTime(1640404800000);      

console.log(Christmas);  // 2021-12-25T04:00:00.000Z

// UTC的方法也一样,就不演示了
输出时间
const Christmas = new Date(2021,11,25,12,00,00);

console.table({
  // 1. toLocaleDateString 返回日期对象日期部分的字符串
  'toLocaleDateString': Christmas.toLocaleDateString(), // 2021/12/25

  // 2. toLocaleTimeString 返回日期对象时间部分的字符串
  'toLocaleTimeString': Christmas.toLocaleTimeString(),  // 下午12:00:00

  // 3. toLocaleString 返回该日期对象的日期和时间字符串, 相当于 toLocaleDateString + ' ' + toLocaleTimeString
  'toLocaleString': Christmas.toLocaleString(),         // 2021/12/25 下午12:00:00

  // 6. toDateString 返回日期对象日期部分的美式英语日期格式的字符串
  'toDateString': Christmas.toDateString(),             // Sat Dec 25 2021

  // 7. toTimeString 返回日期对象时间部分的美式英语日期格式的字符串
  'toTimeString': Christmas.toTimeString(),             // 12:00:00 GMT+0800 (中国标准时间)

  // 8.Date实例重写了toString方法,返回日期对象日期和时间的美式英语日期格式的字符串
  // 相当于 toDateString + ' ' +  toTimeString
  'toString': Christmas.toString(),                    // Sat Dec 25 2021 12:00:00 GMT+0800 (中国标准时间)

  // 9. toUTCString 返回UTC时间的美式英语日期格式的字符串
  'toUTCString': Christmas.toUTCString(),               // Sat, 25 Dec 2021 04:00:00 GMT
  
  // 10. toISOString 返回ISO格式的字符串: YYYY-MM-DDTHH:mm:ss.sssZ
  // 时区总是UTC(协调世界时),加一个后缀“Z”标识
  'toISOString': Christmas.toISOString(),               // 2021-12-25T04:00:00.000Z

  // 11. toJSON 返回一个JSON格式字符串(使用 toISOString())
  'toJSON': Christmas.toJSON(),                         // 2021-12-25T04:00:00.000Z

  // 12. valueOf 返回和getTime一样的毫秒数
  'valueoOf': Christmas.valueOf(),                       // 1640404800000
});           

console.log(Christmas.toISOString() === Christmas.toJSON()); // true

时间矫正

通过构造函数和setXXX的形式设置时间时,如果传入的日期超出,则会对时间进行矫正。

// 1. 元旦节 - 2021/1/1
const newYear = new Date(2021,0,1);
console.log(newYear.toLocaleString()); // 2021/1/1 上午12:00:00

/// 这也是元旦 - 2020/12/32 因为12月只有31天, 32天则是下一个月的第一天,就变成 2021/1/1
const newYear2 = new Date(2020,11,32);
console.log(newYear2.toLocaleString()); // 2021/1/1 上午12:00:00

应用

Date的应用中,最经常用到的无非就是时间格式化和时间差值的计算了。

  • 时间格式化: 当以上date实例提供的输出方法不能够满足我们的需求的时候,就需要手动的获取各个属性,然后根据需求做相应的操作。
  • 时间差值: 计算两个日期之间的时间差,通过获取两个日期的毫秒数,进行减法运(-),就可以获取两个日期之间间隔的毫秒数,然后转换成需要的单位。
实战

假设现在正在完成一个聊天的项目,涉及到聊天消息相关的功能,现在有个需求,编写一个工具类函数,接收一个date对象,并根据和当前时间的差值,返回不同的结果。

  • 过去30秒内, 返回'刚刚'
  • 30秒以上,但是是同一天, 返回格式 'HH:mm',如 '16:00'
  • 昨天的date对象, 返回 '昨天 HH:mm', 如 '昨天 16:00'
  • 昨天以前,但是是同一年, 返回格式 'X月X日 HH:mm',如 '12月25日 16:00'
  • 去年以及再往前, 返回 'XXXX年X月X日 HH:mm', 如 '2016年12月11日 16:00'
/**
 * 
 * @param {Date} date 日期对象
 * @returns {String} 格式化后的日期字符串
 */
function dateFormat(date){
  // 需要先获取当前时间和接收时间的 date对象和毫秒数
  // 毫秒数用来计算差值,date对象用来获取年/月/日/时/分
  const now = new Date();  // 当前时间的date对象
  const nowTime = Date.now(); // 当前时间的毫秒表示
  const dateTime = date.getTime(); // 接收的date对象的毫秒数
  const diff = dateTime - nowTime; // 时间差值, 单位是毫秒

  // dateMap用于获取存储date的年/月/日/时/分, 目前用到的就这些,根据需要存储
  const dateMap = {
    year: date.getFullYear(),
    mouth: date.getMonth()+1,
    day: date.getDate(),
    hour: date.getHours(),
    minute: date.getMinutes(),
  };
  
  // 这个是昨天的date对象,用于等会获取昨天的日期部分
  const yesterday = new Date(nowTime - 24 * 3600 * 1000);

  // 根据年/月/日/时/分和时间差值来判断两个时间之间的关系
  // 1. 时间间隔小于等于 30秒
  if(Math.abs(diff) <= 30000 ) return '刚刚';
  // 2. 时间间隔大于30秒,但是是同一天
  // 通过比较now(现在)的日期部分和date对象的日期部分
  else if (now.toLocaleDateString() === date.toLocaleDateString()){
    const {hour, minute} = dateMap;
    return `${hour}:${minute}`;
  // 3. 昨天的消息, 比较昨天的日期部分和 date的日期部分
  }else if(yesterday.toLocaleDateString() === date.toLocaleDateString()){
    const { hour, minute } = dateMap;
    return `昨天 ${hour}:${minute}`;
  // 4. 年份相同(同年),但是不是今天、不是昨天(昨天和今天在上面就return了)
  }else if(now.getFullYear() === dateMap.year){
    const {mouth, day, hour, minute} = dateMap;
    return `${mouth}${day}${hour}:${minute}`;
  // 5. 年份不同
  }else{
    const {year,mouth, day, hour, minute} = dateMap;
    return `${year}${mouth}${day}${hour}:${minute}`
  }
}

// 因为是以当前时间作为参照,所以不同时间打印出来的也是不一样的,关注返回格式即可
console.log(dateFormat(new Date(new Date().getTime()-9000)));         // 刚刚, 9秒前
console.log(dateFormat(new Date(new Date().getTime()-3600000)));      // 10:55, 一小时前
console.log(dateFormat(new Date(new Date().getTime()-24 * 3600000))); // 昨天 11:55, 一天前
console.log(dateFormat(new Date(new Date().getTime()-48 * 3600000))); // 12月25日 11:55, 两天前
console.log(dateFormat(new Date(new Date().getTime()-365 * 24 * 3600000)));  // 2020年12月27日 11:55, 365天前