Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

常规业务开发中是否需要引入moment.js? #16

Open
myheartwillgoon opened this issue Oct 15, 2018 · 0 comments
Open

常规业务开发中是否需要引入moment.js? #16

myheartwillgoon opened this issue Oct 15, 2018 · 0 comments

Comments

@myheartwillgoon
Copy link
Owner

myheartwillgoon commented Oct 15, 2018

moment.js作为一个全球通用库,需要做兼容性(<ES5),数据边界检测,边缘(多)场景覆盖,国际化支持...使其最终的文件体积较大(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 setFormatDate(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/Global_Objects/Date

@myheartwillgoon myheartwillgoon changed the title 日常业务开发是否需要引入moment.js? 常规业务开发中是否需要引入moment.js? Nov 9, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant