客户端、服务器、数据库之间的时区转换

简介: 做国外的项目经常会遇到时区转换的问题,这里简单针对遇到的时区问题做个记录,也希望对大家有所帮助,少走弯路。(本文设计开发语言为java)

背景


做国外的项目经常会遇到时区转换的问题,这里简单针对遇到的时区问题做个记录,也希望对大家有所帮助,少走弯路。(本文设计开发语言为java)


时区的概念


先说下时区的概念 初中地理好的同学应该还记得,由于地球不停地自西向东旋转,使得昼夜半球和晨昏线也不断自东向西移动。


image.gif


为了照顾到各地区的使用方便,又使其他地方的人容易将本地的时间换算到别的地方时间上去。有关国际会议决定将地球表面按经线从东到西,划成一个个区域(时区),全球一共分为24个时区(东12区+西12区),相邻时区时间相差1个小时。


规定英国(格林尼治天文台旧址)所在区域为零时区,往东分别为东1区、东2区……东11区、东12区,往西分别为西1区、西2区……西11区、西12区,东12区和西12区重合(所属同一个时区)。


16.png


我们国家由于地域广袤辽阔,横跨了5个时区(东5、东6、东7、东8、东9),但建国以后,全国统一采用首都北京所处的东8区的时间。


虽然全世界一共划分了24个时区,同一个时间点,每个时区钟表上显示的时间各不同,但是它们仅仅是同一时刻在不同地区展示的形式,它们代表的仍然是一个时刻/瞬间。


跑题结束,开始正文。



跨境电商下单场景涉及的时区转换


先以跨境电商系统中的下单场景举个栗子,如果该电商系统的【数据库服务器】部署在英国伦敦,【应用服务器】部署在德国柏林,北京时间2020-06-01 10:00:00 有位北京的用户在通过浏览器在该网站上买了一个儿童节礼物。


这个过程就涉及到了时区转换的问题,一般刚给电脑安装操作系统的时候,都会让选择电脑所在时区,系统就是以时区来显示时间的。上面下单的例子涉及到三个设备:客户端(电脑浏览器/手机App)、网站web服务器、网站数据库服务器,都配置了对应的时区,假设这三种设备配置的时区就是所在地区的时区。


在【客户端→web服务器】、【web服务器→数据库】、【数据库→web服务器】、【web服务器→客户端】这几个过程都涉及到了时区的转换。如果不考虑时区转换,北京的用户在2020-06-01 10:00:00下单,web服务器处理的时候认为订单时间是在2020-06-01 03:00:00,然后传给数据库的订单时间也是2020-06-01 03:00:00,数据库保存的时候会保存成2020-06-01 03:00:00。当北京的用户查询订单的时候,数据库返回给应用服务器的订单时间为2020-06-01 03:00:00,最后应用服务器返回给用户的订单时间(用户看到的时间)也就是2020-06-01 03:00:00,如下图:



0.png


但实际上对用户来说是在2020-06-01 10:00:00下的单,应该是这样:

1.png


要解决这个问题,可以通过在客户端和web服务器、web服务器和数据库两两交互的时候添加”时区协议“来自动转换时区。


假如服务端应用是用SpringBoot实现的,可以在配置文件中配置

spring.jackson.time-zone = Asia/Shanghai(注意没有Asia/Beijing哈),这样应用服务器接收到客户端传来的时间后会把这个时间当成是东8区的时间转换成服务器所在时区的时间,也就是会把2020-06-01 10:00:00(UTC+8)转换成2020-06-01 03:00:00(UTC+1)。同样当客户端查询时,服务端会把当前时区的时间2020-06-01 03:00:00(UTC+1)转换成客户端所在时区的时间2020-06-01 10:00:00(UTC+8)。


假如服务端是用JDBC和MySQL交互,可以在MySQL连接中配置 serverTimezone=Europe/London,这样当应用服务器向Mysql发起持久化数据的请求时,会把服务器所在时区的时间2020-06-01 03:00:00(UTC+1)转换成数据库所在时区的时间2020-06-01 02:00:00(UTC)。同样当应用服务器查询数据的时候,会把数据库所在时区的时间2020-06-01 02:00:00(UTC)转换成服务器所在时区的时间2020-06-01 03:00:00(UTC+1)。


题外话


1、修改时区


一般浏览器的时区是默认获取的当前计算机系统的时区;应用服务器中获取的时区默认为当前计算机系统时区,可以在项目启动时设置(java -Duser.timezone=Asia/Shanghai -jar xxx.jar),也可以通过java.util.TimeZone动态设置;数据库时区默认也是取当前计算机系统时区,可以通过命令set global time_zone修改时区,可也以通过修改配置文件等其他方式。


2、Java中Date的时区无关性


Date类中有个fastTime变量,用来存储当前时刻的毫秒数。Date默认构造函数用System.currentTimeMillis()来为这个毫秒数赋值。


如果此刻在北京、柏林、伦敦同时执行如下语句:Date date = new Date();,那这三个date对象里存的毫秒数是相同的吗?答案是这3个Date里的毫秒数是完全一样的。


确切的说,Date对象里存的是自格林威治时间( GMT)1970年1月1日0点至Date对象所表示时刻所经过的毫秒数。所以,如果某一时刻遍布于世界各地的程序员同时执行new Date语句,这些Date对象所存的毫秒数是完全一样的。也就是说,Date里存放的毫秒数是与时区无关的。


相关文章
|
10天前
|
网络协议 网络架构
【网络编程入门】TCP与UDP通信实战:从零构建服务器与客户端对话(附简易源码,新手友好!)
在了解他们之前我们首先要知道网络模型,它分为两种,一种是OSI,一种是TCP/IP,当然他们的模型图是不同的,如下
|
22天前
|
Java Android开发
Java Socket编程示例:服务器开启在8080端口监听,接收客户端连接并打印消息。
【6月更文挑战第23天】 Java Socket编程示例:服务器开启在8080端口监听,接收客户端连接并打印消息。客户端连接服务器,发送"Hello, Server!"后关闭。注意Android中需避免主线程进行网络操作。
40 4
|
1天前
|
安全 网络协议 网络安全
SSL(Secure Sockets Layer)是一种安全协议,用于在客户端和服务器之间建立加密的通信通道。
SSL(Secure Sockets Layer)是一种安全协议,用于在客户端和服务器之间建立加密的通信通道。
4 0
|
5天前
|
Java 数据格式
Java面试题:简述Java Socket编程的基本流程,包括客户端和服务器的创建与通信。
Java面试题:简述Java Socket编程的基本流程,包括客户端和服务器的创建与通信。
11 0
|
12天前
|
网络协议 网络安全
使用NetAssist网络调试助手在单台计算机上配置TCP服务器和客户端
使用NetAssist网络调试助手在单台计算机上配置TCP服务器和客户端
27 0
|
15天前
|
SQL DataWorks 定位技术
DataWorks产品使用合集之进行ETL工作时,数据库位于国外且存在不同时区问题,该如何解决
DataWorks作为一站式的数据开发与治理平台,提供了从数据采集、清洗、开发、调度、服务化、质量监控到安全管理的全套解决方案,帮助企业构建高效、规范、安全的大数据处理体系。以下是对DataWorks产品使用合集的概述,涵盖数据处理的各个环节。
12 0
|
15天前
|
消息中间件 Serverless 网络性能优化
消息队列 MQ产品使用合集之客户端和服务器之间的保活心跳检测间隔是怎么设置的
消息队列(MQ)是一种用于异步通信和解耦的应用程序间消息传递的服务,广泛应用于分布式系统中。针对不同的MQ产品,如阿里云的RocketMQ、RabbitMQ等,它们在实现上述场景时可能会有不同的特性和优势,比如RocketMQ强调高吞吐量、低延迟和高可用性,适合大规模分布式系统;而RabbitMQ则以其灵活的路由规则和丰富的协议支持受到青睐。下面是一些常见的消息队列MQ产品的使用场景合集,这些场景涵盖了多种行业和业务需求。
|
17天前
|
网络协议 安全 分布式数据库
技术分享:分布式数据库DNS服务器的架构思路
技术分享:分布式数据库DNS服务器的架构思路
19 0
|
18天前
|
前端开发 API 开发工具
视觉智能开放平台产品使用合集之人脸识别客户端如何直接访问服务器进行人脸识别并传递视频流
视觉智能开放平台是指提供一系列基于视觉识别技术的API和服务的平台,这些服务通常包括图像识别、人脸识别、物体检测、文字识别、场景理解等。企业或开发者可以通过调用这些API,快速将视觉智能功能集成到自己的应用或服务中,而无需从零开始研发相关算法和技术。以下是一些常见的视觉智能开放平台产品及其应用场景的概览。
|
21天前
|
关系型数据库 MySQL Go
Mysql查看数据库时区并设置时区
Mysql查看数据库时区并设置时区
20 0