V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
推荐关注
Meteor
JSLint - a JavaScript code quality tool
jsFiddle
D3.js
WebStorm
推荐书目
JavaScript 权威指南第 5 版
Closure: The Definitive Guide
noahlam
V2EX  ›  JavaScript

介绍一个超轻量级的 js 时间库 miment

  •  
  •   noahlam · 2018-04-19 00:04:59 +08:00 · 3871 次点击
    这是一个创建于 2448 天前的主题,其中的信息可能已经有所发展或是发生改变。

    介绍

    Miment ("Mini Moment") 是一个轻量级的时间库,打包压缩后体积 1K,没有过多的方法。它的上手成本几乎为零,无需反复查阅文档。当你只需要 Moment 的若干核心能力但又不希望使你的包体积膨胀时,欢迎尝试 Miment。

    Build Status

    首先致敬一下 Moment,非常好用的一个时间库。我本身也是 Moment 重度使用者,用习惯了 Moment,一碰到需要处理时间的需求立马 Moment。不过有时候想想,Moment 给我们提供了那么多的功能,但是我们天天用的, 也就那么一两个。刚好最近在写微信小程序,然后在页面引入 Moment,打包完,包竟然大了 200 多 K,把 Moment 去掉,就直接少掉 200 多 K。反复试了好几次,确定一个 Moment 在小程序里面,占用大概 200K 的空间。于是就想自己写一个类似 Moment 的精简的时间库,于是就有了这个。为什么要叫 Miment 呢?其实刚开始我是想叫 Mini-Moment 的,但是考虑到以后可能会经常使用到,打 2 个单词中间还要加一个横杆太累了,所以就把 Mini-Moment 缩水成 Miment 了。

    安装

    对浏览器环境,在页面引入 ./dist/miment-min.js 即可:

    <script src="//unpkg.com/miment/dist/miment-min.js"></script>
    <script>miment().format()</script>
    

    在 NPM 生态中使用时,请使用包管理器安装 Miment:

    npm i miment
    

    然后就可在你的项目中使用了:

    import miment from 'miment'
    miment().format() // 2018-04-09 23:01:58
    

    API

    API 方法可分为三类:

    • 返回 Computed 结果的方法。如 format 返回字符串,json 返回的是一个 JSON 对象。
    • 返回 Miment 对象的方法,即支持链式调用。
    • 从 Date 对象继承的方法。Date 对象上的方法 miment 也可以使用,这些方法类似私有 API,不推荐直接使用。

    返回 Computed 结果的方法

    format

    format 方法几乎是我们平时最常用的了。它一共接收 2 个参数,这 2 个参数都有默认值,不传则使用默认值:

    参数名称 参数类型 参数默认值 是否必传 说明
    格式化的字符串 string 'YYYY-MM-DD hh:mm:ss' N 年 YYYY
    月 MM
    日 DD
    时 hh
    分 mm
    秒 ss
    毫秒 SSS
    数字星期 ww
    中文星期 WW
    是否为时间差 boolean false N 格式化 distance 时间差时,使用 true
    • 本着简单的原则,我们没有实现特别灵活的格式化方式。有时灵活也意味着学习成本:你需要记忆更多的用法,不是吗?
    • 格式化字符串区分大小写,记忆技巧是日期大写如 YYYY MM DD,时间小写如 hh mm ss,毫秒跟星期特殊的单独记。参数格式需严格匹配,长度过多或过少均无效,如 YYYY 写成 YYYYY 均无效。
    • 对第二个参数的使用,参见 distance 方法。
    miment().format('YYYY 年 MM 月 DD 日 hh:mm:ss')
    // 2018-04-09 23:49:36
    
    miment().format('YYYY/MM/DD hh-mm-ss SSS')
    // 2018/04/09 23-49-36 568
    
    miment().format('YYYY 年 MM 月 DD 日 星期 WW')
    // 2018 年 04 月 09 日 星期一
    
    miment().format('YYYY 年 MM 月 DD 日 星期 ww')
    // 2018 年 04 月 09 日 星期 1 *周日对应星期 0*
    

    作为扩展,如果我们只想获取单独的年、月或日,可这样使用:

    miment().format('YYYY') // 2018
    miment().format('MM') // 04
    miment().format('DD') // 09
    miment().format('hh') // 23
    miment().format('mm') // 57
    miment().format('ss') // 16
    miment().format('SSS') // 063
    miment().format('ww') // 1
    miment().format('WW') // 一
    

    基于这个方法,你可以不需要记忆大部分原生的日期方法(如 getFullYear / getDate / getDay 等),使用统一的 format 处理各种需求。

    json

    输出 JSON 格式的时间字段:

    miment().json()
    
    {
      "year": 2018,
      "month": 4,
      "date": 11,
      "hour": 8,
      "minute": 57,
      "second": 41,
      "day": 3,
      "milliSecond": 87
    }
    

    stamp

    输出时间戳,不需参数。

    miment().stamp()
    // 1523408529932
    

    daysInMonth

    获取当前 Miment 对象所在月的天数。

    miment().daysInMonth()
    // 30
    

    支持链式调用的方法

    add

    增加或减少时间。它接收 2 个参数:

    参数名称 参数类型 参数默认值 是否必传 说明
    增量 number 0 N 要增加的时间量,增加传正数,减少传负数
    单位 string 无默认值 Y 要增加的时间单位
    可选同 format 格式化字符串

    为方便使用,单位的可选参数格式与格式化方法 format 的保持一致。同样严格匹配大小写与长度。

    miment().add(1,'DD') // 增加一天
    miment().add(1, 'YYYY').add(2, 'MM').add(-3, 'DD') // 增加 1 年 2 个月又减回 3 天
    miment().add(-1,'ww') // 减去一周,即获取上周的日期
    miment().add(500,SSS) // 增加 500 毫秒
    

    add 返回的值是增加完后的 Miment 对象,我们可以在它后面继续调用 mimont 支持的方法:

    miment().add(1,'DD').format()
    // 2018-04-12 09:29:55
    

    需要注意的是,当你调完返回 Computed 结果的方法后,返回的对象类型不是 Miment,故而不支持链式调用:

    miment().add(1,'DD').format().add(1,'DD') // 报错
    

    distance

    计算 2 个时间的距离。它接收 2 个参数,返回一个 Miment 对象:

    参数名称 参数类型 参数默认值 是否必传 说明
    起始时间 miment/date/number/string Y 接受 4 种类型参数,会自动转换
    结束时间 miment/date/number/string N 同上
    • 只传一个起始时间时,返回 起始时间 - miment 当前时间
    • 提供起始时间和结束时间时,返回 起始时间 - 结束时间。相减顺序如何?先出现的减去后出现的:
    miment().distance('2018-04-10 00:00:00')
    // Mon Dec 29 1969 22:11:51 GMT+0800 (CST)
    
    miment().distance(1523408529932)
    // Wed Dec 31 1969 07:13:47 GMT+0800 (CST)
    
    miment().distance('2018-04-10 00:00:00')
    // Mon Dec 29 1969 22:11:51 GMT+0800 (CST)
    
    miment().distance(1523408529932)
    // Wed Dec 31 1969 07:13:47 GMT+0800 (CST)
    
    miment().distance('2018-04-10 00:00:00', new Date())
    // Mon Dec 29 1969 22:11:13 GMT+0800 (CST)
    
    miment().distance('2018-04-10 00:00:00', '2018-04-11 00:00:00')
    // Mon Dec 29 1969 22:10:46 GMT+0800 (CST)
    

    你一定注意到了,为什么 distance 方法返回的年份是 1969 年呢?这实际上是基于1970-01-01 00:00:00 的毫秒数,参见 Unix 时间,而我们把两个时间相减,得到的可能是一个相对很小的时间戳(还可能是负数),所以离 1970 很近。

    那我们要怎么显示我们能看得懂的时间呢?配合 format 即可。format 的第二个参数是用于用来格式化 distance 计算出的时间差,只要把第二个参数设为 true,即可将当前时间格式化成时间差。作为对比:

    miment().distance(1523408529932).format('YYYY 年 MM 月 DD 日 hh 时 mm 分 ss 秒')
    // 1969 年 12 月 30 日 00 时 52 分 16 秒
    
    miment().distance(1523408529932).format('YYYY 年 MM 月 DD 日 hh 时 mm 分 ss 秒', false)
    // 1969 年 12 月 30 日 00 时 52 分 16 秒
    

    把第二个参数设为 true

    miment().distance(1523408529932).format('YYYY 年 MM 月 DD 日 hh 时 mm 分 ss 秒', true)
    // 00 年 01 月 03 日 23 时 08 分 23 秒
    

    firstDayOfWeek

    获取本周的第一天(周日),无参数:

    miment().firstDayOfWeek() // Sun Apr 08 2018 11:27:55 GMT+0800 (CST)
    miment().firstDayOfWeek().format() // 2018-04-08 11:27:55
    

    如果想获取周一呢?周二、三、四、五、六呢?

    miment().firstDayOfWeek().add(1,'DD').format()
    // 2018-04-09 11:27:55
    

    firstDay

    获取每个月的第一天,无参数:

    miment().firstDay() // Sun Apr 01 2018 00:00:00 GMT+0800 (CST)
    miment().firstDay().format() // 2018-04-01 00:00:00
    

    lastDay

    获取每个月的最后一天,无参数:

    miment().lastDay()
    // Mon Apr 30 2018 00:00:00 GMT+0800 (CST)
    
    miment().lastDay().format()
    // 2018-04-30 00:00:00
    

    Date 自有方法

    Miment 继承自 Date 对象,所以也拥有 Date 对象的所有方法。请移步至 MDN 查看

    需要注意的是,由于继承而来的方法是属于 Date 对象的,为保持一致,我们没有对方法做改动。故而方法无法返回 miment 对象,也无法链式调用 miment。

    许可

    MIT

    写在最后

    目前这些功能(函数),是我们团队在日常实践中碰到的比较常用的。如果你对功能有新的需求或者建议,欢迎给我们提 Issue。如果喜欢 miment,请在我的 GitHub 上给我一个 star,你的 star 就是我最大的动力了,谢谢!

    GooMS
        1
    GooMS  
       2018-04-19 01:26:49 +08:00 via Android
    不错,在多语言和时区上处理下就更有竞争力了
    noahlam
        2
    noahlam  
    OP
       2018-04-19 10:30:34 +08:00
    @GooMS 多语言由于能力问题,目前只能做到中英文..时区的问题,在 roadmap 中了..
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   1000 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 32ms · UTC 20:16 · PVG 04:16 · LAX 12:16 · JFK 15:16
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.