相关文章推荐
强悍的双杠  ·  Excel ...·  1 年前    · 
自信的芒果  ·  Oops!!! - 简书·  2 年前    · 
·  阅读

moment.js作为一个全球通用库,需要做许多兼容,导致其大而全.在日常项目开发中,往往用不到几个API.个人参与维护的B端项目,组内同事使用其API集中在日期选择组件及前后端日期格式化传递处理上.在项目优化时,通过组内内部约定,采用几个小函数去除moment.js的依赖,可显著减少项目打包体积(moment.min.js 52Kb, moment-with-locales.min.js 327Kb).

日期/时间格式化展示

在与后端进行数据交接时,后端通常接收/传递 2018-10-15 15:34:33 形式的标准格式,前端在日期选择组件里展示给用户时,也会采用该格式.定义一个函数将日期对象转换为该类字符返回.

export function getDateTime(date = new Date()) {
    let arr = [];
    arr[0] = date.getFullYear();
    arr[1] = date.getMonth() + 1;
    arr[2] = date.getDate();
    arr[3] = date.getHours();
    arr[4] = date.getMinutes();
    arr[5] = date.getSeconds();
    arr = arr.map(item => item < 10 ? `0${item}`:item);
    return `${arr.slice(0,3).join('-')} ${arr.slice(3).join(':)}`;
复制代码

后续可通过该标准日期格式,再二次处理获得一些常用的格式:

  • 只需要日期部分: getDateTime(date).slice(0, 10)
  • 只需要时间部分: getDateTime(date).slice(10)/getDateTime(date).slice(-8)
  • 去掉前置的0: getDateTime(date).replace(/([-|:|\s])0/g, "$1")
  • // 获取标准时间格式hack方法.
    export function getDateTime(date = new Date()) {
        const times = date.getTime() - date.getTimezoneOffset() * 6e4;
        return new Date(times).toISOString().slice(0,19).replace('T', ' ');
    //转换为中文日期时间格式
    const cn = ['年', '月','日 ', '时', '分', '秒'];
    const ret = getDateTime(date).split(/[-:\s]/).map((val, index) => +val + cn[index]).join('');
    复制代码

    标准日期格式转换为Date对象

    从接口获取到时间字符串,需要转换为日期对象进行后续的区间计算等操作,如计算昨天,今天,近一周,近一个月.

    export function toDate(string) {
        const args = string.split(/[\-:\s]/);
        args[1] -= 1;
        return new Date(...args);
    // 这里有隐性转换, '09' 通过减法运算或给Date()构造函数传递多参数,会转整.
    // 如果是ES5,这里spread运算符怎么写? https://babeljs.io/en/repl.html
    复制代码

    日期区间计算

    在订单查询等业务中,经常会提供今天,昨天,近一周,近一个月等便捷日期选择查询方式,前端需要根据当前日期结合用户操作,转换为后端需要的时间格式进行查询操作.

    对于天/时/分/秒,可以加减相应的秒数来处理.

    const ONE_DAY = 86400000;
    export function getOffsetDay(offset = 0, date = new Date()) {
        const seconds = date.getTimes();
        const days = new Date(seconds + ONE_DAY * offset);
        return getDateTime(days).slice(0, 10);
    复制代码

    对于月份,计算秒数较复杂,可以利用setMonth来简便处理.不过需要考虑自然月逻辑(7/31减一个月是6/30,而不是7/1(6/31)).

    export function getOffsetMonth(offset = 0, date = new Date()) {
        const year = date.getFullYear();
        const month = date.getMonth();
        const day = date.getDate();
        //can add if day >28 for less cacl monthlastday
        const monthLastDay = new Date(new Date(year, month+1 + offset, 1, 1) - ONE_DAY).getDate();
        if (day > monthLastDay) date.setDate(monthLastDay);
        date.setMonth(month + offset);
        return getDateTime(date).slice(0, 10);
    复制代码

    日期比较

    日期转换为上面的标准字符格式后,可以直接采用字符串来比较(早于,晚于,等于).日期对象可显式转换为毫秒数(date.getTime()) 或 隐式(调valueOf())来进行比较. 特定区间的日期比较,则可以用上面的函数将日期字符转换为日期对象,加减相应的毫秒数后再用简单的比较方式处理.

    notice

  • date.set**相关函数会有相应的进位处理.
  • date.set**返回值为设置后日期对象的时间戳
  • new Date(string) 底层是调用的Date.parse().格式为RFC 2822 或 ISO 8601,具体见MDN链接
  • new Date(...args) 多参数时,调用的是Date.UTC()
  • new Date(...args) 多参数(2 ~ 7)传递时,当省略相关参数时,采用默认值(0 or 1),而非当前本地时间对应值.
  • 直接采用函数方式调用Date(),返回当前时间的字符串形式,忽略传递的参数.
  • date.toGMTString()正在弃用,建议使用toUTCString()替代.二者有闰秒之差?
  • date.getTimezoneOffset()返回的是当前本地时间与UTC时间相差的分钟数
  • date.toJSON返回toISOString字符串,用JSON.stringify深拷贝对象时需要将时间字符转换回来.
  • developer.mozilla.org/en-US/docs/…

    GitHub勘误/交流: github.com/pagemarks/c…

    分类:
    前端
    标签: