JavaScript 时间与日期处理实战:你肯定被坑过
转载自:http://web.jobbole.com/89120/
本部分的知识图谱请参考编程语言知识图谱-时间与日期。
本文JavaScript 时间与日期处理实战:你肯定被坑过从属于笔者的Web 前端入门与最佳实践中 JavaScript 入门与最佳实践系列文章。
标准时间
GMT即「格林威治标准时间」(Greenwich Mean Time,简称G.M.T.),指位于英国伦敦郊区的皇家格林威治天文台的标准时间,因为本初子午线被定义为通过那里的经线。然而由于地球的不规则自转,导致GMT时间有误差,因此目前已不被当作标准时间使用。UTC是最主要的世界时间标准,是经过平均太阳时(以格林威治时间GMT为准)、地轴运动修正后的新时标以及以「秒」为单位的国际原子时所综合精算而成的时间。UTC比GMT来得更加精准。其误差值必须保持在0.9秒以内,若大于0.9秒则由位于巴黎的国际地球自转事务中央局发布闰秒,使UTC与地球自转周期一致。不过日常使用中,GMT与UTC的功能与精确度是没有差别的。协调世界时区会使用“Z”来表示。而在航空上,所有使用的时间划一规定是协调世界时。而且Z在无线电中应读作“Zulu”(可参见北约音标字母),协调世界时也会被称为“Zulu time”。
TimeZone&UTC Offsets:时区与偏移
人们经常会把时区与UTC偏移量搞混,UTC偏移量代表了某个具体的时间值与UTC时间之间的差异,通常用HH:mm形式表述。而TimeZone则表示某个地理区域,某个TimeZone中往往会包含多个偏移量,而多个时区可能在一年的某些时间有相同的偏移量。譬如America/Chicago, America/Denver, 以及 America/Belize在一年中不同的时间都会包含 -06:00 这个偏移。
时间戳
Unix时间戳表示当前时间到1970年1月1日00:00:00 UTC对应的秒数。注意,JavaScript内的时间戳指的是当前时间到1970年1月1日00:00:00 UTC对应的毫秒数,和unix时间戳不是一个概念,后者表示秒数,差了1000倍。
时间数字字符串格式
RFC2822
JavaScript
12 | YYYY/MM/DD HH:MM:SS ± timezone(时区用4位数字表示)// eg 1992/02/12 12:23:22+0800 |
ISO 8601
国际标准化组织的国际标准ISO 8601是日期和时间的表示方法,全称为《数据存储和交换形式·信息交换·日期和时间的表示方法》。目前最新为第三版ISO8601:2004,第一版为ISO8601:1988,第二版为ISO8601:2000。年由4位数组成,以公历公元1年为0001年,以公元前1年为0000年,公元前2年为-0001年,其他以此类推。应用其他纪年法要换算成公历,但如果发送和接受信息的双方有共同一致同意的其他纪年法,可以自行应用。
JavaScript1 2 3 4 5 6 | 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 |
Reference
- JS原生Date类型方法的一些冷知识
- 阮一峰 JavaScript标准参考教程 Date对象
JavaScript为我们提供了不是很好用的Date对象作为时间日期对象,Date()直接返回当前时间字符串,不管参数是number还是任何string。而new Date()则是会根据参数来返回对应的值,无参数的时候,返回当前时间的字符串形式;有参数的时候返回参数所对应时间的字符串。new Date()对参数不管是格式还是内容都要求,且只返回字符串,标准的构造Date对象的方法有:
JavaScript12345678910111213141516 | // 不带new操作符,像一个函数一样调用。它将忽略所有传入的参数,并返回当前日期和时间的一个字符串表示。new Date();// 可接受一个数字参数,该参数表示设定时间与1970年1月1日0点之间的毫秒数。new Date(value);// 可接受一个字符串参数,参数形式类似于Date.parse()方法。但parse()方法返回的是一个数字,而Date()函数返回的是一个对象。new Date(dateString);// 可接受参数形式类似于Date.UTC()方法的参数,但Date.UTC()方法返回是一个毫秒数,且是UTC时间,而Date()函数返回是一个对象,且是本地时间。new Date(year, month[, day[, hour[, minutes[, seconds[, milliseconds]]]]]);---------------------------------------------------------------------------------------------------------------------year:四位年份,如果写成两位数,则加上1900month:表示月份,0表示一月,11表示12月date:表示日期,1到31hour:表示小时,0到23minute:表示分钟,0到59second:表示秒钟,0到59ms:表示毫秒,0到999 |
这里需要注意的是,月份month参数,其计数方式从0开始,而天day参数,其计数方式从1开始。
JavaScript1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | 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 |
Parse:解析
TimeStamp:时间戳
如果需要从当前的时间对象获取其相应的时间戳,我们可以使用getTime或者valueOf(),返回距离1970年1月1日0点的毫秒数:
JavaScript12345678 | var date1 = new Date(2007,0,1);var date2 = new Date(2007,1,1);console.log(date1 > date2);//falseconsole.log(date1 < date2);//true// ECMAScript5新增了now()方法,该方法返回当前时间距离1970年1月1日0点UTC的毫秒数。该方法不支持传递参数Date.now = function(){ return (new Date()).getTime()} |
另外Date对象还有一个静态方法同样返回给定日期的毫秒数。但其参数并不是一个字符串,而是分别代表年、月、日、时、分、秒、毫秒的数字参数:
JavaScript1 2 3 4 5 6 | console.log(Date.UTC(1970));//NaN console.log(Date.UTC(1970,0));//0 console.log(Date.UTC(1970,0,2));//86400000 console.log(Date.UTC(1970,0,1,1));//3600000 console.log(Date.UTC(1970,0,1,1,59));//714000 console.log(Date.UTC(1970,0,1,1,59,30));//717000 |
还是需要强调下,JavaScript内的时间戳指的是当前时间到1970年1月1日00:00:00 UTC对应的毫秒数,和unix时间戳不是一个概念,后者表示秒数,差了1000倍。new Date(timestamp)
中的时间戳必须是number
格式,string
会返回Invalid
Date
。所以比如new Date("11111111")
这种写法是错的。
DateTimeString:时间日期字符串
JavaScript原生Date对于时间字符串的解析真的是槽点满满,假设我们希望以DD/MM/YYYY的格式进行解析,那么它是无法识别的:
JavaScript12 | var a = new Date("01/12/2016"); //December 1 2016 in DD/MM/YYYY format//"Tue Jan 12 2016 00:00:00 GMT-0600 (Central Standard Time)" |
另外,在ES5的标准中,其对ISO 8601标准的字符串进行了一个神奇的断言:所有没有提供时区的字符串默认为标准时区。换言之,你会发现你解析出来的时间和你预期中的不一样,而且它打印的时候是按照本地时区又进行了转换:
JavaScript1 2 3 4 5 6 7 | //US local format var a = new Date("1/1/2016"); //"Fri Jan 01 2016 00:00:00 GMT-0600 (Central Standard Time)" //ISO 8601 var a = new Date("2016-01-01"); //"Thu Dec 31 2015 18:00:00 GMT-0600 (Central Standard Time)" |
ES 2015标准中则是修复了该Bug,不过还是会让人觉得头大,毕竟你不知道你代码的最终运行环境会是ES5还是ES6。Date对象也有一个parse方法,用于解析一个日期字符串,参数是一个包含待解析的日期和时间的字符串,返回从1970年1月1日0点到给定日期的毫秒数。该方法会根据日期时间字符串格式规则来解析字符串的格式,除了标准格式外,以下格式也支持。如果字符串无法识别,将返回NaN。
- ‘月/日/年’ 如6/13/2004
- ‘月 日,年’ 如January 12,2004或Jan 12,2004
- ‘星期 月 日 年 时:分:秒 时区’ Tue May 25 2004 00:00:00 GMT-0700
JavaScript1234567 console.log(Date.parse("6/13/2004"));//1087056000000console.log(Date.parse("January 12,2004"));//1073836800000console.log(Date.parse("Tue May 25 2004 00:00:00 GMT-0700"));//1085468400000console.log(Date.parse("2004-05-25T00:00:00"));//1085443200000console.log(Date.parse("2016"));//1451606400000console.log(Date.parse("T00:00:00"));//NaNconsole.log(Date.parse());//NaN
在ECMAScript5中,如果使用标准的日期时间字符串格式规则的字符串中,数学前有前置0,则会解析为UTC时间,时间没有前置0,则会解析为本地时间。其他情况一般都会解析为本地时间
JavaScript1 2 3 | console.log(Date.parse("7/12/2016"));//1468252800000 console.log(Date.parse("2016-7-12"));//1468252800000 console.log(Date.parse("2016-07-12"));//1468281600000 |
Manipulate:时间对象操作
Get&Set
Date对象提供了一系列get*方法,用来获取实例对象某个方面的值。具体的Get函数列表详见附录:
JavaScript1234567 | var d = new Date("January 6, 2013"); d.getDate() // 6d.getMonth() // 0d.getYear() // 113d.getFullYear() // 2013d.getTimezoneOffset() // -480 |
同样的,Date对象还提供了一系列的Set方法:
JavaScript1 2 3 4 5 6 7 8 9 | var d1 = new Date("January 6, 2013"); d1.setDate(32) // 1359648000000 d1 // Fri Feb 01 2013 00:00:00 GMT+0800 (CST) var d2 = new Date ("January 6, 2013"); d.setDate(-1) // 1356796800000 d // Sun Dec 30 2012 00:00:00 GMT+0800 (CST) |
Add&Subtract
我们可以巧用Set方法的特性,set*方法的参数都会自动折算。以setDate为例,如果参数超过当月的最大天数,则向下一个月顺延,如果参数是负数,表示从上个月的最后一天开始减去的天数。
JavaScript1234567891011121314151617181920 | var d1 = new Date("January 6, 2013"); d1.setDate(32) // 1359648000000d1 // Fri Feb 01 2013 00:00:00 GMT+0800 (CST) var d2 = new Date ("January 6, 2013"); d.setDate(-1) // 1356796800000d // Sun Dec 30 2012 00:00:00 GMT+0800 (CST) var d = new Date(); // 将日期向后推1000天d.setDate( d.getDate() + 1000 ); // 将时间设为6小时后d.setHours(d.getHours() + 6); // 将年份设为去年d.setFullYear(d.getFullYear() - 1); |
Diff:计算差值
类型转换时,Date对象的实例如果转为数值,则等于对应的毫秒数;如果转为字符串,则等于对应的日期字符串。所以,两个日期对象进行减法运算,返回的就是它们间隔的毫秒数;进行加法运算,返回的就是连接后的两个字符串。
JavaScript1 2 3 4 5 6 7 8 | var d1 = new Date(2000, 2, 1); var d2 = new Date(2000, 3, 1); d2 - d1 // 2678400000 d2 + d1 // "Sat Apr 01 2000 00:00:00 GMT+0800 (CST)Wed Mar 01 2000 00:00:00 GMT+0800 (CST)" |
Display:时间展示
Format:格式化
Date对象提供了一系列的to*
方法来支持从Date对象转化为字符串,具体的函数列表详见附录:
12345678910111213141516171819202122232425 | var d = new Date(2013, 0, 1); d.toString()// "Tue Jan 01 2013 00:00:00 GMT+0800 (CST)" d.toUTCString()// "Mon, 31 Dec 2012 16:00:00 GMT" d.toISOString()// "2012-12-31T16:00:00.000Z" d.toJSON()// "2012-12-31T16:00:00.000Z" d.toDateString() // "Tue Jan 01 2013" d.toTimeString() // "00:00:00 GMT+0800 (CST)" d.toLocaleDateString()// 中文版浏览器为"2013年1月1日"// 英文版浏览器为"1/1/2013" d.toLocaleTimeString()// 中文版浏览器为"上午12:00:00"// 英文版浏览器为"12:00:00 AM" |
Durations:时长
JavaScript1 2 3 4 5 | const nMS = 1320; //以毫秒单位表示的差值时间 var nD = Math.floor(nMS/(1000 * 60 * 60 * 24)); var nH = Math.floor(nMS/(1000*60*60)) % 24; var nM = Math.floor(nMS/(1000*60)) % 60; var nS = Math.floor(nMS/1000) % 60; |
i18n:国际化
浏览器获取当前用户所在的时区等信息只和系统的日期和时间设置里的时区以及时间有关。区域和语言设置影响的是浏览器默认时间函数(Date.prototype.toLocaleString等)显示的格式,不会对时区等有影响。Date有个Date.prototype.toLocaleString()方法可以将时间字符串返回用户本地字符串格式,这个方法还有两个子方法Date.prototype.toLocaleDateString和Date.prototype.toLocaleTimeString,这两个方法返回值分别表示日期和时间,加一起就是Date.prototype.toLocaleString的结果。这个方法的默认参数会对时间字符串做一次转换,将其转换成用户当前所在时区的时间,并按照对应的系统设置时间格式返回字符串结果。然而不同浏览器对用户本地所使用的语言格式的判断依据是不同的。
- IE:获取系统当前的区域和语言-格式中设置的格式,依照其对应的格式来显示当前时间结果;IE浏览器实时查询该系统设置(即你在浏览器窗口打开后去更改系统设置也会引起返回格式变化)。假设系统语言为 ja-JP,系统unicode语言为zh-CN日期格式为nl-NL,浏览器语言设置(accept-language)为de,浏览器界面语言为en-US(其他条件不变,浏览器界面语言改为zh-CN的时候结果也是一样),
JavaScript
- 上一篇: JS~jwPlayer为js预留的回调方法大总结
- 下一篇:没有了