你尚未登录,仅允许查看本站部分内容。请登录使用邀请码注册
Traveller

常规业务开发中是否需要引入moment.js? 0个回复 专栏 @ Javascript

Traveller 发布于 3 周前

moment.js作为一个全球通用库,需要做兼容性((moment.min.js 52Kb, moment-with-locales.min.js 327Kb).在无国际化的日常业务开发中,Date的应用场景主要在日期(时间)控件的格式化展示,处理(比较,区间计算).
通过下面几个自定义的小函数,能否解决这些日常需求呢?

日期/时间格式化展示

在日期选择器(datePicker)中,通常采用类似2018-10-15 15:34:33的格式来展示给用户.

// return 2018-10-15 15:34:33
export function getDateTime(date = new Date()) {
    let arr = new Array(6);
    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(-8)
  • 如果小于10的想去掉前置0,则可以使用replace(/([-|:|\s])0/g, "$1")

通过字符转换思想,有个简洁的实现方法. toISOString()返回世界时间格式化的字符串,需要加上对应时区再转换,才能正确获取本地时区时间信息.

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对象,做后续操作的进一步处理.如日期区间查询(昨天,近三天,近一周,近一个月).

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

根据指定日期生成一定时间区间的日期

如上面所描述的日期区间查询,对于常用的几个时间区间(今天,昨天,近一周,近一个月...),会提供便捷的按钮操作来处理展现日期区间.
对于天/小时/分钟/秒,我们可以通过生成的日期对象,加减对应的毫秒数来实现.

const ONE_DAY = 86400000;
export function getOffsetDayDate(offset = 0, start = new Date()) {
    const times = start.getTime();
    const date = new Date(offset * ONE_DAY + times);
    return getDateTime(date).slice(0, 10);
}

对于月份,我们则可以利用new Date多参数(>=2)传递时,会自动进位的特性来便捷实现.
当对应的年,月(0\~11),日(1\~31),小时,分钟,秒,毫秒,超出其范围时,Date构造函数会自动进行进位或降位计算.
如给月份传递-1,则Date构造函数将返回上一年的12月份.其中有个自然逻辑需要考虑,当目前的月当前天数 大于计算增加月后最大的天数后,需要做一下处理.

export function getOffsetMonthDate(offset, date = new Date()) {
    const year = date.getFullYear();
    const month = date.getMonth();
    const day = date.getDate();
    const monthLastDay = new Date(new Date(year, month + offset + 1, 1, 1) - ONE_DAY).getDate();
    if (day > monthLastDay) date.setDate(monthLastDay);
    date.setMonth(month + offset);
    return getDateTime(date).slice(0, 10);
}

日期时间比较

将日期按上面的标准字符格式转换后,可以直接采用字符串来比较,解决常用的开始结束时间比较(早于,晚于,等于),无须转换为毫秒数(date.getTime() 或 JavaScript的隐式调valueOf())来进行比较.
特定区间的日期比较(如时间间隔不能超过一年),则可以用上面的函数将日期字符转换为日期对象,加减相应的毫秒数来对比处理(也可以将一个日期字符加上指定时间区间再转换为字符来对比).

Notice

  • date.set**相关函数也会有相应的进位处理.
  • date.set**返回值为设置后对象的时间戳,注意unix为秒数,这里为毫秒数.与后端API交互时,需处理.
  • 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深拷贝对象时需要将时间字符转换回来.

推荐阅读

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/GlobalObjects/Date

等待第一条回复
登录后回复,如无账号,请使用邀请码注册