马上就要五一劳动节放假了,忙碌了半年,准备趁着假期出去放松放松,于是开始准备行程。女朋友听说日本5月份可以看樱花,于是她在看去日本的航班。我在旁边默默的看了下我的信用卡额度。
因为日本时间比中国时间早一个小时。日本的17:50相当于国内的16:50。飞机实际上只飞了3小时而已。
很久以前,在没有钟表的年代,人们通过观察太阳决定时间,一开始人们根据太阳挂在天空的位置来大致的确定时间,慢慢的人们根据太阳照射到的物体投下的影子来确定时间。
如古代人们使用的日晷,就是人类古代利用日影测得时刻的一种计时仪器。
第一是影子的长短在改变。早晨的影子最长,随着时间的推移,影子逐渐变短,一过中午它又重新变长;
第二是影子的方向在改变。在北回归线以北的地方,早晨的影子在西方,中午的影子在北方,傍晚的影子在东方。从原理上来说,根据影子的长度或方向都可以计时,但根据影子的方向来计时更方便一些。故通常都是以影子的方位计时。
随着时间的推移,晷针上的影子慢慢地由西向东移动。移动着的晷针影子好像是现代钟表的指针,晷面则是钟表的表面,以此来显示时刻。
但是,由于地球的自转,这就使得不同经度的地方的时间有所不同(地方时)。东边的地点比西边的地点先看到日出,东边地点的时刻较早,西边地点的时刻较晚。
世界各个国家位于地球不同位置上,因此不同国家,特别是东西跨度大的国家日出、日落时间必定有所偏差。这些偏差就是所谓的时差。
为了照顾到各地区的使用方便,又使其他地方的人容易将本地的时间换算到别的地方时间上去,1863年,人们首次提出了时区的概念。
有关国际会议决定将地球表面按经线从东到西,划成一个个区域,并且规定相邻区域的时间相差1小时。
就像我们如果去日本旅游,我们的手表时间显示的是中国时间,为了适应当地的时间,就需要将其校正一个小时。
现今全球共分为24个时区。
我们说中国在时区上是东八区,一般用GMT+8来表示,日本是东九区,一般用GMT+9来表示。
其实就是说中国时间是在GMT时间的基础上加8个小时,而日本时间是在GMT时间的基础上加9个小时。所以日本时间会比中国时间快一个小时。
那么到底什么是GMT呢?
GMT是Greenwich Mean Time的缩写,即格林威治时间(格林尼治平时),是指位于英国伦敦郊区的皇家格林尼治天文台当地的平太阳时,因为本初子午线被定义为通过那里的经线。
自1924年2月5日开始,格林尼治天文台负责每隔一小时向全世界发放调时信息。国际天文学联合会于1928年决定,将由格林威治平子夜起算的平太阳时作为世界时,也就是通常所说的格林威治时间。
理论时区与法定时区
理论时区以被15整除的子午线为中心,向东西两侧延伸7.5度,即每15°划分一个时区,这是理论时区。
但是,各个国家和地区具体采用哪个时区其实是自己可以决定的,理论时区只是建议性的。为了避开国界线,有的时区的形状并不规则,而且比较大的国家以国家内部行政分界线为时区界线,这是实际时区,即法定时区。
例如,中国幅员宽广,在理论时区上,差不多跨5个时区,包括东五区、东六区、东七区、东八区以及东九区。如果严格按照地理划分的话,那么乌鲁木齐的时间可能和黑龙江的时间相差四个小时。
好处自然不言而喻,大家统一使用同一个时间,就是比较方便。缺点也比较明显,就是同样是早上四点,有的地区天已经亮了,但是有些地方还是黑的。
虽然本文介绍的中国和日本这两个国家都是使用唯一法定时区的。但是,还是有很多国家并不是使用统一的时区的。
如美国各州的时区,基本上按地理位置,也就是经度区分的,也许美国是执行的最标准者之一。
Java中使用TimeZone 表示时区偏移量。TimeZone对象给我们的是原始的偏移量,也就是与GMT相差的微秒数,即TimeZone表示时区偏移量,本质上以毫秒数保存与GMT的差值。
获取TimeZone可以通过时区ID,如"America/New_York",也可以通过GMT+/-hh:mm来设定。例如北京时间可以表示为GMT+8:00。
当我们想要输出美国洛杉矶时间时,可以选择这种方式:
TimeZone.setDefault(TimeZone.getTimeZone("America/Los_Angeles"));
Date date = new Date();
System.out.println(date);
复制代码
需要注意的是,以下代码是无法获得美国洛杉矶时间的:
System.out.println(Calendar.getInstance(TimeZone.getTimeZone("America/Los_Angeles")).getTime());
复制代码
因为当我们使用System.out.println来输出一个时间的时候,他会调用Date类的toString方法,而该方法会读取操作系统的默认时区来进行时间的转换。只有修改了默认时区才会显示该时区的时间。
但是,通过阅读Calendar的源码,我们可以发现,getInstance方法虽然有一个参数可以传入时区,但是并没有将默认时区设置成传入的时区。
而在Calendar.getInstance.getTime后得到的时间只是一个时间戳,其中未保留任何和时区有关的信息,所以,在输出时,还是显示的是当前系统默认时区的时间。
Java8提供了一套新的时间处理API,这套API比以前的时间处理API要友好的多。
Java8 中加入了对时区的支持,带时区的时间为分别为:ZonedDate、ZonedTime、ZonedDateTime。其中每个时区都对应着 ID,地区ID都为 “{区域}/{城市}”的格式,如Asia/Shanghai、America/Los_Angeles等。
在Java8中,直接使用以下代码即可输出美国洛杉矶的时间:
LocalDateTime now = LocalDateTime.now(ZoneId.of("America/Los_Angeles"));
System.out.println(now);
复制代码