前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >【踩坑】服务器和本地相差8小时

【踩坑】服务器和本地相差8小时

作者头像
神仙朱
发布2021-07-20 16:55:33
5.8K0
发布2021-07-20 16:55:33
举报

最近在弄需求的接口的时候,添加数据需要比对时间

如果添加的该条数据的时间区间在数据库中已经有重叠的区间,那么就不允许添加,但是在添加的数据的时候,明明添加并没有这个区间,但是一直提示已经存在数据

在确认比较的条件没有问题之后,才发现是 时间转换的问题!!

本地时间和 服务器时间相差了8个小时,具体是服务器时间 比 本地时间 早了8个小时

也就是 本地时间是 16:00,服务器时间是 8:00,查了好久,所以值得记录一下,完善一下时间的知识点

回到正题,本文会分成两个部分

1、原因

2、解决办法

1.原因

简单说,因为本地时区和服务器的时区不一样,差了8个小时导致

1什么是时区

由于地球很大,每个地方经历的昼夜都不一样。

而大家又习惯于时间和昼夜的对应关系,比如正午就是12点

但是如果全球用一个时间,就会完成有一些国家的正午12点是大半夜。这样就不符合人们的作息习惯了。

从而分出了时区的概念,让时间相对统一,而不是绝对统一

2时间分了什么时区

在1884年的华盛顿国际会议上,把全球划分为了24个时区,零时区,东12个区,西12个区,每个区相差1个小时

一般概念是这么按时区去计算时间,但是实际上,有的国家国土通常横跨几个时区,所以最后是以国家为纬度计算,比如大中国横跨5个时区,还是只共用一个时区。即东8区,北京时间

其中有个零时区,他的位置在英国(格林尼治天文台旧址)

3时区的时间标准

因为时间是相对统一的,所有时区的时间都是相对于零时区得出的,那么就需要一个格式去表示

时间标准 有两种, UTCGMT

UTC 是我们现在用的时间标准,GMT是老的时间计量标准。

UTC 是根据原子钟来计算时间,

GMT是英国格林尼治天文台观测太阳每天经过它的时间就是中午12点

所以能看到GMT根据地球自转来计算时间,肯定有误差,并且自转时间不可控,可能快一点可能慢一点,所以我们会采取更加精准的UTC

UTC主要是各个时区相对于零时区加上 时间偏移量

UTC偏移量的表示形式为:±[hh]:[mm]、±[hh][mm]或者±[hh]

比如北京时间比协调世界时(UTC)早八小时,那么表示为:UTC+8

我们的时间 = 零时区时间 + 8个小时

4时间格式

时间格式有两种,RFC-2822标准格式 和 ISO-8601标准格式

RFC-2822标准格式

比如

Tue Jul 06 2021 16:31:45 GMT+0800

GMT+0800 表示 GMT 时间 +8 小时,即是东八区

JavaScript 使用 new Date 返回的也是这个格式

ISO-8601标准格式

比如

2021-07-06T16:31:45+08:00

T 后面表示的是 时分秒,+08:00 也是表示 东八区的意思

如果是零时区,则可以表示成

2021-07-04T16:33:23.400Z

其中 Z 就表示这是 UTC 时间

5怎么知道是什么时区

在JavaScript中当然提供了一个对象 Intl,他可以提供精确的日期格式化,数字格式化 等

今天我们只用他的一个api获取时区

代码语言:javascript
复制
Intl.DateTimeFormat().resolvedOptions().timeZone

在控制台执行一下,可以看到输出

代码语言:javascript
复制
Asia/Shanghai

咦,为什么是上海,不应该是北京吗

原因是1949年以前,中国一共分了5个时区,以哈尔滨 ( Asia/Harbin)、上海(Asia/Shanghai)、重庆(Asia/Chongqing)、乌鲁木齐(Asia/Urumqi)、喀什(Asia/Kashgar)为代表——分别是:长白时区GMT+8:30、中原标准时区 GMT+8、陇蜀时区GMT+7、新藏时区GMT+6和昆仑时区GMT+5:30。它是1912年北京观象台制订,后由内政部批准过。而且从国际标准本身的角度来看,北京和上海处于同一时区,只能保留一个。而作为时区代表上海已经存在,并且足够具有代表性,因此其维护者没有足够的动力做出改变。所以目前还没有Asia/Beijing。

然后我们在服务器打印一下时区,则显示

UTC

好家伙,果然是时区不对,所以时区不同,不能直接计算的

6时间怎么转换时区

比如我当前有一个北京时间,我怎么知道他对应的美国时间是多少呢

同一个时间戳在 不同时区 对应的 时间是不一样的

所以我们需要转换一下

代码语言:javascript
复制
Date.prototype.toLocaleString( [locales [, options] ] )

该方法可以根据你设定的 语言 和 时区 来给你返回对应的 时间

如果是你什么都不传,默认就是你所在的时区

如果你是我大中国时间,想看看对应的美国时间是多少,可以这么设置 timeZone

代码语言:javascript
复制
new Date().toLocaleString("chinese",{
   hour12:false,
   timeZone:"America/New_York"
})

如下图,可以看到差了12 个小时

相关的时区有

"Asia/Shanghai" ,"Asia/Kolkata", "America/New_York" 等

更多时区可以看

https://www.iana.org/time-zones

2.解决办法

就是要保证 本地 和 服务器通信的 时间 是同一个时区

1、前后端时间字段直接使用 时间戳 ,数据库存时间戳

2、使用同一个时区进行转换

1前端传时间戳,数据库也存时间戳

最简单的处理方式,不用任何转换

因为时间戳都是 前端传的,所以可以保证都是都是同一个时区,可以直接进行计算(如果你应用是国际化的,就不行了,还是要转)

2使用同一个时区进行转换

但是我这次的问题是,前端传的是时间戳,而数据库存的是格式化后的时间

然后我把数据库的数据查出来转成了时间戳 之后,和 前端传的时间戳 进行比较

这个时候才有这个大问题因为 服务器是 UTC 时区,如果我用这个 格式化的时间 转成 时间戳

得到的时间戳 比 实际对应的时间戳 大 8h

因为原本

Local Time= 2021-05-27 14:00:00

Server Time= Local Time - 8 (本地是 东八区,server 是 UTC,所以本地时间比 server 多八个小时)

如果本地时间当做服务器时间直接转换

Server Time= 2021-05-27 14:00:00

那么相当于本地时间比原来传的多了8h

Local Time= ServerTime + 8h = 2021-05-27 22:00:00

如果这样进行比较,肯定是不对的了,所以取出来的时间转成 时间戳必须要设置时区

具体我使用了 dayjs,如下

代码语言:javascript
复制
const dayjs = require('dayjs');
const utc = require('dayjs/plugin/utc');
const timezone = require('dayjs/plugin/timezone');
dayjs.extend(utc);
dayjs.extend(timezone);
function getSvrTimestampTZ(datestring) {
  return dayjs.tz(datestring, "Asia/Shanghai").valueOf()
}

然后测试一下

代码语言:javascript
复制
// 服务器运行
getSvrTimestampTZ("2021-7-6 21:00:00") // 1625576400000
// 本地运行
new Date("2021-7-6 21:00:00").getTime() // 1625576400000

可以看到,同一个时间转换得到的时间戳是一样的了,说明现在就对了

都是 1625576400000

如果服务器不设置时区,那么直接转得到的时间戳是 1625605200000

1625605200000 - 1625576400000

= 28800000

= 8 * 60*60*1000

这个问题也是因为对于时间的 概念模糊造成了,排查了很久,不过也算是填了自己知识的一个坑

最后

鉴于本人能力有限,难免会有疏漏错误的地方,请大家多多包涵, 如果有任何描述不当的地方,欢迎后台联系本人

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2021-07-18,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 神仙朱 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
相关产品与服务
数据库
云数据库为企业提供了完善的关系型数据库、非关系型数据库、分析型数据库和数据库生态工具。您可以通过产品选择和组合搭建,轻松实现高可靠、高可用性、高性能等数据库需求。云数据库服务也可大幅减少您的运维工作量,更专注于业务发展,让企业一站式享受数据上云及分布式架构的技术红利!
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档