大厂日期时间处理最佳实践(下)

本文涉及的产品
云解析 DNS,旗舰版 1个月
公共DNS(含HTTPDNS解析),每月1000万次HTTP解析
全局流量管理 GTM,标准版 1个月
简介: 大厂日期时间处理最佳实践

3 时区问题

全球有24个时区,同一个时刻不同时区(比如中国上海和美国纽约)的时间不同。全球化项目,若初始化时间时未提供时区,那就不是真正意义上的时间,只能认为是我看到的当前时间的一个表示。

3.1 Date类

  • Date无时区概念,任一机器使用new Date()初始化得到时间相同。因为,Date中保存的是UTC时间,其为以原子钟为基础的统一时间,不以太阳参照计时,无时区划分
  • Date中保存的是一个时间戳,代表从1970年1月1日0点(Epoch时间)到现在的毫秒数。尝试输出Date(0):
System.out.println(new Date(0));
System.out.println(TimeZone.getDefault().getID() + ":" +
  TimeZone.getDefault().getRawOffset()/3600000);

得到1970年1月1日8点。我的机器在中国上海,相比UTC时差+8小时:

Thu Jan 01 08:00:00 CST 1970
Asia/Shanghai:8

对于国际化项目,处理好时间和时区问题首先就是要正确保存日期时间。

这里有两种

3.2 如何正确保存日期时间

  • 保存UTC
    保存的时间无时区属性,不涉及时区时间差问题的世界统一时间。常说的时间戳或Java中的Date类就是这种方式,也是推荐方案

保存字面量

比如年/月/日 时:分:秒,务必同时保存时区信息。有了时区,才能知道该字面量时间真正的时间点,否则它只是一个给人看的时间表示且只在当前时区有意义。

而Calendar才具有时区概念,所以通过使用不同时区初始化Calendar,才能得到不同时间。

正确地保存日期时间后,就是正确展示,即要使用正确时区,将时间点展示为符合当前时区的时间表示。至此也就能理解为何会发生“时间错乱”。

从字面量解析成时间 & 从时间格式化为字面量

对同一时间表示,不同时区转换成Date会得到不同时间戳

  • 比如2020-11-11 11:11:11
  • image.png
  • 对当前上海时区/纽约时区,转化为UTC时间戳不同
Wed Nov 11 11:11:11 CST 2020:1605064271000
Thu Nov 12 00:11:11 CST 2020:1605111071000

这就是UTC的意义,并非时间错乱。对同一本地时间的表示,不同时区的人解析得到的UTC时间必定不同,反过来不同本地时间可能对应同一UTC。

格式化后出现的错乱

即同一Date,在不同时区下格式化得到不同时间表示。

  • 在当前时区和纽约时区格式化2020-11-11 11:11:11
  • image.png
  • 输出如下,当前时区Offset(时差)是+8小时,对于-5小时的纽约
  • image.png
  • 因此,有时数据库中相同时间,由于服务器时区设置不同,读取到的时间表示不同。这不是时间错乱,而是时区作用,因为UTC时间需根据当前时区解析为正确的本地时间。


所以要正确处理时区,在于存和读两阶段


存,需使用正确的当前时区来保存,这样UTC时间才会正确

读,也须正确设置本地时区,才能把UTC时间转换为正确当地时间

Java8处理时区问题

时间日期类ZoneId、ZoneOffset、LocalDateTime、ZonedDateTime和DateTimeFormatter,使用起来更简单清晰。

初始化上海、纽约和东京三时区

可使用ZoneId.of初始化一个标准时区,也可使用ZoneOffset.ofHours通过一个offset初始化一个具有指定时间差的自定义时区。

日期时间表示

  • LocalDateTime无时区属性,所以命名为本地时区的日期时间
  • ZonedDateTime=LocalDateTime+ZoneId,带时区属性

因此,LocalDateTime仅是一个时间表示,ZonedDateTime才是一个有效时间。这里将把2020-01-02 22:00:00这个时间表示,使用东京时区解析得到一个ZonedDateTime。


DateTimeFormatter格式化时间

可直接通过withZone直接设置格式化使用的时区。最后,分别以上海、纽约和东京三个时区来格式化这个时间输出:

image.png

日志输出:

  • 相同时区,经过解析存和读的时间表示一样(比如最后一行)
  • 不同时区,比如上海/纽约,输出本地时间不同。
    +9小时时区的晚上10点,对上海时区+8小时,所以上海本地时间为早10点
    而纽约时区-5小时,差14小时,为晚上9点
  • image.png

小结

要正确处理国际化时间问题,推荐Java8的日期时间类,即

  1. 使用ZonedDateTime保存时间
  2. 然后使用设置了ZoneIdDateTimeFormatter配合ZonedDateTime进行时间格式化得到本地时间表示
目录
相关文章
|
4月前
|
分布式计算 DataWorks 大数据
MaxCompute产品使用问题之月和日是1位数的日期格式如何转化成标准日期值
MaxCompute作为一款全面的大数据处理平台,广泛应用于各类大数据分析、数据挖掘、BI及机器学习场景。掌握其核心功能、熟练操作流程、遵循最佳实践,可以帮助用户高效、安全地管理和利用海量数据。以下是一个关于MaxCompute产品使用的合集,涵盖了其核心功能、应用场景、操作流程以及最佳实践等内容。
|
3月前
|
数据库
uniapp 【专题详解 -- 时间】云数据库时间类型设计,时间生成、时间格式化渲染(uni-dateformat 组件的使用)
uniapp 【专题详解 -- 时间】云数据库时间类型设计,时间生成、时间格式化渲染(uni-dateformat 组件的使用)
124 0
|
4月前
|
SQL 数据采集 DataWorks
DataWorks产品使用合集之如何处理时间格式中含有空格的日期和时间字段,并将其拼接成一个完整的字符串
DataWorks作为一站式的数据开发与治理平台,提供了从数据采集、清洗、开发、调度、服务化、质量监控到安全管理的全套解决方案,帮助企业构建高效、规范、安全的大数据处理体系。以下是对DataWorks产品使用合集的概述,涵盖数据处理的各个环节。
24 0
|
5月前
|
C++
C++ Qt开发:DateTime日期时间组件
Qt 是一个跨平台C++图形界面开发库,利用Qt可以快速开发跨平台窗体应用程序,在Qt中我们可以通过拖拽的方式将不同组件放到指定的位置,实现图形化开发极大的方便了开发效率,本章将重点介绍`QDateTime`日期与时间组件的常用方法及灵活运用。在Qt中,日期和时间的处理通常使用 `QDateTime` 类。`QDateTime` 是一个用于表示日期和时间的类,而与之相关的组件还包括 `QDate` 、 `QTime`以及`QDateTime`,以下是对这些组件的详细概述。
117 0
|
12月前
|
前端开发 定位技术
前端将UTC时间格式转化为本地时间格式~~uniapp写法
前端将UTC时间格式转化为本地时间格式~~uniapp写法
110 0
|
存储 Java 程序员
实战:求年月日时间前后遇到的坑和解决方式
这周接到一个时间转换任务需要处理,本来没什么问题,后来完成后发现时间有偏差,又重写了一遍代码,感觉很有记录必要性,希望看过的小伙伴可以避坑。
实战:求年月日时间前后遇到的坑和解决方式
|
JavaScript 前端开发
如何利用JS获取当前具体日期时间与获取前一天日期时间
在项目中获取当前时间是从后台处理来进行获取的,然后通过ajax请求接口,返回给前端,我也不知道为什么要这么进行,不知道谁写的,暂时先放着吧,供大家观看,后面我会贴出来js获取当前时间的方法。
473 0
|
关系型数据库 MySQL
开发指南—数据类型—日期和时间类型
本文介绍了PolarDB-X支持的日期时间类型。
|
5月前
|
前端开发 Java Maven
springboot优雅的实现excel的导出(自适应列宽实现,中文也行),复制可用
springboot优雅的实现excel的导出(自适应列宽实现,中文也行),复制可用
214 0
|
机器学习/深度学习
开发指南—函数—日期时间函数
本文介绍了PolarDB-X支持的日期时间函数