时间和时间戳的概念理解及转换

873 阅读11分钟

Vue 中使用 moment 处理时间格式

  1. npm install moment --save
  2. 在入口文件 main.js 中导入并使用
    import moment from 'moment'
    Vue.prototype.$moment = moment
  3. 汉化,否则显示日期格式是国外的日期格式
    moment.locale("zh-CN")
  4. 使用 this.$moment()统一处理

常见的几种时间格式

  1. ISO 8601
    格式:YYYY-MM-DDTHH:mm:ss[.mmm]TZD
    举例:2023-10-16T11:37:34.291+08:00
  2. Unix 时间戳
    1. 13 位数的时间戳是以毫秒为单位,即毫秒时间戳
      举例:1697005688175
    2. 10 位数的时间戳是以秒为单位,即秒时间戳
      举例:1642662900
  3. 格林威治标准时间(GMT)
    格式:new Date()的时间格式
    举例:Mon Dec 04 2017 00:00:00 GMT+0800 (中国标准时间), 即北京时间 2017 年 12 月 4 日 00:00:00(格林尼治所在地的标准时间加 8 小时)
  4. 世界协调时间(或称世界标准时间 UTC)
    格式:new Date().toUTCString()
    举例:Mon, 29 Apr 2019 09:52:21 GMT
    本质为比 GMT 更为精确的世界时间标准

概念

  1. Unix 时间戳的概念
    1. 概念
      格林威治时间 1970 年 01 月 01 日 00 时 00 分 00 秒(北京时间 1970 年 01 月 01 日 08 时 00 分 00 秒)起至现在的总秒数
    2. 获取时间戳(毫秒)的方法
      1. Date.now()返回自 UNIX 纪元开始(1970 年 1 月 1 日 00:00:00(UTC))到当前时间的毫秒数(毫秒时间戳)
      2. new Date().getTime() 返回自 UNIX 纪元开始(1970 年 1 月 1 日 00:00:00(UTC))到当前时间的毫秒数(毫秒时间戳)
      3. new Date().valueOf() 返回自 UNIX 纪元开始(1970 年 1 月 1 日 00:00:00(UTC))到当前时间的毫秒数(毫秒时间戳)
      4. Date.parse(new Date()) 解析一个表示某个日期的字符串,返回 Unix 毫秒时间戳(由于浏览器差异和不一致,不建议使用)
  2. ISO 8601
    1. 概念
      一种国际通用的日期和时间格式,是国际标准化组织的日期和时间的表示方法
    2. 格式
      YYYY-MM-DDTHH:mm:ss[.mmm]TZD
      YYYY 表示四位数的年份
      MM 表示两位数的月份
      DD 表示两位数的天(day of the month),从 01 到 31
      T - 用来指示时间元素的开始字符,日期和时间合并表示时,要在时间前面加大写字母 T
      HH 表示两位数的小时,从 00 到 23
      mm 表示两位数的分钟,从 00 到 59
      ss 表示两位数的秒,从 00 到 59
      mmm 表示三位数的毫秒数,从 000 到 999
      TZD - 表示时区指示符 +hh:mm表示比 UTC 时间快的本地时区 -hh:mm表示比 UTC 时间慢的本地时区
  3. Date
    1. date 相减会返回相差的毫秒时间戳
    2. 如何创建日期对象?
      创建的日期对象一般都会返回格林威治标准时间 GMT 格式, 例如Fri Jan 11 2019 00:00:00 GMT+0800 (中国标准时间)
      1. 直接Date.now() 返回自 1970-1-1 00:00:00 UTC(世界标准时间)至今所经过的毫秒数
      2. new Date() 返回当前时间的格林威治标准时间 GMT 格式
      3. new Date(value);
      4. new Date(dateString)
        可以输入日期格式字符串
        例如new Date(2019-01-11),new Date('1995-12-17T03:24:00'),new Date('December 17, 1995 03:24:00')
      5. new Date(year, monthIndex [, day [, hours [, minutes [, seconds [, milliseconds]]]]])
        例如new Date(2023, 5, 18)

时间换算

  1. 时间换算 1 天 = 24 小时 = 1440 分钟 = 86400 秒 = 86,400,000 毫秒

时间与时间戳的转化

  1. 时间戳转化为 ISO
    moment().format('YYYY-MM-DDTHH:mm:ss.SSSZ') // 2023-10-16T11:37:34.291+08:00
    
  2. 时间戳转化为常见格式
    moment().format('YYYY-MM-DDTHH:mm:ss.SSSZ') // 2023-10-16T11:37:34.291+08:00
    moment().format('llll') // 2022年7月15日星期五 17:26
    moment().format('LLLL') // 2022年7月15日星期五下午5点26分
    moment().format('YYYY MMM Do dddd a') // 2022 7月 15日 星期五 下午
    
  3. 常见格式转化为毫秒时间戳
    moment().format('x') // 返回值为字符串类型,小写x
    moment().valueOf() //返回值为数值型
    new Date().getTime()
    new Date().valueOf()
    Date.parse(new Date())
    

与时间相关方法

以当天为 2023/10/11 为例

  1. 日期比较(格式:YYYY-MM-DD HH:mm:ss | 比较 2023-10-13 00:00:00 和 2022-10-13 00:00:00 的大小)

    /**
     * @desc 日期比较,第一个日期是否大于第二个日期
     * @date 2023-04-10
     * @param {String} d1 第一个日期
     * @param {String} d2 第二个日期
     * @returns {Boolean}
     */
    function dateSort() {
      // 将年月日时分秒转化为毫秒数
      let date1 = new Date(d1).getTime()
      let date2 = new Date(d2).getTime()
      return date1 - date2 > 0
    }
    console.log(dateSort('2023-10-13 00:00:00', '2022-10-13 00:00:00')) // true,第一个日期大于第二个
    
  2. 年月日比较 (格式:YYYY-MM-DD | 比较 2018/20/20 和 2018/20/21)

    /**
     * @desc 年月日比大小,第一个日期是否大于第二个日期
     * @date 2023-04-10
     * @param {String} d1 第一个日期
     * @param {String} d2 第二个日期
     * @returns {Boolean}
     */
    function timeSortByStamp(d1, d2) {
      // 将年月日转化为毫秒数
      let date1 = new Date(d1).getTime()
      let date2 = new Date(d2).getTime()
      return date1 - date2 > 0
    }
    console.log(timeSortByStamp('2022/10/12', '2022/10/11')) // true
    
    /**
     * @desc 时间排序,对日期字符串进行解析,通过获取时间戳进行比较
     * @date 2023-10-16
     * @param {any} arr, ['2022/10/13', '2023/10/13', '2023/10/01']
     * @returns {any}
     */
    function timeSortByStamp1(arr) {
      arr.sort((d1, d2) => {
        let date1 = new Date(d1).getTime()
        let date2 = new Date(d2).getTime()
        return date1 - date2
      })
    }
    console.log(timeSortByStamp1(['2022/10/13', '2023/10/13', '2023/10/01']))
    // ['2022/10/13', '2023/10/01', '2023/10/13']
    
    /**
     * @desc 时间排序,对日期字符串进行解析,通过获取时间戳进行比较
     * @date 2023-10-16
     * @param {any} arr, ['2022/10/13', '2023/10/13', '2023/10/01']
     * @returns {any}
     */
    function timeSortByStamp2(arr) {
      arr.sort((d1, d2) => {
        return Date.parse(d1) - Date.parse(d2)
      })
    }
    console.log(timeSortByStamp2(['2022/10/13', '2023/10/13', '2023/10/01']))
    // ['2022/10/13', '2023/10/01', '2023/10/13']
    
  3. 时分秒比较 (格式:HH:mm:ss | 比较 11:23:24 和 12:23:24)

    /**
     * @desc 时分秒比较
     * @date 2023-04-10
     * @param {Array} result 例如['02:00:00', '03:00:00', '03:00:00','13:30:00', '01:25:00', '00:13:00']
     * @returns {Array}
     */
    function timeSortFn(result) {
      result.sort((item1, item2) => {
        if (item1 > item2) {
          return 1;
        }
        if (item1 < item2) {
          return -1;
        }
        return 0;
      });
      return result;
    },
    console.log(['02:00:00', '03:00:00', '13:30:00', '01:25:00', '00:13:00','03:00:00'])
    // ['00:13:00', '01:25:00', '02:00:00', '03:00:00', '03:00:00', '13:30:00']
    
  4. 判断两个日期范围是否存在交集

    /**
     * @desc 判断两个日期范围是否存在交集,利用时间戳判断
     * @date 2023-04-12
     * @param {Array} rangeData1 例如['2022/02/03', '2022/03/03']
     * @param {Array} rangeDate2 例如['2022/03/03', '2022/03/24']
     * @returns {Boolean}
     */
    function isDateIntersection(rangeData1, rangeDate2) {
       let startDate1 = Date.parse(rangeData1[0])
       let endDate1 = Date.parse(rangeData1[1])
       let startDate2 = Date.parse(rangeDate2[0])
       let endDate2 = Date.parse(rangeDate2[1])
       if (startDate2 > endDate1 || startDate1 > endDate2) {
          return false
       } else {
          return true
       }
    },
    
  5. 判断多个日期范围是否存在交集

    /**
     * @desc 判断多个日期范围是否存在交集
     * @date 2023-04-12
     * @param {Array} rangeDateArr 例如[['2022/02/03', '2022/03/03'],['2022/03/03', '2022/03/24'],['2022/04/05', '2022/06/12']]
     * @returns {Boolean}
     */
    function isMulDateIntersection(rangeDateArr) {
      if (rangeDateArr.length > 1) {
        // 定义多个日期范围是否存在交集
        let isDateIntersection = false
        for (let i = 0; i < rangeDateArr.length; i++) {
          for (let j = i + 1; j < rangeDateArr.length; j++) {
            if (isDateIntersection(rangeDateArr[i], rangeDateArr[j])) {
              isDateIntersection = true
              break
            }
          }
          if (isDateIntersection) {
            break
          }
        }
        if (isDateIntersection) {
          console.log('多个日期范围存在交集')
        }
        return isDateIntersection
      }
    
      // 判断两个日期是否存在交集
      function isDateIntersection(rangeData1, rangeDate2) {
        let startDate1 = Date.parse(rangeData1[0])
        let endDate1 = Date.parse(rangeData1[1])
        let startDate2 = Date.parse(rangeDate2[0])
        let endDate2 = Date.parse(rangeDate2[1])
        if (startDate2 > endDate1 || startDate1 > endDate2) {
          return false
        } else {
          return true
        }
      }
    }
    
    console.log(
      isMulDateIntersection([
        ['2022/02/03', '2022/03/03'],
        ['2022/03/03', '2022/03/24'],
        ['2022/04/05', '2022/06/12'],
      ]),
    ) //true
    
  6. 获取时间戳(以秒为单位)

    moment().format('X') // 返回值为字符串类型,大写X
    moment().unix() // 返回值为数值型
    
  7. 获取时间戳(以毫秒为单位)

    moment().format('x') // 返回值为字符串类型,小写x
    moment().valueOf() //返回值为数值型
    new Date().getTime()
    new Date().valueOf()
    Date.parse(new Date())
    
  8. 获取当前时间的标准时间

    moment().format('YYYY-MM-DDTHH:mm:ss.SSSZ') // 2023-10-16T11:37:34.291+08:00
    moment().format('llll') // 2022年7月15日星期五 17:26
    moment().format('LLLL') // 2022年7月15日星期五下午5点26分
    moment().format('YYYY MMM Do dddd a') // 2022 7月 15日 星期五 下午
    
  9. 时分秒(HH:mm:ss)转化成秒(s)

    /**
    * @desc 时分秒(HH:mm:ss)转化成秒(s),举例'04:10:23' => 15023
    * @date 2023-05-18
    * @param {Number} time
    * @returns {any}
    */
    timeToSec(time) {
       let hour = time.split(':')[0]
       let minute = time.split(':')[1]
       let seconds = time.split(':')[2]
       return Number(hour*3600) + Number(minute*60) + seconds
    }
    
  10. 秒(s)转化成时分秒(HH:mm:ss),例如 15000 => '04:10:00'

    /**
     * @desc 秒转化成时分秒 例如 15000 => '04:10:00'
    * @date 2023-05-18
    * @param {any} total
    * @returns {any}
    */
    secToTime(total) {
       let hour = parseInt(total / 60 / 60 % 24)
       let minute = parseInt(total / 60 % 60)
       let second = parseInt(total % 60)
       hour = hour < 10 ? '0' + hour : hour
       minute = minute < 10 ? '0' + minute : minute
       second = second < 10 ? '0' + second : second
       return `${hour}:${minute}:${second}`
    }
    
  11. 获取未来一个月时间 格式:1688832000000(毫秒时间戳)

    let stamp1Copy = new Date(new Date().setHours(0, 0, 0, 0))
    let endTime = stamp1Copy.setMonth(stamp1Copy.getMonth() + 1)
    
  12. 获取当天 00:00:00

    new Date(new Date().setHours(0, 0, 0, 0)) // Mon Oct 16 2023 00:00:00 GMT+0800 (中国标准时间) {}
    moment().startOf('day').format('YYYY-MM-DD HH:mm:ss') // 2023-10-16 00:00:00
    
  13. 获取当天 23:59:59

    moment().endOf('day').format('YYYY-MM-DD HH:mm:ss')
    new Date(new Date().setHours(0, 0, 0, 0) + 24 * 60 * 60 * 1000 - 1)
    //Mon Dec 04 2017 23:59:59 GMT+0800 (中国标准时间)
    moment(new Date(new Date().setHours(0, 0, 0, 0) + 24 * 60 * 60 * 1000 - 1)).format('YYYY-MM-DD HH:mm:ss')
    
  14. 获取前 n 天/后 n 天

    moment().add(n, 'days')
    moment().subtract(n, 'days')
    
  15. 获取本周一

    moment().weekday(0).format('YYYY-MM-DD')
    
  16. 获取本周日

    moment().weekday(6).format('YYYY-MM-DD')
    
  17. 获取本周一 00:00:00

    moment().startOf('isoWeek').format('YYYY-MM-DD HH:mm:ss')
    
  18. 获取本周日 23:59:59

    moment().endOf('isoWeek').format('YYYY-MM-DD HH:mm:ss')
    
  19. 获取 7 天前的日期

    moment().subtract(7, 'days').format('YYYY-MM-DD')
    
  20. 获取当天周几

    moment().day()
    
  21. 获取当前月份的第一天 00:00:00

    moment().startOf('month').format('YYYY-MM-DD HH:mm:ss')
    
  22. 获取当前月份的最后一天 23:59:59

    moment().endOf('month').format('YYYY-MM-DD HH:mm:ss')
    
  23. 获取上个月份的今天日期

    moment().subtract(1, 'months').format('YYYY-MM-DD')
    
  24. 获取下个月份的今天日期

    moment().add(1, 'months').format('YYYY-MM-DD')
    
  25. 获取当前月的总天数

    moment().daysInMonth()
    
  26. 判断时间是否在另一个时间之后

    moment('2010-10-20').isBefore('2010-10-21')
    
  27. 判断时间是否在某个范围内

    moment('2010-10-20').isBetween('2010-10-19', '2010-10-25')