V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
millx
V2EX  ›  程序员

这个 js bug 应该大家都碰到过吧?

  •  
  •   millx · 2018-06-15 11:06:13 +08:00 · 7088 次点击
    这是一个创建于 2358 天前的主题,其中的信息可能已经有所发展或是发生改变。

    开发 bufpay.com 个人收款接口 的时候,前端需要计算账号过期时间。直接用了:

    var t = new Date('2018-06-15 00:00:00');
    

    这样来初始化,在 Chrome 里面是没问题的,但是 Safari 里面就不行了,发现 Safari 支持 :

    var t = new Date('2018-06-15');
    

    和这样

    var t = new Date('2018-06-15T00:00:00');
    

    Chrome 里面是上面三种格式初始化都支持的。

    这个 bug (应该也不能算 Safari 的 bug )应该是 Chrome 做了兼容,Safari 是符合 ECMAScript IOS 8601 关于时间的格式定义的。

    51 条回复    2018-06-16 15:59:09 +08:00
    wenzhoou
        1
    wenzhoou  
       2018-06-15 11:11:21 +08:00 via Android
    改用 moment.js 怎么样
    hanpei
        2
    hanpei  
       2018-06-15 11:15:20 +08:00
    t = new Date('2018/06/15 00:00:00')
    safari 这样可以
    以前也遇到过
    替换-为 /
    millx
        3
    millx  
    OP
       2018-06-15 11:15:39 +08:00
    @wenzhoou 需求比较简单,注意到这个问题手动处理一下就好啦,不太喜欢引入太多 lib 😆
    cccRaim
        4
    cccRaim  
       2018-06-15 11:15:47 +08:00
    我好像是 split(' ')分成日期和时间,然后再对日期 split('-')区分出年月日
    millx
        5
    millx  
    OP
       2018-06-15 11:17:23 +08:00
    @hanpei 嗯,这样也可以,或者是把空格替换为 T
    opengps
        6
    opengps  
       2018-06-15 11:19:15 +08:00
    遇到过-有问题,但是没深入研究,于是一直后台返回 2018/06/15 00:00:00 格式给前台 new Date('')。
    目前没发现问题
    Mutoo
        7
    Mutoo  
       2018-06-15 11:23:07 +08:00
    这种必须前端后统一使用 IOS 8601,或者使用 UTC Timestamp 整数,不然遇到不同时区的时候,就蛋疼了。
    IOS 8601 的 T 部分是负责时区
    millx
        8
    millx  
    OP
       2018-06-15 11:23:40 +08:00
    @opengps 后台 PHP 么? Python 里面 str(datetime.now()) 直接就是 '2018-06-15 11:23:06.674947' 这种格式
    grewer
        9
    grewer  
       2018-06-15 11:23:56 +08:00   ❤️ 1
    以前碰到过,反正只要以'/'作为分割,那就没什么问题了
    Mutoo
        10
    Mutoo  
       2018-06-15 11:24:17 +08:00   ❤️ 1
    @Mutoo 更正一下,Z 部分负责时区(可选)
    zjsxwc
        11
    zjsxwc  
       2018-06-15 11:25:22 +08:00
    moment.js +1
    millx
        12
    millx  
    OP
       2018-06-15 11:26:09 +08:00
    @Mutoo timestamp 可读性不太好 /(ㄒoㄒ)/~~
    agagega
        13
    agagega  
       2018-06-15 11:28:50 +08:00
    同样的坑也出现在 iOS 平台的微信小程序里
    millx
        14
    millx  
    OP
       2018-06-15 11:31:13 +08:00
    @agagega 就是不同 js 编译器有差异,容易被忽略
    jin5354
        15
    jin5354  
       2018-06-15 11:34:05 +08:00   ❤️ 1
    原生 Date 兼容性问题多了,非 IOS 8601 标准格式,有的端直接报错,移动端某些版本还会出现 8 小时误差(不标 Z 的话有的按东八区算,有的按零时区算),如果跨端多非标准格式还是建议用个库
    zhouyg
        16
    zhouyg  
       2018-06-15 11:35:21 +08:00
    建议覆盖掉原生 Date 类型,改为自己实现或模块
    zenxds
        17
    zenxds  
       2018-06-15 11:36:02 +08:00   ❤️ 2
    new Date(时间戳)
    new Date('2014/07/12 12:34:35')
    new Date(year, month, day[, hour[, minute[, second[, millisecond]]]])

    其他的都有兼容问题
    millx
        18
    millx  
    OP
       2018-06-15 11:52:36 +08:00
    @zenxds 统一用这几种就够了
    Cbdy
        19
    Cbdy  
       2018-06-15 11:55:43 +08:00 via Android
    不要用时间戳数字,不要用奇奇怪怪的格式,数据传输统一用字符串,用 ISO8601 格式!
    kslr
        20
    kslr  
       2018-06-15 11:57:35 +08:00
    用时间戳处理只有展示格式化可以避免很多奇怪的问题
    millx
        21
    millx  
    OP
       2018-06-15 11:59:57 +08:00
    @Cbdy 时间戳除了可读性不好,其他应该还是没问题的 😆
    Cbdy
        22
    Cbdy  
       2018-06-15 12:06:48 +08:00 via Android
    @millx 可读性是最严重的问题了,然后他是数字,“类型对不上”,还有诸如 2038 问题
    millx
        23
    millx  
    OP
       2018-06-15 12:10:02 +08:00
    @Cbdy 也是,养成统一格式习惯可以省好多事儿
    doubleflower
        24
    doubleflower  
       2018-06-15 12:32:12 +08:00
    没碰到过,从来不用这种感觉不牢靠的方式
    millx
        25
    millx  
    OP
       2018-06-15 12:34:56 +08:00
    @doubleflower 你用哪种?
    royzxq
        26
    royzxq  
       2018-06-15 12:34:58 +08:00   ❤️ 1
    ```js
    function parseDate(date) {
    if (!date) return new Date()
    if (date instanceof Date) return date
    if (!/[^\d]+/g.test(date)) {
    date = date.toString().concat('000').substr(0, 13) * 1

    return new Date(date)
    }

    return new Date(date.toString().replace(/-/g, '/').replace(/T|(?:\.\d+)?Z/g, ' '))
    }
    ```
    millx
        27
    millx  
    OP
       2018-06-15 12:38:10 +08:00
    @royzxq 👍 不错
    doubleflower
        28
    doubleflower  
       2018-06-15 12:40:55 +08:00
    @millx 我没用过中间有空格的,感觉不符标准
    kefengong
        29
    kefengong  
       2018-06-15 12:59:02 +08:00 via Android   ❤️ 1
    把 - 换成 / 就可以了
    learnshare
        30
    learnshare  
       2018-06-15 13:06:12 +08:00
    这不叫 Bug,是 Chrome 容错更强而已

    2018-06-15 00:00:00 这不是标准格式
    参考 https://zh.wikipedia.org/wiki/ISO_8601
    weixiangzhe
        31
    weixiangzhe  
       2018-06-15 13:14:27 +08:00   ❤️ 1
    不是 bug 这个是兼容问题,推荐 dayjs 吧,api 兼容 momentjs,大小只有 2kb,https://github.com/iamkun/dayjs
    millx
        32
    millx  
    OP
       2018-06-15 13:17:10 +08:00
    @learnshare 是的
    millx
        33
    millx  
    OP
       2018-06-15 13:19:21 +08:00
    @weixiangzhe 这个赞,可以 locale 收藏了
    wwt2017
        34
    wwt2017  
       2018-06-15 13:20:48 +08:00
    Safari 用 - 转化为毫秒时也会出问题
    auroraccc
        35
    auroraccc  
       2018-06-15 15:12:33 +08:00
    平常用个 dayjs 就行了 , momentjs 好大
    zpf124
        36
    zpf124  
       2018-06-15 15:19:01 +08:00
    ie 也有这个问题

    '2018-06-15' 正确
    '2018/06/15 00:00:00' 正确

    '2018-06-15 00:00:00' 报错。
    millx
        37
    millx  
    OP
       2018-06-15 16:02:47 +08:00
    @auroraccc @royzxq 他的这个 parseDate 也不错
    millx
        38
    millx  
    OP
       2018-06-15 16:03:13 +08:00
    @zpf124 应该都是老老实实按标准来实现的 哈哈哈
    mooo
        39
    mooo  
       2018-06-15 16:19:34 +08:00
    第一种不规范啊, 规范只支持 RFC2822 和 ISO 8601 标准的
    metrxqin
        40
    metrxqin  
       2018-06-15 16:29:12 +08:00
    **前端需要计算账号过期时间**

    你确定这种设计足够安全?
    millx
        41
    millx  
    OP
       2018-06-15 16:35:15 +08:00
    @metrxqin 前端后端都需要啊,为什么不安全?
    millx
        42
    millx  
    OP
       2018-06-15 16:37:58 +08:00
    @metrxqin 前端只是用来计算显示的啦,后端肯定需要自己重新计算的,不要太紧张 😆
    Cynic222
        43
    Cynic222  
       2018-06-15 16:38:41 +08:00 via iPhone
    @wenzhoou #1 moment 太大,现在有个 dayjs,一样的 api
    ernest
        44
    ernest  
       2018-06-15 16:41:53 +08:00
    ISO 8601 date string 格式了解下:2018-06-15T00:00:00 是 js Core 支持的。https://en.wikipedia.org/wiki/ISO_8601
    Building
        45
    Building  
       2018-06-15 16:47:32 +08:00 via iPhone   ❤️ 1
    js 没有 bug,如果有的话,那是 feature。
    iamkun
        46
    iamkun  
       2018-06-15 17:17:04 +08:00   ❤️ 1
    @millx 其实这几个时间字符串都不是标准时间,所以呢不同浏览器的支持情况是不一样的。 推荐前后统一用 ISO 时间或者时间戳,省心省力

    当然,欢迎体验 dayjs , 2kb 类似 moment.js 的时间库,欢迎提出各种改进意见。
    feder
        47
    feder  
       2018-06-15 17:31:47 +08:00
    LS dayjs 作者
    wenzhoou
        48
    wenzhoou  
       2018-06-15 18:22:16 +08:00 via Android
    恩。那我下次项目也用 dayjs
    millx
        49
    millx  
    OP
       2018-06-15 20:07:13 +08:00
    @iamkun (*@ο@*) 哇~ dayjs 作者 😆
    scplay
        50
    scplay  
       2018-06-16 09:38:03 +08:00
    第一次用 dayjs 发现 dayjs 没有解决 iso8601 在 safari 上的问题,果断换回 moment,
    iamkun
        51
    iamkun  
       2018-06-16 15:59:09 +08:00
    @scplay 请问在 safari 上是什么问题呢
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   1795 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 61ms · UTC 16:34 · PVG 00:34 · LAX 08:34 · JFK 11:34
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.