1.现象
前端向nodejs服务器请求数据时,发现得到的返回数据中日期字段(json格式)值有时差
从mysql中读出的时间格式 > publishtime:Sat Aug 19 2017 15:46:01 GMT+0800 (中国标准时间)
前端收到的时间格式 > "publishtime":"2017-07-16T14:46:01.000Z"
“Sat Aug 19 2017 15:46:01 GMT+0800”这个可以用new date 得到和设置的时间一致,但是用json序列化过的时间重新new 后得到的时间和设置的时间相差8个小时。
原因是时间对象在转化成json字符串时会被转换成国际标准时间(ISO),而不是当前国家区域的时间,而用new Date转成时间对象返回的是当前国家所在时区的时间,东八区就加上了8个小时。
2.解决
nodejs发送前数据转化在response.js中,
res.send = function send(body) { var chunk = body; var encoding; var len; var req = this.req; var type; // settings var app = this.app; // allow status / body if (arguments.length === 2) { // res.send(body, status) backwards compat if (typeof arguments[0] !== 'number' && typeof arguments[1] === 'number') { deprecate('res.send(body, status): Use res.status(status).send(body) instead'); this.statusCode = arguments[1]; } else { deprecate('res.send(status, body): Use res.status(status).send(body) instead'); this.statusCode = arguments[0]; chunk = arguments[1]; } } // disambiguate res.send(status) and res.send(status, num) if (typeof chunk === 'number' && arguments.length === 1) { // res.send(status) will set status message as text string if (!this.get('Content-Type')) { this.type('txt'); } deprecate('res.send(status): Use res.sendStatus(status) instead'); this.statusCode = chunk; chunk = statuses[chunk] } switch (typeof chunk) { // string defaulting to html case 'string': if (!this.get('Content-Type')) { this.type('html'); } break; case 'boolean': case 'number': case 'object': if (chunk === null) { chunk = ''; } else if (Buffer.isBuffer(chunk)) { if (!this.get('Content-Type')) { this.type('bin'); } } else { return this.json(chunk); } break; } ...............此处省略.................
如果发送的数据是对象的话,会转换成json字符串格式后在发送,下面是json转换
res.json = function json(obj) { var val = obj; // allow status / body if (arguments.length === 2) { // res.json(body, status) backwards compat if (typeof arguments[1] === 'number') { deprecate('res.json(obj, status): Use res.status(status).json(obj) instead'); this.statusCode = arguments[1]; } else { deprecate('res.json(status, obj): Use res.status(status).json(obj) instead'); this.statusCode = arguments[0]; val = arguments[1]; } } // settings var app = this.app; var replacer = app.get('json replacer'); var spaces = app.get('json spaces'); var body = stringify(val, replacer, spaces); // content-type if (!this.get('Content-Type')) { this.set('Content-Type', 'application/json'); } return this.send(body); };
继续跟踪发现 xxpluginsJavaScriptLanguagelibJavaScriptLanguage.jar!comintellijlangjavascriptindexpredefinedEcmaScript5.js 这里有这两句
Date.now = function() {}; /** @return {string} */ Date.prototype.toJSON = function() {};
发现原来日期类型有专门的转化处理方式的。所以我的解决方式是 覆盖这个方法,返回time长整型,方便处理,也不容易有时区转化问题。
Date.prototype.toJSON = function () { return this.getTime(); }
当然如果只是展示成一般格式的话可以用这个,直接网上拷贝一个,可以看这个博客http://www.cnblogs.com/vipstone/p/4953110.html
function dateFormat(date, fmt) { if (null == date || undefined == date) return ''; var o = { "M+": date.getMonth() + 1, //月份 "d+": date.getDate(), //日 "h+": date.getHours(), //小时 "m+": date.getMinutes(), //分 "s+": date.getSeconds(), //秒 "S": date.getMilliseconds() //毫秒 }; if (/(y+)/.test(fmt)) fmt = fmt.replace(RegExp.$1, (date.getFullYear() + "").substr(4 - RegExp.$1.length)); for (var k in o) if (new RegExp("(" + k + ")").test(fmt)) fmt = fmt.replace(RegExp.$1, (RegExp.$1.length == 1) ? (o[k]) : (("00" + o[k]).substr(("" + o[k]).length))); return fmt; }