不要怂,就是干,撸起袖子干!

Commit 71df0289 by Jan Aagaard Meier

bug(dates/timezone) Fix parsing of dates in mysql when a named timezone is used. Closes #4208

1 parent 5132e4d2
# NEXT # NEXT
- [FIXED] `updatedAt` and `createdAt` values are now set before validation [#5367](https://github.com/sequelize/sequelize/pull/5367) - [FIXED] `updatedAt` and `createdAt` values are now set before validation [#5367](https://github.com/sequelize/sequelize/pull/5367)
- [FIXED] `describeTable` maintains proper enum casing in mysql [#5321](https://github.com/sequelize/sequelize/pull/5321) - [FIXED] `describeTable` maintains proper enum casing in mysql [#5321](https://github.com/sequelize/sequelize/pull/5321)
- [FIXED] Parsing of dates in MySQL, when a named timezone is used [#4208](https://github.com/sequelize/sequelize/issues/4208)
# 3.19.0 # 3.19.0
- [ADDED] Geography support for postgres - [ADDED] Geography support for postgres
......
...@@ -41,7 +41,7 @@ ConnectionManager.prototype.$clearTypeParser = function () { ...@@ -41,7 +41,7 @@ ConnectionManager.prototype.$clearTypeParser = function () {
ConnectionManager.$typecast = function (field, next) { ConnectionManager.$typecast = function (field, next) {
if (parserMap[field.type]) { if (parserMap[field.type]) {
return parserMap[field.type](field); return parserMap[field.type](field, this.sequelize.options);
} }
return next(); return next();
...@@ -57,7 +57,7 @@ ConnectionManager.prototype.connect = function(config) { ...@@ -57,7 +57,7 @@ ConnectionManager.prototype.connect = function(config) {
password: config.password, password: config.password,
database: config.database, database: config.database,
timezone: self.sequelize.options.timezone, timezone: self.sequelize.options.timezone,
typeCast: ConnectionManager.$typecast typeCast: ConnectionManager.$typecast.bind(self)
}; };
if (config.dialectOptions) { if (config.dialectOptions) {
......
'use strict'; 'use strict';
var wkx = require('wkx') var wkx = require('wkx')
, _ = require('lodash'); , _ = require('lodash')
, moment = require('moment-timezone');
module.exports = function (BaseTypes) { module.exports = function (BaseTypes) {
BaseTypes.ABSTRACT.prototype.dialectTypes = 'https://dev.mysql.com/doc/refman/5.7/en/data-types.html'; BaseTypes.ABSTRACT.prototype.dialectTypes = 'https://dev.mysql.com/doc/refman/5.7/en/data-types.html';
...@@ -39,6 +40,22 @@ module.exports = function (BaseTypes) { ...@@ -39,6 +40,22 @@ module.exports = function (BaseTypes) {
return date.format('YYYY-MM-DD HH:mm:ss'); return date.format('YYYY-MM-DD HH:mm:ss');
}; };
DATE.parse = function (value, options) {
value = value.string();
if (value === null) {
return value;
}
if (moment.tz.zone(options.timezone)) {
value = moment.tz(value, options.timezone).toDate();
} else {
value = new Date(value + ' ' + options.timezone);
}
return value;
};
var UUID = BaseTypes.UUID.inherits(); var UUID = BaseTypes.UUID.inherits();
UUID.prototype.toSql = function() { UUID.prototype.toSql = function() {
......
...@@ -44,15 +44,15 @@ if (dialect !== 'sqlite') { ...@@ -44,15 +44,15 @@ if (dialect !== 'sqlite') {
, TimezonedUser = this.sequelizeWithTimezone.define('user', {}); , TimezonedUser = this.sequelizeWithTimezone.define('user', {});
return this.sequelize.sync({ force: true }).bind(this).then(function() { return this.sequelize.sync({ force: true }).bind(this).then(function() {
return TimezonedUser.create({}); return NormalUser.create({});
}).then(function(timezonedUser) {
this.timezonedUser = timezonedUser;
return NormalUser.findById(timezonedUser.id);
}).then(function(normalUser) { }).then(function(normalUser) {
this.normalUser = normalUser;
return TimezonedUser.findById(normalUser.id);
}).then(function(timezonedUser) {
// Expect 7 hours difference, in milliseconds. // Expect 7 hours difference, in milliseconds.
// This difference is expected since two instances, configured for each their timezone is trying to read the same timestamp // This difference is expected since two instances, configured for each their timezone is trying to read the same timestamp
// this test does not apply to PG, since it stores the timezone along with the timestamp. // this test does not apply to PG, since it stores the timezone along with the timestamp.
expect(normalUser.createdAt.getTime() - this.timezonedUser.createdAt.getTime()).to.be.closeTo(60 * 60 * 7 * 1000, 50); expect(this.normalUser.createdAt.getTime() - timezonedUser.createdAt.getTime()).to.be.closeTo(60 * 60 * 7 * 1000, 50);
}); });
}); });
...@@ -63,11 +63,13 @@ if (dialect !== 'sqlite') { ...@@ -63,11 +63,13 @@ if (dialect !== 'sqlite') {
return this.sequelize.sync({ force: true }).bind(this).then(function() { return this.sequelize.sync({ force: true }).bind(this).then(function() {
return TimezonedUser.create({}); return TimezonedUser.create({});
}).then(function(timezonedUser) { }).then(function(timezonedUser) {
this.timezonedUser = timezonedUser; return Promise.all([
return NormalUser.findById(timezonedUser.id); NormalUser.findById(timezonedUser.id),
}).then(function(normalUser) { TimezonedUser.findById(timezonedUser.id)
]);
}).spread(function(normalUser, timezonedUser) {
// Expect 5 hours difference, in milliseconds, +/- 1 hour for DST // Expect 5 hours difference, in milliseconds, +/- 1 hour for DST
expect(normalUser.createdAt.getTime() - this.timezonedUser.createdAt.getTime()).to.be.closeTo(60 * 60 * 4 * 1000 * -1, 60 * 60 * 1000); expect(normalUser.createdAt.getTime() - timezonedUser.createdAt.getTime()).to.be.closeTo(60 * 60 * 4 * 1000 * -1, 60 * 60 * 1000);
}); });
}); });
} }
......
Markdown is supported
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!