移動端中踩過的關於日曆&時間的坑

mykurisu發表於2017-12-25

① 情景-在移動端日曆中,選擇日期並轉成時間戳,在iOS端莫名失效

日曆相信是大家都做過的小玩意,它有可能是HTML5自帶的也可能是自己做的,同時取到的時間格式也是千奇百怪的。不廢話了,我們直接上程式碼。

let a = Date.parse('2017-1-1');
console.log(a);
let b = Date.parse('2017-01-1');
console.log(b);
let c = Date.parse('2017-01-01');
console.log(c);

let a1 = Date.parse('2017/1/1');
console.log(a1);
let b1 = Date.parse('2017/01/1');
console.log(b1);
let c1 = Date.parse('2017/01/01');
console.log(c1);
複製程式碼

這些都是我們常見的時間格式,無論是從後端取得還是我們前端轉換而來的。那麼大家知道每個console的結果是什麼嗎?

let a = Date.parse('2017-1-1');
console.log(a);
//chrome瀏覽器--1483200000000
//Android微信端(類Android內建瀏覽器)--1483200000000
//iOS微信端(類Safari瀏覽器)--NAN
let b = Date.parse('2017-01-1');
console.log(b);
//chrome瀏覽器--1483200000000
//Android微信端(類Android內建瀏覽器)--1483200000000
//iOS微信端(類Safari瀏覽器)--NAN
let c = Date.parse('2017-01-01');
console.log(c);
//chrome瀏覽器--1483228800000
//Android微信端(類Android內建瀏覽器)--1483228800000
//iOS微信端(類Safari瀏覽器)--1483228800000

let a1 = Date.parse('2017/1/1');
console.log(a1);
//chrome瀏覽器--1483200000000
//Android微信端(類Android內建瀏覽器)--1483200000000
//iOS微信端(類Safari瀏覽器)--1483200000000
let b1 = Date.parse('2017/01/1');
console.log(b1);
//chrome瀏覽器--1483200000000
//Android微信端(類Android內建瀏覽器)--1483200000000
//iOS微信端(類Safari瀏覽器)--1483200000000
let c1 = Date.parse('2017/01/01');
console.log(c1);
//chrome瀏覽器--1483200000000
//Android微信端(類Android內建瀏覽器)--1483200000000
//iOS微信端(類Safari瀏覽器)--1483200000000
複製程式碼

驚不驚喜!神不神奇!iOS的瀏覽器是無法解析2017-1-1和2017-01-1(2017-1-01)這兩類格式的日期。所以如果用童鞋們在寫日曆元件的時候發現安卓和iOS行為不一致的時候不妨看看日期格式那邊是否存在問題。

總的來說,在移動端中使用'/'作為日期分割是最保險的,但是這一般與前端展示的期望不一,這時候就改取捨一下,是用多的程式碼量來提高專案容錯率還是嚴格控制自己的日期格式...

②專案引入了"完美時間外掛moment.js"但是它又粗又大...

也許有些童鞋還不太瞭解moment,可以點選傳送門看看它的文件。

不得不說它的功能確實很強大,基本可以滿足大部分專案對時間顯示或轉換的各種需求,它甚至還內建了語言包,只能說功能很強大並且用途很廣泛,看看GitHub上的star就大概能感受到它的地位了。

它這麼好用,用起來簡單粗暴,又粗又大又有什麼所謂呢?

其實不然,因為你沒有在專案打包之後整體的分析專案bundle的佔比。如果你是用webpack構建專案的話可以選擇使用webpack-bundle-analyzer來分析一下你的包體結構,如果在專案中引入了moment,你會發現它真的很大...

無論是站在專案角度還是使用者角度,個人認為都不應該草率的使用如此巨大的依賴包。並且,只要我們靜下來仔細分析一下我們的專案,會發現,其實我們對日期時間方面的需求並沒有想象中的那麼繁雜。

下面我會貼一個自己正在使用的工具類--

//用法--TimeStream(1500614243, 'CN-YMD')
function TimeStream(timestamp, type) {
    let date = new Date(timestamp * 1000);
    let Y = date.getFullYear();
    let M = (date.getMonth() + 1 < 10 ? '0' + (date.getMonth() + 1) : date.getMonth() + 1);
    let D = date.getDate() < 10 ? '0' + date.getDate() : date.getDate();
    let h = date.getHours() < 10 ? '0' + date.getHours() : date.getHours();
    let m = date.getMinutes() < 10 ? '0' + date.getMinutes() : date.getMinutes();
    let s = date.getSeconds();

    switch (type) {
        case 'YMD': //年-月-日
            return Y + '-' + M + '-' + D;
        case 'MD': //月-日
            return M + '-' + D;
        case 'MD_HM': //月-日
            return M + '-' + D + ' ' + h + ':' + m;
        case 'YMD_HMS': // 月-日 時:分:秒
            return Y + '-' + M + '-' + D + ' ' + h + ':' + m + ':' + s;
        case 'CN_YMD': //x年x月x日
            return Y + '年' + M + '月' + D + '日';
        case 'CN_YMD_HM': //x年x月x日
            return Y + '年' + M + '月' + D + '日' + ' ' + h + ':' + m;
        case 'hm': // 時:分
            return h + ':' + m;
        case '-D': //天數差
            return Math.floor(((timestamp * 1000) - Date.parse(new Date())) / 1000 / 3600 / 24);
        case '-H': //小時差
            return Math.ceil((timestamp * 1000 - Date.parse(new Date())) / 1000 / 3600);
        default: //年-月-日 時:分
            return Y + '-' + M + '-' + D + ' ' + h + ':' + m;
    }
}
複製程式碼

這是我正在使用的自己寫的有關時間的工具類,當然它與我們的專案是密切結合的(其實就我們的專案而言也只需要這幾種型別的轉換),並且它可以靈活的根據需求的變化而變化,用法也並不算很麻煩,只要稍作註釋,任何同事都可以隨心使用。

以上工具類肯定還有很多別的更優寫法,我只是想借助這個解釋一下為什麼我不提倡盲目使用moment(可代入任何又粗又大的依賴),要知道,在這幾十行程式碼誕生之前,我們用著的是一個Gzip過後還有幾十K的依賴。

移動端中踩過的關於日曆&時間的坑

相關文章