1. 程式人生 > >坑人的toLocaleDateString和簡單地跳坑方式

坑人的toLocaleDateString和簡單地跳坑方式

  最近在做一個一個醫學大資料的專案的時候,獨立設計、構思、製作了完成了一個生命歷程圖的功能。既然設計到時間,那就免不了對Date物件進行一系列的操作,也就免不了對日期物件進行一系列的格式化。走的路多了,難免遇到坑。其中toLocaleDateString就是一個天坑。

  今天,上司和我說:“阿倫啊,你那個小卡片領導有點不滿意啊,你再研究一下。”於是乎,我就開始了和UI的深入淺出地研究,最終定下了一版,我成功地把他實現了。當時我就跑到專案組每個人的電腦前讓他們瞅瞅,我當時的想法是這樣的:

  但是,等等?what?納尼?(⊙o⊙)?我在專案組資料分析師的電腦上看到了驚悚的一幕,類似這樣的:

  我有跑回去瞅了一下我的電腦,依舊完美地執行著。那麼問題是什麼呢?開啟資料分析師的瀏覽器控制檯,發現了一個報錯“Unable to get property ‘mouths’ of undefined or null refernce”,雖然我屬於英語困難戶型別的,但是這句話也能猜個八九不離十,大概就是這個屬性沒找到。我分別對其上一層物件進行了列印,結果在我這裡正常,在同事那裡就是undefind。那麼問題就來了,資料分析師使用的是搜狗瀏覽器,而博主使用的是chrome瀏覽器。因此,很可能是相容的問題。於是乎,博主繼續向上級列印。發現有一個數據dateEnd在我這裡為“2018/3/2”,在同事那裡是“2018年3月2日”。原因找到了,我在對這個資料進行處理的時候使用了字串轉陣列的split('/'),但是問題是‘2018年3月2日’並沒有“-”,所以只能被轉換成了length為1的['2018年3月2日'],因此無法進行下一步處理了。

  我研究了一下搜狗瀏覽器,發現其和360瀏覽器差不多,都有相容模式和極速模式。相容模式是使用了ie的核心,極速模式使用了webkit核心。而這個專案暫時是用ip地址登陸的,所以無意間觸發了ie的Trident核心,因此引發了某些相容問題。

  找到問題後,博主查看了一下這個日期資料的來源,發現是一個程式碼"new Date().toLocaleDateString()",即對當前的額日期資料進行格式化。於是乎,我分別在chrome瀏覽器和ie瀏覽器列印了一下,得到的結果分別是"2018/3/2"和"2018年3月2日"。

  博主去MDN查詢相關屬性,結果發現了這樣一段話“toLocaleDateString()

 方法返回該日期物件日期部分的字串,該字串格式因不同語言而不同。新增的引數 locales 和 options 使程式能夠指定使用哪種語言格式化規則,允許定製該方法的表現(behavior)。在舊版本瀏覽器中, locales 和 options 引數被忽略,使用的語言環境和返回的字串格式是各自獨立實現的。”貌似以前錯過了什麼,居然還有引數。也就是說不配置引數的話可能結果會隨著瀏覽器的變化而變化。

  經過測試,樓主發現在不同的瀏覽器結果是這樣的:

# firefox
> new Date().toLocaleDateString()
> "2017/5/12"

#IE11
> new Date().toLocaleDateString()
> "2017-5-12"

#Chrome
> new Date().toLocaleDateString()
> "2017/5/12"

#Edge
> new Date().toLocaleDateString()
> "‎2018‎年‎3‎月‎2‎日"

  我只是想靜靜地處理一下日期,你卻這麼對我,我選擇toLocaleDateString() 狗帶。

  於是,我就隨便寫下了`/${new Date().getFullYear()}/${new Date().getMonth()}${new Date().getDate()}`。OK,收工。

  生命在於折騰,完成專案之後,我用正則和簡單的方法寫了一個小的方法作為下次在遇到時的對策:

 1 var Format = function(date, rule) {
 2     this.time = date ? date : (new Date());
 3     this.rule = rule;
 4     if (this.rule) {
 5         this.standard()
 6     }
 7 }
 8 Format.prototype.standard = function() {
 9     let date = new Date(this.time)
10     if (date == 'Invalid Date') {
11         let reg1 = /^(\d{3,6}年)?\d{1,2}月(\d{1,2}日)?$/g,
12             reg2 = /^\d{1,2}月(\d{1,2}日)?(\d{1,6}年)?$/g,
13             reg3 = /^(\d{1,2}日)?\d{1,2}月(\d{1,6}年)?$/g,
14             reg4 = /^\d{3,6}年$/;
15         if (this.time.match(reg1)||this.time.match(reg2)||this.time.match(reg3)||this.time.match(reg4)){
16             let timeRule 
17                 = new Date(`${(this.time.match(/\d{3,6}年/g))?(this.time.match(/\d{3,6}年/g)[0].replace(/年/g,'')
18                 .split('').reverse().concat([0,0,0,0,0,0]).reverse().slice(2).join(''))+'-':''}` 
19                 +`${(this.time.match(/\d{1,2}月/g))?(this.time.match(/\d{1,2}月/g)[0].replace(/月/g,''))+'-':''}`
20                 +`${(this.time.match(/\d{1,2}日/g))?(this.time.match(/\d{1,2}日/g)[0].replace(/日/g,'')):''}`);
21             return timeRule == 'Invalid Date' ? '請輸入正確的日期數字' : timeRule
22         } else {
23             return '請輸入正確的日期,如2000年1月1日、2000-1-1或2000/1/1'
24         }
25     } else {
26         this.time = new Date(this.time)
27         return this.time
28     }
29 }
30 Format.prototype.change = function() {
31     if (!this.rule) {
32         return this.standard()
33     } else if (this.rule == 'chinese' || this.rule == 'line' || this.rule == 'slash') {
34         let date = new Date(this.standard()).toDateString().split(' ');
35         var month = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dece"];
36         for (var i = 0; i < month.length; i++) {
37             if (date[1] == month[i]) {
38                 date[1] = i + 1
39             }
40         }
41         if (this.rule == 'chinese') {
42             return `${Number(date[3])}年${Number(date[1])}月${Number(date[2])}日`
43         } else if (this.rule == 'line') {
44             return `${Number(date[3])}-${Number(date[1])}-${Number(date[2])}`
45         } else {
46             return `${Number(date[3])}/${Number(date[1])}/${Number(date[2])}`
47         }
48     } else {
49         return '請輸入正確的格式化引數:chinese、line或slash'
50     }
51 }

  呼叫的方法為:

 1 new Format('2011年10月1日').standard()
 2 //Sat Oct 01 2011 00:00:00 GMT+0800 (中國標準時間)
 3 
 4 new Format('Sat Oct 01 2011 00:00:00 GMT+0800 (中國標準時間)', 'line').change()
 5 //2011-11-1
 6 
 7 new Format('Sat Oct 01 2011 00:00:00 GMT+0800','chinese').change()
 8 //2011年11月1日
 9 
10 new Format('Sat Oct 01 2011 00:00:00 GMT+0800','slash’).change()
11 //2011/11/1
12 
13 new Format('2011-11-1').change()
14 //Sat Nov 01 2011 00:00:00 GMT+0800 (中國標準時間)

   如果您覺得我的博文有用,請不要吝嗇您的關注。如需轉載,請標明出處,謝謝。