幾個原生小函數去掉項目moment.js依賴

moment.js做爲一個全球通用庫,須要作許多兼容,致使其大而全.在平常項目開發中,每每用不到幾個API.我的參與維護的B端項目,組內同事使用其API集中在日期選擇組件及先後端日期格式化傳遞處理上.在項目優化時,經過組內內部約定,採用幾個小函數去除moment.js的依賴,可顯著減小項目打包體積(moment.min.js 52Kb, moment-with-locales.min.js 327Kb).html

日期/時間格式化展現

在與後端進行數據交接時,後端一般接收/傳遞2018-10-15 15:34:33形式的標準格式,前端在日期選擇組件裏展現給用戶時,也會採用該格式.定義一個函數將日期對象轉換爲該類字符返回.前端

export function getDateTime(date = new Date()) {
    let arr = [];
    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(':)}`;
}
複製代碼

後續可經過該標準日期格式,再二次處理得到一些經常使用的格式:git

  • 只須要日期部分: getDateTime(date).slice(0, 10)
  • 只須要時間部分: getDateTime(date).slice(10)/getDateTime(date).slice(-8)
  • 去掉前置的0: getDateTime(date).replace(/([-|:|\s])0/g, "$1")
// 獲取標準時間格式hack方法.
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對象

從接口獲取到時間字符串,須要轉換爲日期對象進行後續的區間計算等操做,如計算昨天,今天,近一週,近一個月.github

export function toDate(string) {
    const args = string.split(/[\-:\s]/);
    args[1] -= 1;
    return new Date(...args);
}
// 這裏有隱性轉換, '09' 經過減法運算或給Date()構造函數傳遞多參數,會轉整.
// 若是是ES5,這裏spread運算符怎麼寫? https://babeljs.io/en/repl.html
複製代碼

日期區間計算

在訂單查詢等業務中,常常會提供今天,昨天,近一週,近一個月等便捷日期選擇查詢方式,前端須要根據當前日期結合用戶操做,轉換爲後端須要的時間格式進行查詢操做.後端

對於天/時/分/秒,能夠加減相應的秒數來處理.babel

const ONE_DAY = 86400000;
export function getOffsetDay(offset = 0, date = new Date()) {
    const seconds = date.getTimes();
    const days = new Date(seconds + ONE_DAY * offset);
    return getDateTime(days).slice(0, 10);
}
複製代碼

對於月份,計算秒數較複雜,能夠利用setMonth來簡便處理.不過須要考慮天然月邏輯(7/31減一個月是6/30,而不是7/1(6/31)).less

export function getOffsetMonth(offset = 0, date = new Date()) {
    const year = date.getFullYear();
    const month = date.getMonth();
    const day = date.getDate();
    //can add if day >28 for less cacl monthlastday
    const monthLastDay = new Date(new Date(year, month+1 + offset, 1, 1) - ONE_DAY).getDate();
    if (day > monthLastDay) date.setDate(monthLastDay);
    date.setMonth(month + offset);
    return getDateTime(date).slice(0, 10);
}
複製代碼

日期比較

日期轉換爲上面的標準字符格式後,能夠直接採用字符串來比較(早於,晚於,等於).日期對象可顯式轉換爲毫秒數(date.getTime()) 或 隱式(調valueOf())來進行比較. 特定區間的日期比較,則能夠用上面的函數將日期字符轉換爲日期對象,加減相應的毫秒數後再用簡單的比較方式處理.函數

notice

  • date.set**相關函數會有相應的進位處理.
  • date.set**返回值爲設置後日期對象的時間戳
  • 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深拷貝對象時須要將時間字符轉換回來.

文章推薦

developer.mozilla.org/en-US/docs/…優化

GitHub勘誤/交流: github.com/pagemarks/c…ui

相關文章
相關標籤/搜索