为什么 Java 开发中时区设定用 Asia/Shanghai 而不是 GMT+8(防止踩雷)

在全球化的背景下,时区管理对于开发人员来说是个重要但复杂的问题。虽然中国的标准时间是 UTC+8,但在实际开发中,特别是 Java 开发中,我们应尽量使用时区数据库中的区域/位置形式(例如 Asia/Shanghai),而不是简单的偏移量形式(例如 GMT+8)。这篇博文将通过具体的例子和分析,探讨为什么在 Java 开发中推荐使用 Asia/Shanghai 作为时区设定。

时区基础

全球共分为24个时区,但为了行政方便,许多国家或地区会统一使用一个标准时间。例如,中国地跨五个时区,但全国统一使用北京时间(UTC+8)。时区可以用名称(如东八区、西五区)、偏移量(如 UTC+8、UTC-5)、缩写(如 CST、PST),或时区数据库中的区域/位置(如 Asia/ShanghaiAmerica/Chicago)来表示。

缩写时区具有不唯一性,容易引起混淆。例如,CST 可以表示 China Standard Time(UTC+8)或 Central Standard Time(UTC-6)。因此,通常不推荐使用缩写形式设定时区。

Java 中的 UTC 和 GMT

在 Java 中,时区设定有多种方式。通过以下例子,我们可以看到 Java 中 UTC 和 GMT 的具体使用区别:

jshell> Date now = new Date()
now ==> Thu Oct 30 16:59:27 CST 2021jshell> import java.text.*
jshell> DateFormat df = DateFormat.getInstance()jshell> df.setTimeZone(TimeZone.getTimeZone("GMT+8"))
jshell> df.format(now)
$5 ==> "2021/10/30 下午4:59"jshell> df.setTimeZone(TimeZone.getTimeZone("UTC+8"))
jshell> df.format(now)
$7 ==> "2021/10/30 上午8:59"jshell> df.setTimeZone(TimeZone.getTimeZone("UTC"))
jshell> df.format(now)
$9 ==> "2021/10/30 上午8:59"jshell> df.setTimeZone(TimeZone.getTimeZone("GMT"))
jshell> df.format(now)
$11 ==> "2021/10/30 上午8:59"jshell> df.setTimeZone(TimeZone.getTimeZone("abc"))
jshell> df.format(now)
$13 ==> "2021/10/30 上午8:59"

从上述输出可以看出,在当前 Java 版本中,设定时区偏移量时,不能使用 UTC,只能使用 GMT。另外,使用非法的时区 ID 时,会将时区设定为零时区。

GMT+8 和 Asia/Shanghai

下面我们来看一下 GMT+8Asia/Shanghai 的区别:

jshell> import java.text.*
jshell> SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss")
jshell> DateFormat df = DateFormat.getInstance()jshell> df.setTimeZone(TimeZone.getTimeZone("Asia/Shanghai"))
jshell> df.format(sdf.parse("2021-10-31 10:34:00"))
$6 ==> "2021/10/31 上午10:34"jshell> df.setTimeZone(TimeZone.getTimeZone("GMT+8"))
jshell> df.format(sdf.parse("2021-10-31 10:34:00"))
$8 ==> "2021/10/31 上午10:34"

这看起来似乎没有区别,但让我们继续测试另一个日期:

jshell> df.setTimeZone(TimeZone.getTimeZone("Asia/Shanghai"))
jshell> df.format(sdf.parse("1986-05-04 02:00:00"))
$10 ==> "1986/5/4 上午3:00"jshell> df.setTimeZone(TimeZone.getTimeZone("GMT+8"))
jshell> df.format(sdf.parse("1986-05-04 02:00:00"))
$12 ==> "1986/5/4 上午2:00"

我们发现,当使用 1986-05-04 02:00:00 这个时间戳时,GMT+8Asia/Shanghai 给出了不同的结果。原因在于中国在 1986 年至 1991 年间实行了夏令时(Daylight Saving Time, DST)。Asia/Shanghai 会考虑历史上实际发生的夏令时调整,而 GMT+8 只是一个简单的时区偏移,不考虑任何历史的时区变化。

夏令时的重要性

夏令时是一种为了节约能源,在夏季人为将时间调快一小时的制度。例如,中国在 1986 年至 1991 年也实行过夏令时。因此,使用 Asia/Shanghai 可以确保在处理历史数据时,时间计算是准确的,考虑了夏令时的影响。而使用 GMT+8 则无法正确反映这种历史上的时间调整。

结论

在 Java 开发中,为了确保时间计算的准确性和一致性,特别是在处理历史数据和跨时区操作时,应优先使用时区数据库中的区域/位置形式,例如 Asia/Shanghai,而不是简单的时区偏移形式如 GMT+8。这样可以确保程序正确处理所有时区规则,包括历史上的夏令时调整。

希望这篇博文能帮助开发者理解在 Java 中使用 Asia/Shanghai 作为时区设定的重要性,并在实际项目中应用这一最佳实践。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/bicheng/50432.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【View】Android 事件分发难道你还不会吗?

Android事件分发机制决定了触摸事件如何从顶层窗口传递到具体的视图。主要涉及到三个核心方法:dispatchTouchEvent(), onInterceptTouchEvent(), 和 onTouchEvent()。 1. dispatchTouchEvent() 这是事件分发的入口点。Activity, ViewGroup, 和 View 都重写了这个方…

UI界面卡顿检测工具--UIHaltDetector

引言: 在日常工作当中,我们经常会遇到软件的界面出现卡顿的问题,而为了确定卡顿原因,我特地写了一个UI界面卡顿的小工具:UIHaltDetector;该工具可以在检测到目标窗口出现卡顿的时候直接打印堆栈日志和输出…

iOS 获取mimetype

///根据地址 获取文件类型 (NSString *)mimeType:(NSURL *)url{NSURLRequest *request [NSURLRequest requestWithURL:url];NSURLResponse *response [[NSURLResponse alloc] init];[NSURLConnection sendSynchronousRequest:request returningResponse:&response error:…

各种聚类方法的聚类思想介绍及其优缺点

聚类是一种无监督学习方法,旨在将数据集中的样本划分为若干个组,使得同一组内的样本相似度最大,而不同组之间的样本相似度最小。以下是几种常见的聚类方法及其思想、优缺点的介绍: 1. K-means 聚类 聚类思想: K-mea…

MySQL SQL 编程练习

目录 创建表并插入数据 查看表结构 创建触发器 创建INSERT 触发器 创建DELETE 触发器 创建更新触发器 创建存储过程 创建提取emp_new表所有员工姓名和工资的存储过程s1 创建存储过程s2,实现输入员工姓名后返回员工的年龄 创建一个存储过程s3,有2个参数&…

spring-from表单

在spring boot当中,from表单怎样开发(name=value) 先列出接口所需信息(抓包得到请求信息),将这些必要信息以注解的方式表达出来 步骤: 梳理前置条件(请求地址,请求header,请求方法,请求数据,响应结果)编辑一个普通类,在类上标记注解@Controller: 标记在类上,让类…

springboot校园商店配送系统-计算机毕业设计源68448

摘要 本文详细阐述了基于Spring Boot框架的校园商店配送系统的设计与实现过程。该系统针对校园内的用户需求,整合了用户注册与登录、商品浏览与购买、订单管理、配送追踪、用户反馈收集以及后台管理等功能,为校园内的普通用户、商家、配送员和管理员提供…

深入理解 SQL 中的 DATEDIFF 函数

DATEDIFF 是 SQL 中的一个常用函数,用于计算两个日期之间的天数差异。它非常有用,特别是在需要根据日期进行条件筛选或计算时间间隔的场景中。以下是对 DATEDIFF 函数的详细介绍,包括其语法和实用例子。 1. DATEDIFF 函数概述 DATEDIFF 函数…

算法与算法分析

目录 一.前言 二.算法的特性和要求 三.分析算法--时间效率 四. 分析算法--空间效率 一.前言 算法就是对特定问题求解方法和步骤的一种描述,它是指令的有限序列。其中,每个指令表示一个或多个操作。总而言之,我们数据结构就是通过算法实现操…

学习SQL如何使用CASE语句查询分析设备状态

学习SQL如何使用CASE语句查询分析设备状态 一、前言1. 问题背景2. SQL查询分析3. SQL查询解析 二、结论 一、前言 在实际应用中,经常需要对设备的状态进行监控和分析。通过SQL查询,我们可以有效地从数据库中提取和计算设备的状态信息。本文将介绍如何编…

FPGA实现LCD1602控制

目录 注意! 本工程采用野火征途PRO开发板,外接LCD1602部件进行测试。 有偿提供代码!!!可以定制功能!!! 联系方式见底部 一、基础知识 1.1 引脚信息 1.2 指令 1.2.1 清屏 1.…

【有效的括号】

有效的括号 一、题目二、思路三、代码 一、题目 二、思路 利用栈先进后出的特点存储左括号:后面遍历遇到的左括号要先闭合 用map存储左括号与右括号的对应关系,利用键值对快速查找右括号进行匹配 三、代码 使用.has()方法判断当前遍历的字符是否是右括…

项目架构知识点总结

项目架构知识点总结 【一】重要注解【1】SpringBootApplication(1)⭐️ComponentScan 注解(2)⭐️EnableAutoConfiguration 注解(3)⭐️SpringBootConfiguration 注解(4)Inherited 注…

vite+cesium+天地图

创建vite项目 直接在地址栏输入cmd进入命令行(vite项目默认为vue3) # yarn yarn create vite 项目名称 --template vue 创建成功后依次执行 yarn install yarn dev 安装cesium和vite-plugin-cesium 没有加版本号默认为最新版本 加版本号如cesium1.1…

vue3——两种利用自定义指令实现防止按钮重复点击的方法

方法一:利用定时器设置时间,下方代码设置时间为1秒 但是有个缺点:请求如果很慢,1秒钟还没有好,那么该方法就没用了 // 利用定时器:1秒之后才能再次点击app.directive(preventReClick, {mounted: (el, bind…

sql注入的专项练习 sqlilabs(含代码审计)

在做题之前先复习了数据库的增删改查,然后自己用本地的环境,在自己建的库里面进行了sql语句的测试,主要是回顾了一下sql注入联合注入查询的语句和sql注入的一般做题步骤。 1.获取当前数据库 2.获取数据库中的表 3.获取表中的字段名 一、sql…

WordPress 后台开发技巧:向文章发布页右侧添加自定义菜单项

案例图片 这个案例向你介绍了如何在文章发布页的右侧边栏增加一个新的自定义菜单项。具体用它实现什么功能,就看你的需要了。 代码 function add_custom_menu_item() { add_meta_box(custom_menu_item, 这里是菜单项名称, display_custom_menu_item, post, side, …

基于JSP、java、Tomcat、mysql三层交互的项目实战--校园交易网(1)-项目搭建(前期准备工作)

这是项目的初始页面 接下来我先写下我的初始项目搭建 技术支持:JAVA、JSP 服务器:TOMCAT 7.0.86 编程软件:IntelliJ IDEA 2021.1.3 x64 首先我们打开页面,准备搭建项目的初始准备 1.New Project 2.随后点击Next,勾…

C# Aspose PDF.dll 实现PDF添加水印

在C#中使用Aspose.PDF库来给PDF文档添加水印是一个常见的需求。Aspose.PDF是一个功能强大的库,它允许开发者在不需要Adobe Acrobat或其他PDF查看器的情况下创建、修改、渲染、打印和解析PDF文档。以下是一个使用Aspose.PDF库给PDF添加水印的基本示例: 首…

AttributeError: ‘list‘ object has no attribute ‘text‘

AttributeError: ‘list‘ object has no attribute ‘text‘ 目录 AttributeError: ‘list‘ object has no attribute ‘text‘ 【常见模块错误】 【解决方案】 示例代码 欢迎来到英杰社区https://bbs.csdn.net/topics/617804998 欢迎来到我的主页,我是博主英…