问题背景
js中获取当前时间,并进行json序列化,传至后台,发现存入数据库中后时间早了八个小时。
var msgObj= {
msgId:RndNum(16),
msgType:messageType,
data:message,
fromUid:fromUid,
toUid:toUid,
createAt:new Date()
};
var json = JSON.stringify(msgObj)
逐步调试差错
一步一步调试发现问题所在:
- js获取的本地时间正确:
以上是浏览器中通过RFC-822格式展示的时间,GMT+8即格林威治时间+8小时,正好是中国的东八区时间。
- JSON序列化后时区信息丢失
此处是按照RFC-3339格式展示的时间,以下为RFC-3339格式关于时区的规则:
最末尾一位字母表示时区
字母A至I 代表+0100到+0900
字母k至M 代表+1000到+1200
字母N至Y 代表-100到-1200
字母z 代表+0000
即,本地时间经过JSON序列化之后,变成了格林威治时间,数值上比本地时间要小8个小时,即2021-02-16T09:18:36
于是在golang后台获取得到的元数据为:
json反序列化后用time.Time类型装载得到的时间为:
在我的golang后端程序中,连接mysql时没有加上&loc=Local
属性,导致上述丢失了时区信息的时间入库后比东八区时间小了八个小时。
在加上&loc=Local
属性后,上述时间入库后则是正确的东八区时间
解决办法
到这里,我遇到的问题实际上已经解决,但是依然没有解决JSON解析Date丢失时区的问题,可以这样做:
- 重写Date类型的toJSON方法,通过可以保留时区信息的功能接口进行stringfy,例如,使用moment.js的fomat()方法:
- 引入moment.js脚本文件
<script type="text/javascript" src="http://cdn.staticfile.org/moment.js/2.24.0/moment.js"></script>
- 重写Date的toJSON方法
Date.prototype.toJSON = function(){ return moment(this).format(); }
- 注意到,这里的无参format()方法会按照RFC-3339格式对当前Date对象stringfty,能够保留本地的时区。
- 引入moment.js脚本文件
如此操作以后,js页面传到后台的时间就会包含时区信息,存入数据库后依然正确。