Hibop/Hibop.github.io

关于js时间相关小结

Opened this issue · 0 comments

Hibop commented

写在前面的,几个标准

  • 时间标准:GMT UTC ISO Z
    GMT即「格林威治标准时间」(Greenwich Mean Time,简称G.M.T.),指位于英国伦敦郊区的皇家格林威治天文台的标准时间,因为本初子午线被定义为通过那里的经线。然而由于地球的不规则自转,导致GMT时间有误差,因此目前已不被当作标准时间使用
    UTC是最主要的世界时间标准,是经过平均太阳时(以格林威治时间GMT为准)、地轴运动修正后的新时标以及以「秒」为单位的国际原子时所综合精算而成的时间。UTC比GMT来得更加精准。其误差值必须保持在0.9秒以内,若大于0.9秒则由位于巴黎的国际地球自转事务**局发布闰秒,使UTC与地球自转周期一致。不过日常使用中,GMT与UTC的功能与精确度是没有差别的。协调世界时区会使用“Z”来表示。而在航空上,所有使用的时间划一规定是协调世界时。而且Z在无线电中应读作“Zulu”(可参见北约音标字母),协调世界时也会被称为“Zulu time”。
    ISO是国际标准化组织的国际标准ISO 8601是日期和时间的表示方法,时间后面是带有时区的,
    Z 表示本初时
    +1:00 东1区。
    -1:00 西1区
// YYYY-MM-DDThh:mm:ss ± timezone(时区用HH:MM表示)
1997-07-16T08:20:30Z
// “Z”表示UTC标准时区,即"00:00",所以这里表示零时区的`1997年7月16日08时20分30秒`
//转换成位于东八区的北京时间则为`1997年7月17日16时20分30秒`
1997-07-16T19:20:30+01:00
// 表示东一区的1997年7月16日19时20秒30分,转换成UTC标准时间的话是1997-07-16T18:20:30Z
  • Unix后台时间戳&&前端时间戳
    Unix时间戳表示当前时间到1970年1月1日00:00:00 UTC对应的秒数
    JavaScript内的时间戳指的是当前时间到1970年1月1日00:00:00 UTC对应的毫秒数,和unix时间戳不是一个概念,后者表示秒数,差了1000倍, 所以后台时间一般要1000转化。

  • 时间格式: 时间戳;时间实例对象new Date()

  • 时间读写: 实例对象上面绑定读取getXXX和修改setXXX方法
    image

new Date()七种传参形式

和jquery的$函数类似: 函数重载实现多态

  • new Date("month dd,yyyy hh:mm:ss");

  • new Date("month dd,yyyy"); // string

  • new Date("yyyy/MM/dd hh:mm:ss"); // string

  • new Date("yyyy/MM/dd"); // string

  • new Date(yyyy,month,dd,hh,mm,ss); // number

  • new Date(yyyy,month,dd); // number
    // 注意month: 0~11 分别代表1-12月份

  • new Date(ms); // 时间戳
    栗子:

new Date("September 16,2016 14:15:05");

new Date("September 16,2016");

new Date("2016/09/16 14:15:05");

new Date("2016/09/16");

new Date(2016,8,16,14,15,5); // 月份从0~11

new Date(2016,8,16);

new Date(1474006780);

常见应用场景

1. 将时间戳转换成日期格式,然后格式化string化后做界面显示

// 比如需要这样的格式 yyyy-MM-dd hh:mm:ss
var date = new Date(1398250549490);
Y = date.getFullYear() + '-';
M = (date.getMonth()+1 < 10 ? '0'+(date.getMonth()+1) : date.getMonth()+1) + '-';
D = date.getDate() + ' ';
h = date.getHours() + ':';
m = date.getMinutes() + ':';
s = date.getSeconds(); 
console.log(Y+M+D+h+m+s);

一般在实际生产中会抽出一个format函数, 绑定到Date.prototype或者export出去按需引入

// @params format 'YYYY-MM-DD hh:mm:ss'
export function formatDate(date, format) {
  let time = {
    'M+': date.getMonth() + 1,
    'D+': date.getDate(),
    'h+': date.getHours(),
    'm+': date.getMinutes(),
    's+': date.getSeconds(),
    'q+': Math.floor((date.getMonth() + 3) / 3),
    'S+': date.getMilliseconds()
  };

  if (/(Y+)/i.test(format)) {
    format = format.replace(RegExp.$1, (date.getFullYear() + '').substr(4 - RegExp.$1.length));
  }

  for (let k in time) {
    if (new RegExp('(' + k + ')').test(format)) {
      format = format.replace(RegExp.$1, RegExp.$1.length === 1 ? time[k] : ('00' + time[k]).substr(('' + time[k]).length));
    }
  }
  return format;
}

从‘2018-06-07’ ==> '20180607'
只需要formatedDate.replace(/-/g, '') 或者 formateDate(date, 'YYMMDD');

2. 日期格式转时间戳

// 也很简单
var strtime = '2014-04-23 18:55:49:123';
var date = new Date(strtime); //传入一个时间格式,如果不传入就是获取现在的时间了,这样做不兼容火狐。
// 可以这样做
var date = new Date(strtime.replace(/-/g, '/'));

// 有三种方式获取
time1 = date.getTime();
time2 = date.valueOf();
time3 = Date.parse(date);

/* 
三种获取的区别:
第一、第二种:会精确到毫秒
第三种:只能精确到秒,毫秒将用0来代替
比如上面代码输出的结果(一眼就能看出区别):
1398250549123
1398250549123
1398250549000 
*/

3. 获取一段时间(非时间点);

一定注意时间端点判断(月头月尾、年头年尾)问题
一般会综合使用到date.setXXX

  • data.setDate(0);可以得到上个月多少天
  • data.setMonth(-1); 去年的最后一个月
    这些0和-1会得到意想不到额捷径作用
    我们可以巧用Set方法的特性,set*方法的参数都会自动折算。以setDate为例,如果参数超过当月的最大天数,则向下一个月顺延,如果参数是负数,表示从上个月的最后一天开始减去的天数。
var d1 = new Date('January 6, 2013');

d1.setDate(32) // 1359648000000
d1 // Fri Feb 01 2013 00:00:00 GMT+0800 (CST)

var d2 = new Date ('January 6, 2013');

d.setDate(-1) // 1356796800000
d // Sun Dec 30 2012 00:00:00 GMT+0800 (CST)

扩展相关

时间相关的npm包

  • momentjs: Parse, validate, manipulate, and display dates in javascript
    它很好用,然而它的体态却十分丰满(丰盈),没念及此,是否有重新造轮子的冲动?
  • SpaceTime
  • date-fns
  • DAY.js: Fast 2kB alternative to Moment.js with the same modern API