摘要:然而由于地球的不規則自轉,導致時間有誤差,因此目前已不被當作標準時間使用。而在航空上,所有使用的時間劃一規定是協調世界時。
一個多月沒更新了- -偷懶中。這個東西其實很早之前就在整理了,不過后來發現自己不少地方沒弄明白,然后就一直卡那邊了(其實就是不想寫吧),想了下反正是給自己熟悉js的原生API而已,所以也沒必要太鉆牛角尖,也不一定要多完整,因此就當是Date()函數的一個冷門知識點小補充吧。這篇文章主要講Date()的字符串與時間戳轉換以及用戶時間本地化,可能內容上比較亂(不然也不會卡我一個月時間了),見諒
ps:由于Date()是js原生函數,不同瀏覽器的解析器對其實現方式并不同,所以返回值也會有所區別。本文測試未特別申明瀏覽器的情況下,均是指win7 x64+chrome 44.0.2403.155 (正式版本) m (32 位)版本
Date()與new Date()的區別Date()直接返回當前時間字符串,不管參數是number還是任何string
Date(); Date("sssss"); Date(1000); //Fri Aug 21 2015 15:46:21 GMT+0800 (中國標準時間)
而new Date()則是會根據參數來返回對應的值,無參數的時候,返回當前時間的字符串形式;有參數的時候返回參數所對應時間的字符串。new Date()對參數不管是格式還是內容都要求,且只返回字符串,
new Date(); //Fri Aug 21 2015 15:51:55 GMT+0800 (中國標準時間) new Date(1293879600000); new Date("2011-01-01T11:00:00") new Date("2011/01/01 11:00:00") new Date(2011,0,1,11,0,0) new Date("jan 01 2011,11 11:00:00") new Date("Sat Jan 01 2011 11:00:00") //Sat Jan 01 2011 11:00:00 GMT+0800 (中國標準時間) new Date("sss"); new Date("2011/01/01T11:00:00"); new Date("2011-01-01-11:00:00") new Date("1293879600000"); //Invalid Date new Date("2011-01-01T11:00:00")-new Date("1992/02/11 12:00:12") //596069988000
從上面幾個測試結果可以很容易發現
new Date()在參數正常的情況只會返回當前時間的字符串(且是當前時區的時間)
new Date()在解析一個具體的時間的時候,對參數有較嚴格的格式要求,格式不正確的時候會直接返回Invalid Date,比如將number類的時間戳轉換成string類的時候也會導致解析出錯
雖然new Date()的返回值是字符串,然而兩個new Date()的結果字符串是可以直接相減的,結果為相差的毫秒數。
那么,new Date()能接受的參數格式到底是什么標準呢?(相對于嚴格要求的多參數傳值方法。非嚴格的單參數(數字日期表示格式)更常用且更容易出錯,所以下文只考慮單參數數字時間字符串轉換的情況)
new Date()解析所支持的參數格式標準 時間戳格式這個是最簡單的也是最不容易出錯的。當然唯一的缺點大概就是對開發者不直觀,無法一眼看出具體日期。
需要注意的以下兩點:
時間數字字符串格式js內的時間戳指的是當前時間到1970年1月1日00:00:00 UTC對應的毫秒數,和unix時間戳不是一個概念,后者表示秒數,差了1000倍
new Date(timestamp)中的時間戳必須是number格式,string會返回Invalid Date。所以比如new Date("11111111")這種寫法是錯的
不大清楚這種該怎么描述,就是類似YYYY/MM/DD HH:mm:SS這種。下文以dateString代指。
new Date(dateString)所支持的字符串格式需要滿足RFC2822標準或者ISO 8601標準
這兩種標準對應的格式分別如下:
RFC2822 標準日期字符串
YYYY/MM/DD HH:MM:SS ± timezon(時區用4位數字表示) // eg 1992/02/12 12:23:22+0800
RFC2822還有別的格式,不過上面這個是比較常用的(另外這標準太難啃了,實在沒耐心啃完,所以也就沒太深入)。RFC2822標準本身還有其他的非數字日期表達方式,不過不在這個話題討論范圍內了,略過
ISO 8601標準日期字符串
YYYY-MM-DDThh:mm:ss ± timezone(時區用HH:MM表示) 1997-07-16T08:20:30Z // “Z”表示UTC標準時區,即"00:00",所以這里表示零時區的`1997年7月16日08時20分30秒` //轉換成位于東八區的北京時間則為`1997年7月17日16時20分30秒` 1997-07-16T19:20:30+01:00 // 表示東一區的1997年7月16日19時20秒30分,轉換成UTC標準時間的話是1997-07-16T18:20:30Z
日期和時間中間的T不可以被省略,一省略就出錯。
雖然在chrome瀏覽器上時區也可以用+0100這種RFC2822的形式來表示,然而IE上不支持這種混搭寫法,所以用ISO8601標準形式表示的時候時區要用+HH:MM
單單從格式上來說,兩者的區別主要在于分隔符的不同。不過需要注意的是,ISO 8601標準的兼容性比RFC2822差得多(比如IE8和iOS均不支持前者。我知道IE8很多人會無視,不過iOS也有這個坑的話,各位或多或少會謹慎點了吧?),所以一般情況下建議用RFC 2822格式的。
不過需要注意的是,在未指定時區的前提下,對于只精確到day的日期字符串,RFC 2822返回結果是以當前時區的零點為準,而ISO8601返回結果則會以UTC時間的零點為標準進行解析。
例如:
//RFC2822: new Date("1992/02/13") //Thu Feb 13 1992 00:00:00 GMT+0800 (中國標準時間) //ISO8601: new Date("1992-02-13") //Thu Feb 13 1992 08:00:00 GMT+0800 (中國標準時間)
然而上面這個只是ES5的標準而已,在ES6里這兩種形式都會變成當前時區的零點為基準1不管你們崩潰沒,反正我是已經想死了
關于跨瀏覽器的dataString解析情況,還可以參考這個頁面:
JavaScript and Dates, What a Mess!
所以對于時間字符串對象,個人意見是要么用RFC2822形式,要么自己寫個解析函數然后隨便你傳啥格式進來。
時間格式化函數的效率這里的時間格式化值得是將時間字符串轉換成毫秒數的過程。js原生的時間格式化函數有Date.parse、Date.prototype.valueOf、Date.prototype.getTime、Number(Date)、+Date(還有個Date.UTC方法,然而對參數要求嚴格,不能直接解析日期字符串,所以略過)
這5個函數從功能上來說一模一樣,但是具體的效率如何呢?我寫了個檢測頁面,諸位也可以自己測試下。
http://codepen.io/chitanda/pen/NqeZag/
function test(dateString,times,func){ var startTime=window.performance.now(); // console.log("start="+startTime.getTime()); for (var i = 0; i < times; i++) { func(dateString);//這里填寫具體的解析函數 }; var endTime=window.performance.now(); // console.log("endTime="+endTime.getTime()); var gapTime=endTime-startTime; console.log("一共耗時:"+gapTime+"ms"); // console.log("時間字符串"+dateString); return gapTime; }
測試結果:之所以這里用window.performance.now()而不用new Date(),是因為前者精確度遠比后者高。后者只能精確到ms。會對結果造成較大影響
單次執行50W次時間格式化函數,并重復測試100次,最后的結果如下:
(表格中的數字為單次執行50W次函數的平均結果。單位為毫秒)
函數 | chrome | IE | Firefox |
---|---|---|---|
Date.parse() | 151.2087 | 55.5811 | 315.0446 |
Date.prototype.getTime() | 19.5452 | 21.3423 | 14.0169 |
Date.prototype.valueOf() | 20.1696 | 21.7192 | 13.8096 |
+Date() | 20.0044 | 31.3511 | 22.7861 |
Number(Date) | 23.0900 | 24.8838 | 23.3775 |
從這個表格可以很容易得出以下結論:
UTC,GMT時間的區別從計算效率上來說,Date.prototype.getTime()≈Date.prototype.valueOf()>+Date≈Number(Date)>>Date.parse()
從代碼書寫效率上來說,對于少量的時間格式化計算,用+Date()或者Number(Date)即可。而若頁面內有大量該處理,則建議用Date原生的函數Date.prototype.getTime()或者Date.prototype.valueOf().只有Date.parse,找不到任何使用的理由。
這個結果和計算機的計算性能以及瀏覽器有關,所以具體數字可能會有較大偏差,很正常。然而幾個函數結果的時間差大小順序并不會變。
codepen的在線demo限制比較大,對于這個測驗個人建議最好將源代碼復制到本地文件然后進行測試
這個不是啥重要東西,單純當課外知識吧。
格林威治標準時間GMTGMT即「格林威治標準時間」(Greenwich Mean Time,簡稱G.M.T.),指位于英國倫敦郊區的皇家格林威治天文臺的標準時間,因為本初子午線被定義為通過那里的經線。然而由于地球的不規則自轉,導致GMT時間有誤差,因此目前已不被當作標準時間使用。
世界協調時間UTCUTC是最主要的世界時間標準,是經過平均太陽時(以格林威治時間GMT為準)、地軸運動修正后的新時標以及以「秒」為單位的國際原子時所綜合精算而成的時間。UTC比GMT來得更加精準。其誤差值必須保持在0.9秒以內,若大于0.9秒則由位于巴黎的國際地球自轉事務中央局發布閏秒,使UTC與地球自轉周期一致。不過日常使用中,GMT與UTC的功能與精確度是沒有差別的。
協調世界時區會使用“Z”來表示。而在航空上,所有使用的時間劃一規定是協調世界時。而且Z在無線電中應讀作“Zulu”(可參見北約音標字母),協調世界時也會被稱為“Zulu time”。
首先需要注意一點,瀏覽器獲取當前用戶所在的時區等信息只和系統的日期和時間設置里的時區以及時間有關。區域和語言設置影響的是瀏覽器默認時間函數(Date.prototype.toLocaleString等)顯示的格式,不會對時區等有影響。以window為例,控制面板時鐘、語言和區域中的兩個子設置項目的區別如下:
日期和時間:設置當前用戶所處的時間和時區,瀏覽器獲取到的結果以此為準,哪怕用戶的設置時間和時區是完全錯誤的。比如若東八區的用戶將自己的時區設置為東9區,瀏覽器就會將視為東9區;時間數據上同理。這里的設置會影響Date.prototype.getTimezoneOffset、new Date()的值
區域和語言:主要是設置系統默認的時間顯示方式。其子設置的格式會影響Date.prototype.toLocaleString方法返回的字符串結果
瀏覽器判斷用戶本地字符串格式Date有個Date.prototype.toLocaleString()方法可以將時間字符串返回用戶本地字符串格式,這個方法還有兩個子方法Date.prototype.toLocaleDateString和Date.prototype.toLocaleTimeString,這兩個方法返回值分別表示日期和時間,加一起就是Date.prototype.toLocaleString的結果。
這個方法的默認參數會對時間字符串做一次轉換,將其轉換成用戶當前所在時區的時間,并按照對應的系統設置時間格式返回字符串結果。然而不同瀏覽器對用戶本地所使用的語言格式的判斷依據是不同的。
IE:獲取系統當前的區域和語言-格式中設置的格式,依照其對應的格式來顯示當前時間結果;IE瀏覽器實時查詢該系統設置(即你在瀏覽器窗口打開后去更改系統設置也會引起返回格式變化)
FF:獲取方式和結果與IE瀏覽器相同,區別在于FF只會在瀏覽器進程第一次啟動的時候獲取一次系統設置,中間不管怎么系統設置怎么變化,FF都無法獲取到當前系統設置。除非重啟FF瀏覽器。
Chrome:獲取方式和以上兩個都不同。chrome無視系統的區域和語言-格式格式,只依照自己瀏覽器的界面設置的菜單語言來處理。(比如英文界面則按系統"en-US"格式返回字符串,中文界面則按系統"zh-CN"格式返回結果)
綜上可得:
瀏覽器界面語言設置和語言設置的區別chrome下瀏覽器語言設置優先系統語言設置。而IE和FF則是系統語言設置優先瀏覽器語言設置,不管瀏覽器界面語言是什么,他們只依照系統設置來返回格式。(沒有MAC,所以不知道safari是啥情況,等以后看情況補充吧)
另外,不同瀏覽器對toLocaleString返回的結果也是不同的,IE瀏覽器嚴格遵守系統設置,而chrome和FF會有自己內置的格式來替換。
這小節貌似有點跑題,然而不說明下的很容易和上面提到的瀏覽器設置的語言混淆,所以也拿出來說一下。
需要注意瀏覽器的語言設置和界面語言設置不是一回事。
瀏覽器的語言設置設置的是瀏覽器發送給服務器的Request Header里的Accept-Language的值,這個值可以告訴服務器用戶的喜好語言,對于某些跨國網站,服務器可以以此為依舊來返回對應語言的頁面(不過實際應用上這個限制比較大,大部分網站還是根據IP來判斷用戶來源的,或者直接讓用戶自己選擇)
對于各大瀏覽器而言,這個設置的更改也是比較顯性,容易找到的。
IE: Internet選項-語言
FF: 選項-內容-語言
chrome:設置-顯示高級設置-語言-語言和輸入設置...
上面這里的設置不會影響到瀏覽器的界面語言設置,以國內大部分用戶而言,即不管你怎么設置這里的語言選項,瀏覽器菜單等默認都會是以中文顯示的.
而瀏覽器的界面語言設置一般來說則藏的深得多,沒那么容易找到。
IE:
卸載前面安裝過的瀏覽器語言包,去微軟官網下載對應的IE瀏覽器語言包安裝。(和安裝的語言包有關。系統界面語言和該語言包相同的情況下,變為該語言。否則以安裝的語言包為準。)
FF:地址欄輸入about:config,然后找到general.useragent.locale字段,修改對應字段即可。
chrome:設置-顯示高級設置-語言-語言和輸入設置...
對于獲取這兩種設置,js原生方法支持度都比較一般:
IE下的navigator方法有四種和language有關的方法,區別如下:
假設系統語言為 ja-JP,系統unicode語言為zh-CN日期格式為nl-NL,瀏覽器語言設置(accept-language)為de,瀏覽器界面語言為en-US(其他條件不變,瀏覽器界面語言改為zh-CN的時候結果也是一樣),
window.navigator.language //"nl-NL" window.navigator.systemLanguage //"zh-CN"(設置中的非unicode程序所使用語言選項) window.navigator.userLanguage //"nl-NL" window.navigator.browserLanguage //"ja-JP"(系統菜單界面語言) window.navigator.languages //undefined
chrome下,當瀏覽器界面語言為zh-CN,accept-language首位為en-US的時候:
window.navigator.language //"zh-CN" window.navigator.languages //["en-US", "en", "zh-CN", "zh", "ja", "zh-TW", "de-LI", "de", "pl"] //當界面語言改為"en-US"時 window.navigator.language //"en-US"(瀏覽器界面語言)
FF下,當瀏覽器界面語言為zh-CN,accept-language首位為en-US的時候:
window.navigator.language //"en-US" window.navigator.languages //["en-US", "zh-CN", "de", "zh", "en"] //當界面語言改為"en-US",`accept-language`首位為`zh-CN`的時候 window.navigator.language //"zh-CN"(`accept-language`首選值) window.navigator.languages //["zh-CN", "de", "zh", "en-US", "en"]
從上面的測試結果可以很明顯的發現IE瀏覽器的這幾個函數都是獲取系統信息的,無法獲取到前面提到的兩個瀏覽器層面上的設置。(這幾個函數具體含義還有疑問的可以參考MSDN官方文檔)
window.navigator.language這個函數雖然三個瀏覽器都可以兼容,然而代表的意義完全不同。IE下該函數返回系統設置的時間顯示格式所遵守的標準的地區代碼;chrome下返回瀏覽器界面語言;FF下返回accept-language的首選語言值
由此:
總結瀏覽器設置的語言即accept-language值,IE瀏覽器無法利用JS獲取。chrome和FF瀏覽器都可以利用window.navigator.languages來獲取,而FF還可以直接用 window.navigator.language直接獲取accept-language的首選語言值。所以對于accept-language,兼容性最好的獲取方法應該是利用后端,發起一個ajax請求,分析header。而不是直接js來處理。
瀏覽器界面語言,IE和FF都無法利用js來獲取,chrome可以用window.navigator.language來獲取
系統級別的語言設置(系統菜單界面語言,系統設置的時間顯示格式),chrome和FF都無法用JS獲取到
這篇文章斷斷續續地寫了一個多月,不過由于對Date()函數的掌握不足因此個人感覺其實還是思路有點亂,所以文章看起來可能稍微有點跳躍性。不過用戶本地化那塊內容確實用了不少心思去寫,希望對看到這篇文章的人有點幫助。
參考文獻Date and Time Formats
Date and Time Specification(RFC2822)
Date.parse()-Differences in assumed time zone
JavaScript and Dates, What a Mess!
navigator object(IE瀏覽器私有language函數的解析)
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://m.specialneedsforspecialkids.com/yun/85943.html
摘要:例如要刪除數組的第個元素,可以使用這樣的語句不過對于大型數組來說,這個函數的效率可能不高。可選參數可以限制被分割的片段數量。看代碼吧下面的代碼利用的來實現垂直居中和水平居中轉自快樂人生,積極進取總結的一些的冷知識 1、!!將一個值方便快速轉化為布爾值 console.log( !!window===true ); 2、不聲明第三個變量實現交換 var a=1,b=2; a=[b...
摘要:在對前端開發熟悉之后,對坑的定義也發生了變化,所以記錄的反而少了,留下的都是些比較實用的方法。現在看回來,今年踏出的不尋常的一步是接觸了。他確實給前端工程師提供了一個方便編寫安卓應用的方法,但是對于一些奇葩需求還是需要自己對接原生模塊。 在博客閱讀:https://ssshooter.com/2019-04... 距離同系列上一篇已經一年了...還是要驚嘆時間過得是如此之快。在對前端開...
摘要:但是,有一件事是肯定的年對全棧開發者的需求量很大。有一些方法可以解決這個問題,例如模式,或者你可以這么想,其實谷歌機器人在抓取單頁應用程序時沒有那么糟糕。谷歌正在這方面努力推進,但不要指望在年會看到任何突破。 對于什么是全棧開發者并沒有一個明確的定義。但是,有一件事是肯定的:2019 年對全棧開發者的需求量很大。在本文中,我將向你概述一些趨勢,你可以嘗試根據這些趨勢來確定你可能要投入的...
摘要:但是,有一件事是肯定的年對全棧開發者的需求量很大。有一些方法可以解決這個問題,例如模式,或者你可以這么想,其實谷歌機器人在抓取單頁應用程序時沒有那么糟糕。谷歌正在這方面努力推進,但不要指望在年會看到任何突破。 對于什么是全棧開發者并沒有一個明確的定義。但是,有一件事是肯定的:2019 年對全棧開發者的需求量很大。在本文中,我將向你概述一些趨勢,你可以嘗試根據這些趨勢來確定你可能要投入的...
閱讀 3619·2021-11-15 11:38
閱讀 2813·2021-11-11 16:55
閱讀 2567·2021-11-08 13:22
閱讀 2641·2021-11-02 14:45
閱讀 1325·2021-09-28 09:35
閱讀 2609·2021-09-10 10:50
閱讀 476·2019-08-30 15:44
閱讀 2788·2019-08-29 17:06