当前位置: 首页 > Web前端 > JavaScript

你考虑过时区吗?

时间:2023-03-26 22:20:48 JavaScript

前端工程师,当你拿到一个日期/时间数据,你是怎么处理的?考虑过时区问题吗?也许你会说:嗯,我没怎么注意时区,但是我测试了一下,没问题。我能说什么可能你还没有接触过外国用户吧!如果盗取的日期得到一个日期字符串“2021-11-17”,为了方便计算和数据处理,可以先封为一个Date对象:consts="2021-11-17";constd=new日期);现在使用d.getDate()看看你得到了什么?—17岁,没问题!其实——怎么说呢——因为你在中国。如果这个程序在浏览器中运行,而浏览器恰好位于加拿大,它还会是17吗?不妨试试。在Windows下进入时间设置,将时间改为“太平洋时间(美国和加拿大)”或UTC-XX:00的其他时区。去浏览器再看,你会发现d.getDate()得到了16!如果是Linux下,也可以重新设置系统时间,然后使用Node控制台查看,如下图:为什么少了一天?浏览器总是用本地时间来询问为什么少了一天,我们看看d是什么数据(记得先把时区改回来!)d.toString();//2021年11月17日星期三08:00:00GMT+0800(中国标准时间)d.toLocaleString();//2021/11/178:00:00am你看,当newDate("2021-11-17")创建一个日期对象时,它把2021-11-17创建的对象当作UTC00:00:00.而中国这个时间是2021-11-1708:00:00。同样,如果-06:00在加拿大中部,则为2021-11-1618:00:00,此时.getDate()当然会得到16。在处理时间的问题上,浏览器处理的简单粗暴,就是根据系统的时区设置,按照当地时间处理。如果我们给出一个精确的时间,浏览器这样处理是没有问题的。毕竟,时间是属于世界的。这个时间点,中国是早上,加拿大是黄昏——问题是Date对象不仅可以描述日期,还可以描述时间。自动按照UTC补上时间数据后,我们可能会得到意想不到的结果。带有时间部分的字符串那么,如果获取的表示时间的字符串带有时间呢?会不会更准确...试试吧://为了方便查看,评论中的结果数据使用了简洁的描述newDate("2021-11-17");//2021-11-1708:00+08:00newDate("2021-11-1700:00:00");//2021-11-1700:00+08:00newDate("2021-11-1709:00:00");//2021-11-1709:00+08:000注2号。按我们的常识,2021-11-1700:00:00和2021-11-17应该是同一时间吧?后者没有时间部分,因此它默认为一天的开始,即00:00:00——问题就在这里,Date对象默认为0:00UTC,而不是当地时间0:00。但是如果给定时间,Date会将其视为本地时间-不知何故存在时差。怎么不区分因为newDate()是按照本地时间来解析的,所以在不同地区的浏览器中,同一个日期时间字符串会被解析成不同的时间——你看,中国的早上9点肯定不一样加拿大的时间是早上9点,对吗?如果我们希望newDate()获得相同的时间怎么办?说起来很简单,只要得到一个包含时区信息的字符串即可,比如符合RFC3339标准的时间表示是2021-11-17T09:00:00+08:00。RFC3339这里就不细说了,简单理解就是日期部分是yyyy-MM-dd格式,时间部分是HH:mm:ss或者HH:mm:ss.sss格式,用T连接时区日期和时间之间的部分格式为Z或±HH:mm,其中Z表示无时差,即UTC时间。比如下面两个时间是同一时间点2021-11-17T09:00:00+08:002021-11-17T01:00:00Z幸运的是Date可以识别符合RFC3339标准的时间描述,所以使用上面两个例子每个字符串的创建时间都是一样的constd1=newDate("2021-11-17T09:00:00+08:00");constd2=newDate("2021-11-17T01:00:00Z");console.log(d1.getTime()===d2.getTime());还需要注意的是,原因已经解释清楚了,但是在实际操作中还是会出现一些奇怪的问题。造成这些问题的原因,归根结底还是没有注意“时区”。比如我问几个问题,看我能不能看懂?得到一个简单表示日期/时间的字符串,不符合RFC3339标准,比如前面提到的“2021-11-1709:00:00”。是UTC时间还是本地时间?如果是当地时间——是应用服务器的当地时间吗?还是数据库服务器的本地时间?还是用户输入时间的时区中的当地时间...?你看,一个简单的时区问题,不仅仅是前端单方面的问题,有可能是整个系统设计时忽略了时区概念导致的问题。如果在系统设计时考虑到时区问题,所有的存储和传输都使用同一时区的时间描述,事件处理起来就会容易很多。当然直接使用UTC时间,或者UnixTimeStamp之类的精确描述会更理想。可能有人会觉得浏览器确实只支持本地时间,但是我们可以使用Moment.js库、Day.js库、date-fns库……是的,可以使用各种工具,但是还是有必要的了解获得的时间描述是准确和明确的。同样,准确的时间描述包括:带有时间信息的字符串,例如符合RFC3339标准的字符串描述;基于特定时间的时间偏移值,单位为秒、毫秒或更精细的级别,例如UnixTimeStamp。我们的程序诞生在中国,却要面向世界——你考虑过时区吗?