抄了一个框架玩玩。。。 - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
supermao
V2EX    前端开发

抄了一个框架玩玩。。。

  •  
  •   supermao
    hongmaoxiao 2017-12-01 17:12:24 +08:00 2822 次点击
    这是一个创建于 2883 天前的主题,其中的信息可能已经有所发展或是发生改变。

    now.js 是什么

    now.js是一个 Javascript 的时间操作小工具,类似date-fnsmoment

    长啥样

    简单的把示例放这,更多用法请到github去发现。

    import Now from 'now.js'; // for node(browser do not need this) now = new Now() // "2017-11-20 22:23:00.285" now.beginningOfMinute() // "2017-11-20 22:23:00" now.beginningOfHour() // "2017-11-20 22:00:00" now.beginningOfDay() // "2017-11-20 00:00:00" now.beginningOfWeek() // "2017-11-19 00:00:00" now.firstDayMOnday= true // Set Monday as first day, default is Sunday now.beginningOfWeek() // "2017-11-20 00:00:00" now.beginningOfMonth() // "2017-11-01 00:00:00" now.beginningOfQuarter() // "2017-10-01 00:00:00" now.beginningOfYear() // "2017-01-01 00:00:00" now.endOfMinute() // "2017-11-20 22:23:59.999" now.endOfHour() // "2017-11-20 22:59:59.999" now.endOfDay() // "2017-11-20 23:59:59.999" now.endOfWeek() // "2017-11-25 23:59:59.999" now.firstDayMOnday= true // Set Monday as first day, default is Sunday now.endOfWeek() // "2017-11-26 23:59:59.999" now.endOfMonth() // "2017-11-30 23:59:59.999" now.endOfQuarter() // "2017-12-31 23:59:59.999" now.endOfYear() // "2017-12-31 23:59:59.999" All the above functions return String type. You can pass 'self' to return Now instance: var beginningOfMinute = now.beginningOfMinute('self') // return Now instance beginningOfMinute.format('ddd, Ah') // "Mon, PM10" beginningOfMinute.format('LLLL') // "Monday, November 20, 2017 10:23 PM" beginningOfMinute.isMonday() // true 

    为什么要写这个库

    因为学习underscore源码的过程中,感觉无聊。想写个库调剂一下,当做学习的机会。
    我是照着underscore源码一个个 commit 敲的.代码放在这里,刚看了一眼,有 668 次 commit,两个月,敲到了 1.4.3 版本,可能还没到一半。
    敲久了有点无聊。想动手写一个库作为调剂。碰巧之前做防健忘短信提醒的时候是用 go 写的后台,用了gorm,在作者jinzhu的 github 主页上发现了now,是一个 go 的时间帮助库,觉得很有意思。clone 之,学之。
    偷了now的思想。造一个 Javascript 版的就显得很容易。很快我就写完了除了ParseMustParse之外的所有方法。跟原库对比一下。觉得 now.js 就是个玩具。这不怪我,Javascript 对时间处理的支持远不如 go。比如 go 原生支持format、字符串解析成时间以及Duration等等。
    想着加上format。该怎么去写?立马就想到的方法是平时经常写的根据不同条件做字符串拼接。确实是个方法。但得多少 switch case 才能涵盖所有情况,想想都可怕。显然这是最蠢也是工作量最大的方法。
    不会,那就借鉴别人的。github 上发现了 date-fns 和 moment,支持 i18n 国际化。

    date-fns:

    import { formatRelative } from 'date-fns' import { es, ru } from 'date-fns/esm/locale' formatRelative(subDays(new Date(), 3), new Date(), { locale: es }) //=> "el viernes pasado a las 19:26" formatRelative(subDays(new Date(), 3), new Date(), { locale: ru }) //=> "в прошлую пятницу в 19:26" 

    moment:

    moment.locale('fr'); moment(1316116057189).fromNow(); // il y a une heure moment.locale('en'); moment(1316116057189).fromNow(); // an hour ago 

    我的审美告诉我应该选择 moment,调用一次 locale(),这之后的 format 都是基于该 locale 的。当然它也还支持每次单独指定 locale 的:

    moment.duration(1, "minutes").locale("en").humanize(); // a minute moment.duration(1, "minutes").locale("fr").humanize(); // une minute moment.duration(1, "minutes").locale("es").humanize(); // un minuto 

    进一步学习发现 moment 的 format 和 i18n 国际化高度耦合。要用它的 i18n 意味着基本上也得用它的 format。当然 i18n 也不是核心的 moment 库作者写的,他们也精通不了那么多国家的语言,那都是 github 上许许多多人贡献的。开源就有这好处。看下 LICENCE 是 MIT 的,代码可用,抄。
    now.js 也是 MIT 协议的,负罪感少了点(其实 MIT 协议是相当宽松的,就算你拿它代码去商业化也是没有问题的)。况且我写库的主要目的是为了学习。
    开干!虽说是抄,毕竟代码要整合到我的库,直接复制粘贴是不行的。所有的代码细节未必都需要全知道,但看懂整体运行的逻辑是必须的,下点功夫,整合成功,开源。

    思维脑图

    moment:

    当然,moment 的东西不止上图这些,我只取了一部分来画。

    now.js:

    now.js 的 Duration 和 moment 的不一样,现在还不支持单独使用,只是给内部方法elapse使用,以后可能会支持单独使用。

    对比

    1. moment 是大而全,now.js 是刚够用。
    2. moment 的 parse 相当强大,now.js 就暂时不支持了,只支持和new Date(args)相同的args参数类型。不过format应该都基本上和 moment 的一样,不过测试用例现在还没有写太全,如果谁用了并且发现 bug,可以到github去提 issues。不胜感激。
    3. moment 是页面一加载的时候会把所有的 i18n 都初始化了,这点我个人认为不好,加载时间长,网络情况不好的时候,差不多需要 10 秒我才能在 devtool 上调试(当然这也包括官网加载的其他很多东西)。now.js 只加载默认的,需要的时候按需加载。
    4. moment 做什么操作前都要检测一下 date 是否合法的( isvalid )。now.js 在 parse 的时候如果不合法就直接抛出错误,以免后续没玩没了的检测。当然这可能损失了用户友好性,但是对减少代码量是很有帮助的。

    结语

    这个库不是我一个人写的,是许多开源工作者共同完成的。感谢 moment 的所有开源贡献者,我从中学习了很多东西。后续还会继续研究 moment 的代码细节,偷偷它的思想。

    写代码什么最重要?思想最重要!

    7 条回复    2017-12-20 22:10:13 +08:00
    Pastsong
        1
    Pastsong  
       2017-12-01 17:25:20 +08:00
    设全局状态这件事情太不 functional 了...
    supermao
        2
    supermao  
    OP
       2017-12-01 17:32:10 +08:00
    @Pastsong 没错,现在这个只是第二个小版本,主要还是学习学习,慢慢再想怎么提高
    wyc829
        3
    wyc829  
       2017-12-04 15:52:20 +08:00
    支持
    supermao
        4
    supermao  
    OP
       2017-12-05 13:17:18 +08:00
    @wyc829 多谢!
    brooky
        5
    brooky  
       2017-12-20 14:44:09 +08:00
    小白一个, 才知道原来是这样学习别人代码的. 但是看了下没有注释啊, 看不懂啊
    underscore 有 2000 多 commits 怎么迅速找到第一个 commit, 而不是一个个点击`older`
    supermao
        6
    supermao  
    OP
       2017-12-20 22:08:37 +08:00 via iPhone
    @brooky 其实我觉得我的命名已经能够很好的理解意思了,所以没加注释,等 1.0.0 再加吧
    supermao
        7
    supermao  
    OP
       2017-12-20 22:10:13 +08:00 via iPhone
    @brooky clone 库 然后 git log 就行 当然可以配合 shell 脚本的 tail 等来看 自己发挥了
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     923 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 26ms UTC 20:16 PVG 04:16 LAX 13:16 JFK 16:16
    Do have faith in what you're doing.
    ubao msn snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86