一个多月没更新了- -偷懒中。这个东西着实很早之前就在整理了,不过厥后发明自身不少地方没弄邃晓,然后就一向卡那边了(着实就是不想写吧),想了下反恰是给自身熟习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 |
从这个表格能够很轻易得出以下结论:
从盘算效力上来讲,
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限定比较大,关于这个考试个人提议最好将源代码复制到当地文件然后举行测试
UTC,GMT时刻的区分
这个不是啥主要东西,纯真当课外学问吧。
格林威治规范时刻GMT
GMT即「格林威治规范时刻」(Greenwich Mean Time,简称G.M.T.),指位于英国伦敦郊区的皇家格林威治天文台的规范时刻,由于本初子午线被定义为经由过程那边的经线。然则由于地球的不规则自转,致使GMT时刻有偏差,因而现在已不被看成规范时刻运用。
天下谐和时刻UTC
UTC是最主要的天下时刻规范,是经由均匀太阳时(以格林威治时刻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猎取用户浏览器言语喜欢
关于猎取这两种设置,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()
函数的控制不足因而个人感觉着实照样思绪有点乱,所以文章看起来能够轻微有点腾跃性。不过用户当地化那块内容确切用了不少心机去写,愿望对看到这篇文章的人有点协助。