JVM默认时区为:Asia/Shanghai与java程序中GMT+08不一致异常

 更新时间:2022年10月31日 10:27:36   作者:ACoderForever  
这篇文章主要介绍了JVM默认时区为:Asia/Shanghai与java程序中GMT+08不一致异常问题,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教

在Spring程序中配置了spring.jackson.time-zone=GMT+08时,部分时间相差一个小时问题,且是固定的时间出现了固定的时差问题。

经过排查,发现是JVM的默认时区为

Asia/Shanghai,两者不一致,然后Asia/Shanghai 这个时区并不一定与GMT+08这个时区相等,他们是2种定义标准。

Asia/Shanghai 这个代表的是中国的时区,但在历史中,有国家(包含中国)政策颁布了在1986-1991年等还存在夏令时。

在这样的时间区间,夏季时,会将时间拨快1个小时(即东9区时间),夏季结束时会再次将时间拨回一个小时(即东8区时间)。

所以要保证程序显示的时间没有问题,需要将JVM和spring.jackson.time-zone设置的时区保持一致即可解决问题

JVM中设置为

Asia/Shanghai,经代码调试出现的底层时区调整的测试案例。

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

/**
 * @author Ashen
 * @date 16/07/2019
 */
public class Test {

	public static SimpleDateFormat sdf = new SimpleDateFormat("yyyy.MM.dd HH:mm:ss");

	static int[] offsets = {
			28800000,
			29143000,
			32400000,
			3600000
	};
	public static void main(String[] args) {
		test2();
	}

	public static void test1(){
		Date date0 = new Date(1986 - 1900, 07 - 1, 29);
		Date date1 = new Date(1980 - 1900, 07 - 1, 29);
		Date date2 = new Date(1988 - 1900, 07 - 1, 29);
	}

	public static void test2() {
		// 以下为JVM中时区为:Asia/Shanghai时的偏移量参数值(共9对,分别为9年夏令时的开启与结束点)
		long transitions[] = {
				-9048018124799999L,
				-8918966038528000L,
				-3823593062399950L,
				-3781140480000000L,
				-3722379263999950L,
				-3651969024000000L,
				2111569920000050L,
				2158623129600000L,
				2232955699200050L,
				2287440691200000L,
				2361773260800050L,
				2416258252800000L,
				2493068083200050L,
				2547553075200000L,
				2621885644800050L,
				2676370636800000L,
				2750703206400050L,
				2805188198400000L,
				8660385792000000L
		};
		for(int i=0;i<18;i++){
			Long longTime = transitions[i] >> 12;
			Long field2 = transitions[i] << 52 >> 60;
			Long field3 = transitions[i] << 56 >> 60;
			Long field4 = transitions[i] << 60 >> 60;
			Date date = new Date(longTime);
			System.out.println("时间"+getIndexStr(i)+": "+sdf.format(date)+" 保留值>>"+field2+" 日光节约量 >> "+getOffset(field3)+" GMT偏移量 >> "+getOffset(field4));
		}

	}

	public static String getIndexStr(int i){
		if(i<10) return "0"+i;
		else return String.valueOf(i);
	}

	public static String getOffset(long offset){
		return offsets[(int)offset]/(1000 *60* 60)+"小时,";
	}

}

下面为运行结果:清晰的看到Asia/Shanghai 时区的调整时间点与调整量。

transitions[] 中的值来源于DEBUG程序时复制jvm中的数据。

以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。

相关文章

  • Java源码解析之详解ReentrantLock

    Java源码解析之详解ReentrantLock

    今天给大家带来的是关于Java并发的相关知识,文章围绕着ReentrantLock源码展开,文中有非常详细的介绍及代码示例,需要的朋友可以参考下
    2021-06-06
  • Java学习基础之安装JDK/配置JDK环境&IEDA工具安装

    Java学习基础之安装JDK/配置JDK环境&IEDA工具安装

    这篇文章主要介绍了Java学习基础系列文章的第一篇,主要内容是安装JDK/配置JDK环境&IEDA工具安装的相关资料,需要的朋友可以参考下
    2020-02-02
  • 详解java中的Collections类

    详解java中的Collections类

    这篇文章主要为大家详细介绍了java中的Collections类,感兴趣的小伙伴们可以参考一下
    2016-07-07
  • Spring Boot实现qq邮箱验证码注册和登录验证功能

    Spring Boot实现qq邮箱验证码注册和登录验证功能

    这篇文章主要给大家介绍了关于Spring Boot实现qq邮箱验证码注册和登录验证功能的相关资料,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2020-12-12
  • SpringBoot 整合RabbitMq 自定义消息监听容器来实现消息批量处理

    SpringBoot 整合RabbitMq 自定义消息监听容器来实现消息批量处理

    Spring Boot中提供了默认的监听器容器,但是有时候我们需要自定义监听器容器,来满足一些特殊的需求,比如批量获取数据,这篇文章主要介绍了SpringBoot 整合RabbitMq 自定义消息监听容器来实现消息批量处理,需要的朋友可以参考下
    2023-04-04
  • SpringBoot中的内容协商器图解

    SpringBoot中的内容协商器图解

    本文通过图文解说加代码的形式给大家介绍了SpringBoot中的内容协商器知识,需要的朋友参考下吧
    2017-11-11
  • Java 实现多线程切换等待唤醒交替打印奇偶数

    Java 实现多线程切换等待唤醒交替打印奇偶数

    这篇文章主要介绍了Java 实现多线程切换等待唤醒交替打印奇偶数 ,本文通过实例代码给大家介绍的非常详细,具有一定的参考借鉴价值,需要的朋友可以参考下
    2019-05-05
  • SpringBoot的@GetMapping路径匹配规则、国际化详细教程

    SpringBoot的@GetMapping路径匹配规则、国际化详细教程

    这篇文章主要介绍了SpringBoot的@GetMapping路径匹配规则、国际化,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友参考下吧
    2023-11-11
  • Java线程的基本概念

    Java线程的基本概念

    本文主要介绍了Java线程的基本概念。具有很好的参考价值,下面跟着小编一起来看下吧
    2017-02-02
  • Java设计模式之原型设计示例详解

    Java设计模式之原型设计示例详解

    这篇文章主要为大家详细介绍了Java的原型设计模式,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下,希望能够给你带来帮助
    2022-03-03

最新评论