时区是怎么划分的

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了时区是怎么划分的相关的知识,希望对你有一定的参考价值。

1884年在华盛顿召开的一次国际经度会议(又称国际子午线会议)上,规定将全球划分为24个时区。它们是中时区(零时区)、东1-12区,西1-12区。每个时区横跨经度15度,时间正好是1小时。最后的东、西第12区各跨经度7.5度,以东、西经180度为界。
中时区 7.5°W~7.5°E 时区中心线 0°    东一区 7.5°E~22.5°E 时区中心线 15°E   
东二区 22.5°E~37.5°E 时区中心线 30°E    东三区 37.5°E~52.5°E 时区中心线45°E   
东四区 52.5°E~67.5°E 时区中心线60°E    东五区 67.5°E~82.5°E 时区中心线75°E   
东六区 82.5°E~97.5°E 时区中心线90°E    东七区 97.5°E~112.5°E 时区中心线105°E  东八区 112.5°E~127.5°E 时区中心线120°E   东九区 127.5°E~142.5°E 时区中心线135°E 东十区 142.5°E~157.5°E 时区中心线150°E   东十一区157.5°E~172.5°E 时区中心线165°E 东西十二区172.5°E~180°~172.5°W 时区中心线180°  
西十一区172.5°W~157.5°W 时区中心线165°W 西十区 157.5°W~142.5°W 时区中心线150°W 西九区142.5°W~127.5°W 时区中心线135°W  西八区 127.5°W~112.5°W 时区中心线120°W 西七区 112.5°W~97.5°W 时区中心线105°W  西六区 97.5°W~82.5°W 时区中心线 90°W  西五区 82.5°W~67.5°W 时区中心线 75°W   西四区 67.5°W~52.5°W 时区中心线60°W  西三区 52.5°W~37.5°W 时区中心线45°W   西二区 37.5°W~22.5°W 时区中心线30°W  西一区 22.5°W~7.5°W 时区中心线 15°W
参考技术A 是按经度划分 的,地球共有360个经度(东经180、西经180),每15度为一个时区,也就是一小时。0度经线为0点,(英国的格林尼治),依次类推。

Java获取当前时区时间LocalDateTime与System.currentTimeMillis

Java获取当前时区时间


全球根据纬度不同,划分不同的时区。对于此时此刻,大家同处同一个时间点,但是,每个时区的时间表示是不同的。Java可以使用 System.currentTimeMillisLocalDateTime相关代码获取当前时区时间。

System.currentTimeMillis

  • 获取当前毫秒数,与时区无关,我们Java的new Date()方法,也是通过它创建当前时间实例。
  • 获得的是自1970-01-01 00:00:00.000到当前时刻的时间距离,类型为long
  • 获取的毫秒数是系统当前时区的1970-01-01 00:00:00.000以来的毫秒数,如果使用的是linux系统默认时区(0),则对于我国的+8时区刚好差8小时毫秒数
import java.time.Instant;
import java.time.LocalDateTime;
import java.time.ZoneOffset;
import java.util.Calendar;
import java.util.TimeZone;

public class Test2 

    public static void main(String[] args) 
        String os = System.getProperty("os.name");
        TimeZone zone = TimeZone.getDefault();
        System.out.println("zone = " + zone.getID() + ", os = " + os);
		
		long time1 = System.currentTimeMillis();
		
        LocalDateTime local = LocalDateTime.now();
		long time2 = local.toInstant(ZoneOffset.UTC).toEpochMilli();
		
		TimeZone.setDefault(TimeZone.getTimeZone("UTC"));
		Calendar calendar = Calendar.getInstance(TimeZone.getTimeZone("UTC"));
		long time3 = calendar.getTime().getTime() + 8 * 60 * 60 * 1000;	
        
		System.out.println("time1 = " + time1);
		System.out.println("time2 = " + time2);
		System.out.println("time3 = " + time3);
    

运行结果

zone = Asia/Shanghai, os = Windows 10
time1 = 1662279837186
time2 = 1662308637222
time3 = 1662308637235

LocalDateTime

  • LocalDateTime 本身不包含时区信息,它存储了年、月、日、小时、分钟、秒和纳秒等数字。
  • LocalDateTime 默认只是存储当前系统所在时区当前时刻的年月日时分秒的数字
  • LocalDateTime.now 可以在传递参数时指定时区
  • toInstant()可以指定时区生成毫秒数(这里指定国际时间 UTC 0,实际上就是 System.currentTimeMillis() + 时区偏移毫秒数)
import java.time.Instant;
import java.time.LocalDateTime;
import java.time.ZoneOffset;
import java.util.Calendar;
import java.util.TimeZone;


public class Test3 

    public static void main(String[] args) 
		
		
        String os = System.getProperty("os.name");
        TimeZone zone = TimeZone.getDefault();
        System.out.println("zone = " + zone.getID() + ", os = " + os);
		
		long time1 = System.currentTimeMillis();
		
		// LocalDateTime itself does not contain time zone information, it stores numbers such as year, month, day, hour, minute, second, and nanosecond.
        LocalDateTime local = LocalDateTime.now();
		System.out.println("local = " + local);
		long time2 = local.toInstant(ZoneOffset.UTC).toEpochMilli();
		
		// LocalDateTime.now can specify the time zone when passing the parameter
		LocalDateTime dtUtc = LocalDateTime.now(ZoneOffset.UTC);	
		System.out.println("dtUtc = " + dtUtc);
        long time3 = dtUtc.toInstant(ZoneOffset.UTC).toEpochMilli();

		Calendar calendar = Calendar.getInstance(TimeZone.getTimeZone("UTC"));
		long time4 = calendar.getTime().getTime() ;//+ 8 * 60 * 60 * 1000;	
        
		System.out.println("time1 = " + time1);
		System.out.println("time2 = " + time2);
		System.out.println("time3 = " + time3);
		System.out.println("time4 = " + time3);
    

运行结果

zone = Asia/Shanghai, os = Windows 10
local = 2022-09-04T16:25:27.030469500
dtUtc = 2022-09-04T08:25:27.031493500
time1 = 1662279926996
time2 = 1662308727030
time3 = 1662279927031
time4 = 1662279927031

最终结果

  • 其实只要服务器设置的时区是正确的,无论LocalDateTime.now()还是System.currentTimeMillis()都是正确的,都没有问题
  • 如果时区不正确,就要考虑针对时区处理下8小时毫秒数差距
  • 下面使用LocalDateTime.now().toInstant(ZoneOffset.UTC).toEpochMilli()获取当前毫秒数,再获取系统时区,判断是否为Asia/Shanghai,若不是(linux默认0时区),则加8小时毫秒数(8 * 60 * 60 * 1000
                // LocalDateTime 本身不包含时区信息(只是当前系统所在时区当前时刻的年月日时分秒)
                // toInstant可以指定时区生成毫秒数(这里指定国际时间 UTC 0,实际上就是 System.currentTimeMillis() + 时区偏移毫秒数)
                long time = LocalDateTime.now().toInstant(ZoneOffset.UTC).toEpochMilli();

                TimeZone zone = TimeZone.getDefault();
                // 东八区为北京/上海时间,国内一般使用 UTC +8(但是linux服务器、docker初始都是 UTC 0)
                if (!"Asia/Shanghai".equals(zone.getID())) 
                    time += 8 * 60 * 60 * 1000;
                
                System.out.println("当前zone为:" + zone + ", 当前时间为:" + time);

以上是关于时区是怎么划分的的主要内容,如果未能解决你的问题,请参考以下文章

世界时区

每个时区相差几小时?

GPS通讯 数据包解析

软件在时间段上称东1-8 西1-8区等是啥意思?

[转] GMTUTC与24时区 等时间概念

Oracle 时区