【踩坑】服务器和本地相差8小时 |
您所在的位置:网站首页 › k8s容器时间比本地时间快8小时 › 【踩坑】服务器和本地相差8小时 |
最近在弄需求的接口的时候,添加数据需要比对时间 如果添加的该条数据的时间区间在数据库中已经有重叠的区间,那么就不允许添加,但是在添加的数据的时候,明明添加并没有这个区间,但是一直提示已经存在数据 在确认比较的条件没有问题之后,才发现是 时间转换的问题!! 本地时间和 服务器时间相差了8个小时,具体是服务器时间 比 本地时间 早了8个小时 也就是 本地时间是 16:00,服务器时间是 8:00,查了好久,所以值得记录一下,完善一下时间的知识点 回到正题,本文会分成两个部分 1、原因 2、解决办法 1.原因 简单说,因为本地时区和服务器的时区不一样,差了8个小时导致 1什么是时区 由于地球很大,每个地方经历的昼夜都不一样。 而大家又习惯于时间和昼夜的对应关系,比如正午就是12点 但是如果全球用一个时间,就会完成有一些国家的正午12点是大半夜。这样就不符合人们的作息习惯了。 从而分出了时区的概念,让时间相对统一,而不是绝对统一 2时间分了什么时区 在1884年的华盛顿国际会议上,把全球划分为了24个时区,零时区,东12个区,西12个区,每个区相差1个小时 一般概念是这么按时区去计算时间,但是实际上,有的国家国土通常横跨几个时区,所以最后是以国家为纬度计算,比如大中国横跨5个时区,还是只共用一个时区。即东8区,北京时间 其中有个零时区,他的位置在英国(格林尼治天文台旧址) 3时区的时间标准 因为时间是相对统一的,所有时区的时间都是相对于零时区得出的,那么就需要一个格式去表示 时间标准 有两种, UTC 和 GMT 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 这个问题也是因为对于时间的 概念模糊造成了,排查了很久,不过也算是填了自己知识的一个坑 最后 鉴于本人能力有限,难免会有疏漏错误的地方,请大家多多包涵, 如果有任何描述不当的地方,欢迎后台联系本人 |
今日新闻 |
点击排行 |
|
推荐新闻 |
图片新闻 |
|
专题文章 |
CopyRight 2018-2019 实验室设备网 版权所有 win10的实时保护怎么永久关闭 |