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;

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

Java时区问题的更多相关文章

  1. java时区问题的一个坑

    事情是这样的,前台传过去一个日期字符串,就像2016/12/15 00:00,2016/12/15 23:59类似的格式,但每次从日志平台查日志查询的时间范围都不对,而是提前了一天. 原因是在java ...

  2. Java —— 时区(夏令时)问题

    有没有遇到过这样的情况:数据库里的是时间是“1991-4-14”,但是Java取出来后就成了“1991-4-13”. 解决方法一: 先把时区设成GMT,把 根据夏时制自动调节时钟 的选项去掉. 再把时 ...

  3. java 时区处理机制(0时区转换到服务器时区)

    package com.globalroam.util; import java.util.Calendar; import java.util.Date; import java.util.Time ...

  4. Java 时区之间时间转换

    SimpleDateFormat foo = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss"); System.out.println(&qu ...

  5. java时区转化相关工具方法

    import java.text.ParseException;import java.text.SimpleDateFormat;import java.util.Date;import java. ...

  6. 世界时区和Java时区详解

    0.引言 Druid中时区的问题一直困扰着我们,所以我专门去研究了一下世界时区和Java中的时区,对使用Druid很用帮助. 1.UTC时间&GMT时间 UTC时间是时间标准时间(Univer ...

  7. Java 时区转换(UTC+8 到 UTC 等等)

    前言:需要做时区转换,知道北京为UTC+8,东京为UTC+9,世界标准时间为UTC,所以下面的代码是只需要知道时区是+8还是+9还是0就可以了,不需要使用"CTT". " ...

  8. Java时区切换时的需要注意

    前言 Java中的时间操作,也许大家都很熟悉,Date.Calendar.SimpleDateFormat等.但或许我们都只是会调用常见接口方法.今天解决的bug,关于TimeZone,即时区. 经常 ...

  9. java时区问题设置,new Date()和系统时间相差8个小时

    出现这种问题有可能是服务时间没有修改. import java.text.DateFormat;import java.text.ParseException;import java.text.Sim ...

随机推荐

  1. 【网络流相关】最大流的Dinic算法实现

    Luogu P3376 于\(EK\)算法求最大流时每一次只求一条增广路,时间复杂度会比较高.尽管实际应用中表现比较优秀,但是有一些题目还是无法通过. 那么我们就会使用\(Dinic\)算法实现多路增 ...

  2. 深入理解 BigDecimal

    .katex { display: block; text-align: center; white-space: nowrap; } .katex-display > .katex > ...

  3. UIImageView与基本动画gif

    UIImageView 作用:[用来进行图片展示] UIImageView UIImageView初始化 initWithImage:如果设置frame,图片的size就是 imageView的siz ...

  4. Java学习笔记(面向对象下)

    面向对象(下) 类的继承 类的继承是指在一个现有类的基础上去构建一个新的类,构建出来的新类称为子类,现有类称为父类,子类会自动拥有父类所有可继承的属性和方法.(用extends关键字)   //定义A ...

  5. css3(2)

    旋转: 2D:transform: rotate()——进行旋转,括号内部写旋转角度,默认顺时针旋转.允许负值,元素将进行逆时针旋转, translate()——从当前位置进行移动,括号内为x,y值. ...

  6. js中 forEach 和 map 区别

    共同点: 1.都是循环遍历数组中的每一项. 2.forEach()和map()里面每一次执行匿名函数都支持3个参数:数组中的当前项item,当前项的索引index,原始数组input. 3.匿名函数中 ...

  7. Java读取Properties文件 Java加载配置Properties文件

    static{ Properties prop = new Properties(); prop.load(Thread.currentThread().getContextClassLoader() ...

  8. Redis面试热点工程架构篇之数据同步

    温馨提示 更佳阅读体验:[决战西二旗]|Redis面试热点之工程架构篇[2] 前言 前面用了3篇文章介绍了一些底层实现和工程架构相关的问题,鉴于Redis的热点问题还是比较多的,因此今天继续来看工程架 ...

  9. 建议3:正确处理Javascript特殊值---(1)正确使用NaN和Infinity

    NaN时IEEE 754中定义的一个特殊的数量值.他不表示一个数字,尽管下面的表达式返回的是true typeof(NaN) === 'number' //true 该值可能会在试图将非数字形式的字符 ...

  10. SpringBoot整合axis1.4后,@Autowired注入失败,使用工具类注入

    问题描述: 费劲心思搭建好webservices服务端后,没想到客户端调用失败,查看日志文件,发现报空指针异常,debug代码后,发现sql查询的值都是null.通常情况下,我们将Dao注入Servi ...