zoukankan      html  css  js  c++  java
  • Java时区问题

    Java时区相关

    时间格式

    UTC是以原子时计时,更加精准,适应现代社会的精确计时。不过一般使用不需要精确到秒时,视为等同。GMT是前世界标准时,UTC是现世界标准时。每年格林尼治天文台会发调时信息,基于UTC。
    GMT和 UTC可以视为几乎是等同的,UTC更精准,有闰秒的概念。

    //世界标准时间UTC,其中T表示时分秒的开始(或者日期与时间的间隔),Z表示这是一个世界标准时间
    String utcStr = "2010-10-12T15:24:22Z";
    //本地时间,也叫不含时区信息的时间,末尾没有Z
    String localStr = "2010-10-12T15:24:22";
    //含有时区的时间,+08:00表示该时间是由世界标准时间加了8个小时得到的,[Asia/Shanghai]表示时区 
    String zoneStr = "2017-12-13T09:47:07.153+08:00[Asia/Shanghai]";
    

    表示时间相关的类

    表示时间的类主要有个:String、Instant、LocalDateTime、ZonedDateTime,
    String是字符串形式的时间,Instant是时间戳,LocalDateTime是不含时区信息的时间,ZonedDateTime是含有时区信息的时间。

    LocalDateTime

    符合格式的String 可以直接转换为LocalDateTime

    System.out.println(LocalDateTime.parse("2019-12-15 10:10:10", DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
    

    LocalDateTime字面意思是本地时间,实际上它可以理解为不含时区信息的时间,只储存了年月日时分秒,要表达是哪里的时间需要时区解释。

    Instant与ZonedDateTime

    Instant是时间戳,是指世界标准时格林威治时间1970年01月01日00时00分00秒(北京时间1970年01月01日08时00分00秒)起至现在的总秒数,Instant本身已经携带了时区信息,默认是0时区。
    ZonedDateTime是含有时区信息的时间,可以理解为它是Instant的格式化对象,
    JDK 8以前的时区是用TimeZone,TimeZone ID是在java里ZoneInfoFile类加载的。在jvm初始化的时候,会读取jdk安装目录下的 ${ java.home } /jre/lib/tzdb.dat,放到其成员变量为zones的ConcurrentHashMap里。当调用TimeZone.getTimeZone(id)方法时,会用id到这个map里进行匹配获取到指定id的时区。其中TimeZone.getTimeZone("Asia/Shanghai")和TimeZone.getTimeZone("GMT+8")是相同的,可以相互替换使用。

    System.out.println(ZonedDateTime.ofInstant(Instant.now(),ZoneId.systemDefault()).toInstant());
    System.out.println(ZonedDateTime.ofInstant(Instant.now(),"Australia/Darwin").toInstant());
    

    相同的Instant,在不同的时区有不同的展示时间,所以在用Instant构造ZonedDateTime的时候需要传入时区;ZonedDateTime可以直接转化为Instant,并且不同的ZonedDateTime可能会生成同样的Instant

    时区转换

    用户输入的String类型的时间是没有时区信息的,需要人为指定时区再解析。
    解析的步骤分2步: 先确定用户时区
    1.把用户输入的时间转化为世界标准时间;//Instant.parse("2010-10-12T15:24:22Z")
    2.再把世界标准时间转为需要的时区的时间。//ZonedDateTime.ofInstant(instant,ZoneId.systemDefault());

    不同地区的服务器统一时间的解决方案

    首先后端封装一个接口后获取服务器相对GMT(格林尼治标准时间)时间的偏移量:

    TimeZone zone = TimeZone.getDefault(); 
    System.out.println(zone.getRawOffset()); 
    

    这段代码放在不同时区的服务器上执行结果会不同(前提是服务器的时区设置跟本地时区一致)。如果在泰国执行结果为25200000ms,换算成小时为7,说明泰国的时区的偏移量相对于GMT标准时间相差7小时。下文简称“时区偏移量”。

    前端首先调用该接口获取服务器的时区偏移量,再在浏览器上获取本地的时区偏移量,计算出两个偏移量的差值。本地浏览器上获取当前的时间戳,减去上一步计算出来的差值即可得到服务器这个时间的时间戳,把这个时间戳传给后端 再转换成时间,就是服务器对应的时间,存入数据库即可。
    前端:

    //服务的时区偏移量,通过接口获得,注意换成负值 
    var serveroffset=-25200000; 
    var d = new Date(); 
    //获取本地浏览器的时区偏移量 
    var localOffset = d.getTimezoneOffset() * 60000; 
    //的到本地和偏移量的差值 
    var deffoffset=localOffset-(serveroffset); 
    //获取本地浏览器时间戳 
    var localTime = d.getTime(); 
    //计算出传到服务器的时间戳 
    var servertime=localTime+deffoffset; 
    

    通过上述方式,可以实现服务器全球各地部署,系统都可以正常使用。

  • 相关阅读:
    Python中__new__()方法的使用和实例化
    python __str__ , __repr__区别
    python中%r和%s的区别
    面向对象进阶
    getattr(sys.modules[__name__], func_name)
    os.path.dirname(__file__)使用
    bound和unbound方法,类的绑定和非绑定是什么
    基于python中staticmethod和classmethod的区别(详解)
    python基础----特性(property)、静态方法(staticmethod)、类方法(classmethod)、__str__的用法
    python @classmethod 的使用场合
  • 原文地址:https://www.cnblogs.com/scholar-hwg/p/12059895.html
Copyright © 2011-2022 走看看