Date填坑记

简介: 平时在项目开发中,经常会遇到诸多的时间处理,最开始选择moment,后来发现,其实项目中需要处理函数的场景比较单一,没必要引入moment,于是就开始了处理date的漫漫填坑之路。

平时在项目开发中,经常会遇到诸多的时间处理,最开始选择moment,后来发现,其实项目中需要处理函数的场景比较单一,没必要引入moment,于是就开始了处理date的漫漫填坑之路。

填坑之旅

坑一

1

首先看一下上面这段代码,我的本意是生成2018-06-17 00:00:00这个时间,但是运行的结果却是早上8点。那么理清这个的原因就涉及GMT、UTC的概念。

GMT(格林尼治标准时间)是一些欧洲和非洲国家正式使用的时间,UTC是国际标准。这两个时间一般情况是相等的。中国处于东八区,与UTC时间相差8个小时,也就是说UTC时间00:00:00的时候,我们的时间是08:00:00。

为了避免这种现象,对于任何的输入,都统一生成一个UTC时间,那么新建一个date函数,这个Date函数用于根据传入的时间模板,生成一致的时间。'yyyy-MM-dd'格式的时间模板new出来的date是本地时间,所以用正则表达式匹配一下/^\d{4}(-\d{2}){0,2}$/.test(date)。重写一个Date构造函数,用于根据输入的时间模板生成一致的时间。

    var localDate = new Date(date)
    if (date && /^\d{4}(-\d{2}){0,2}$/.test(date))  {
      let timeZoneOffset = localDate.getTimezoneOffset()
      let utcTimeStamp = localDate.getTime() + timeZoneOffset * 60 * 1000
      return new Date(utcTimeStamp)
    }
复制代码

坑二

IOS上执行new Date('1990-01-04 09:09:09')会得到invilaid date。处理方法是对1990-01-04转换成1990/01/04的格式

后端为了区分时间和普通的字符串,对时间模板通常会加一个T分隔时间,如'1990-01-04T10:10:00'。 js移动端运行结果

PC端运行结果

ISO 8601的标准格式是:YYYY-MM-DDTHH:mm:ss.sssZ。T表示UTC,所以手机端运行出的时间会在加上8个小时的时差。

此外,

考虑到后端用T只是用于区分普通字符串和时间,所以此处将T替换成空格。 完整的生成Date的函数


  function DateUTC (date) {
    let isDate = (typeof date === 'object') && (date instanceof Date)
    if (isDate) return date
    let localDate
    
    if (Object.prototype.toString.apply(date).slice(-7, -1) === 'String') {
      date = date.replace(/T/, ' ').replace(/-/g, '/')
    }
    try {
      localDate = date === undefined ? new Date() : new Date(date)
    } catch (e) {
      console.error(e)
    }
    
    var localDate = new Date(date)
    if (date && /^\d{4}(-\d{2}){0,2}$/.test(date))  {
      let timeZoneOffset = localDate.getTimezoneOffset()
      let utcTimeStamp = localDate.getTime() + timeZoneOffset * 60 * 1000
      return new Date(utcTimeStamp)
    }
    return localDate
  }
复制代码

常用的功能

format,格式化时间

    // 默认的格式是 'yyyy-MM-dd'
  function format (date, form = 'yyyy-MM-dd') {
    date = DateUTC(date)
    if (!form) return date
    let year = date.getFullYear()
    let month = leftPad(date.getMonth() + 1)
    let day = leftPad(date.getDate())
    let hours = leftPad(date.getHours())
    let minutes = leftPad(date.getMinutes())
    let seconds = leftPad(date.getSeconds())
    return form.replace('yyyy', year).replace('MM', month).replace('dd', day).replace('HH', hours).replace('mm', minutes).replace('ss', seconds)
  }
复制代码

diff,计算两个时间差

  /**
   * 
   * @param {*} time1 a Date object or Date params
   * @param {*} time2 a Date object or Date params
   * @param {*} unit can be one of ['year', 'month', 'day', 'hour', 'minute', 'second']
   * @param {*} exact get exact day diff
   */
  function diff (time1, time2, unit='day', exact = false) {
    let date1 = DateUTC(time1)
    let date2 = DateUTC(time2)
    if (unit === 'year') {
      return date2.getFullYear() - date1.getFullYear()
    }
    if (unit === 'month') {
      let diffYear = date2.getFullYear() - date1.getFullYear()
      return (date2.getMonth() - date1.getMonth()) + 12 * diffYear
    }
    if (!exact && unit === 'day') {
      date1 = DateUTC(format(date1, 'yyyy-MM-dd'))
      date2 = DateUTC(format(date2, 'yyyy-MM-dd'))
    }
    let timeStampUnit = getTimeStampUnit(unit)
    return parseInt((date2.getTime() - date1.getTime()) / timeStampUnit)
  }
复制代码

dateFrom,根据给定的时间time,返回另一个时间

  /**
   * 
   * @param {*} date a Date object or Date params
   * @param {*} diff 
   * @param {*} unit can be one of ['year', 'month', 'day', 'hour', 'minute', 'second']
   * for example: dateFrom('2012-02-29', 12, 'month') // Fri Mar 01 2013 00:00:00 GMT+0800 (CST)
   */
  function dateFrom(time, diff, unit='day') {
    let date = DateUTC(time)
    if (unit === 'year') {
      let year =  date.getFullYear() + diff
      return DateUTC(date.setFullYear(year))
    }
    if (unit === 'month') {
      let month = date.getMonth() + diff
      return DateUTC(date.setMonth(month))
    }
    let timeStampUnit = getTimeStampUnit(unit)
    return DateUTC(date.getTime() + diff * timeStampUnit)
  }
复制代码

dateTemplate,时间模板函数

  /**
   * a date template which can help you new a Date
   */
  function dateTemplate ({ date, diff, form, unit } = {}) {
    var _date = !date ? DateUTC() : date
    if (diff) {
      _date = dateFrom(_date, diff, unit)
    }
    if (form) {
      _date = format(_date, form)
    }
    return _date
  }
复制代码

完整代码

(function ($) {
function DateUTC (date) {
  if (arguments.length === 0) return new Date()
  if (isDate(date)) return date
  let localDate
  if (Object.prototype.toString.apply(date).slice(-7, -1) === 'String') {
    date = date.replace(/T/, ' ').replace(/-/g, '/')
  }
  try {
    localDate = new Date(date)
  } catch (e) {
    console.error(e)
  }
  // 匹配yyyy-MM-dd | yyyy-MM
  if (date && /^\d{4}(-\d{2}){0,2}$/.test(date))  {
    let timeZoneOffset = localDate.getTimezoneOffset()
    let utcTimeStamp = localDate.getTime() + timeZoneOffset * 60 * 1000
    return new Date(utcTimeStamp)
  }
  return localDate
}

function format (date, form = 'yyyy-MM-dd') {
  date = DateUTC(date)
  if (!form) return date
  let year = date.getFullYear()
  let month = leftPad(date.getMonth() + 1)
  let day = leftPad(date.getDate())
  let hours = leftPad(date.getHours())
  let minutes = leftPad(date.getMinutes())
  let seconds = leftPad(date.getSeconds())
  return form.replace('yyyy', year).replace('MM', month).replace('dd', day).replace('HH', hours).replace('mm', minutes).replace('ss', seconds)
}

/**
 * 
 * @param {*} time1 a Date object or Date params
 * @param {*} time2 a Date object or Date params
 * @param {*} unit can be one of ['year', 'month', 'day', 'hour', 'minute', 'second']
 * @param {*} exact get exact day diff
 */
function diff (time1, time2, unit='day', exact = false) {
  let date1 = DateUTC(time1)
  let date2 = DateUTC(time2)
  if (unit === 'year') {
    return date2.getFullYear() - date1.getFullYear()
  }
  if (unit === 'month') {
    let diffYear = date2.getFullYear() - date1.getFullYear()
    return (date2.getMonth() - date1.getMonth()) + 12 * diffYear
  }
  if (!exact && unit === 'day') {
    date1 = DateUTC(format(date1, 'yyyy-MM-dd'))
    date2 = DateUTC(format(date2, 'yyyy-MM-dd'))
  }
  let timeStampUnit = getTimeStampUnit(unit)
  return parseInt((date2.getTime() - date1.getTime()) / timeStampUnit)
}
/**
 * 
 * @param {*} date a Date object or Date params
 * @param {*} diff 
 * @param {*} unit can be one of ['year', 'month', 'day', 'hour', 'minute', 'second']
 * for example: dateFrom('2012-02-29', 12, 'month') // Fri Mar 01 2013 00:00:00 GMT+0800 (CST)
 */
function dateFrom(time, diff, unit='day') {
  let date = DateUTC(time)
  if (unit === 'year') {
    let year =  date.getFullYear() + diff
    return DateUTC(date.setFullYear(year))
  }
  if (unit === 'month') {
    let month = date.getMonth() + diff
    return DateUTC(date.setMonth(month))
  }
  let timeStampUnit = getTimeStampUnit(unit)
  return DateUTC(date.getTime() + diff * timeStampUnit)
}

/**
 * a date template which can help you new a Date
 */
function dateTemplate ({ date, diff, form, unit } = {}) {
  var _date = !date ? DateUTC() : date
  if (diff) {
    _date = dateFrom(_date, diff, unit)
  }
  if (form) {
    _date = format(_date, form)
  }
  return _date
}


function isDate (date) {
  return date instanceof Date
}

function leftPad (val) {
  return val.toString().padStart(2, '0')
}

function getTimeStampUnit (unit) {
  switch (unit) {
    case 'day':
      return 1000 * 3600 * 24
    case 'hour':
      return  1000 * 3600
    case 'minute':
      return 1000 * 60
    case 'second':
      return 1000
      break
    default:
      return 1
  }
}

$.format = format
$.diff = diff
$.DateUTC = DateUTC
$.dateFrom = dateFrom
$.dateTemplate = dateTemplate
})(window.$);
复制代码


原文发布时间为:2018年06月27日

原文作者:因

本文来源: 掘金  如需转载请联系原作者
相关文章
|
3月前
|
Java
在java java.util.Date 已知逝去时间怎么求年月日
在java java.util.Date 已知逝去时间怎么求年月日
23 0
|
12天前
|
编译器 C++
【C++初阶】4. Date类的实现
【C++初阶】4. Date类的实现
35 1
|
2月前
|
安全
第十四届蓝桥杯集训——Date与Calendar函数
第十四届蓝桥杯集训——Date与Calendar函数
9 0
|
3月前
|
Android开发 iOS开发
重新学习一下new Date()
重新学习一下new Date()
|
9月前
|
存储 安全 架构师
Java开发篇 - 还在为计算2个日期间隔的天数纠结?是时候换掉java.util.Date
即然Date及Calendar在计算时间间隔或者其他场景下都比较麻烦,那么有没有更好的API使用呢?当然是有的,JDK1.8中,就更新了新的日期/时间处理工具类。具体的包在java.time目录下,有兴趣的小伙伴可以打开进行查看。
268 0
|
9月前
|
消息中间件 Dubbo NoSQL
老板,JDK8的日期、时间函数我不熟悉?
介绍JDK 8中的新日期工具类,及整理成PDF文档
53 0
|
10月前
|
存储 算法 Java
数据结构算法学习打卡week2 (Java)
数据结构算法学习打卡week2 (Java)
53 0
|
10月前
|
C++
【C++日期类完整版(Date类)】
【C++日期类完整版(Date类)】
|
SQL 安全 Java
java Date 和 Calendar类 万字详解(通俗易懂)
java API专题——常用类Date和Calender类 内容分享。
86 0
java Date 和 Calendar类 万字详解(通俗易懂)
|
Java
《备战蓝桥》之日期问题(Java)
本篇文章是针对蓝桥杯中经常出现的日期问题进行的一个总结,在我们平常判断日期的合法性时,需要很多判断才能实现,先是判断月份和日期的合法性,再去判断是否时闰年,但我们如果利用Java中的类库就可以很快判断出日期是否合法,下边我会先介绍如何判断日期合法性,再针对几道例题进行对应练习。
153 0