mirror of
https://github.com/TryGhost/Ghost.git
synced 2024-12-25 11:55:03 +03:00
🐛 UTC offset for scheduled posts when changing timezone (#8356)
no issue - the UTC offset diff of the current and previous timezone must switch - i have added more tests and more example case descriptions to understand why
This commit is contained in:
parent
d704387482
commit
f7393686f8
@ -43,7 +43,7 @@ events.on('user.deactivated', function (userModel) {
|
||||
events.on('settings.activeTimezone.edited', function (settingModel) {
|
||||
var newTimezone = settingModel.attributes.value,
|
||||
previousTimezone = settingModel._updatedAttributes.value,
|
||||
timezoneOffsetDiff = moment.tz(newTimezone).utcOffset() - moment.tz(previousTimezone).utcOffset();
|
||||
timezoneOffsetDiff = moment.tz(previousTimezone).utcOffset() - moment.tz(newTimezone).utcOffset();
|
||||
|
||||
// CASE: TZ was updated, but did not change
|
||||
if (previousTimezone === newTimezone) {
|
||||
|
@ -17,11 +17,8 @@ describe('Models: listeners', function () {
|
||||
scope = {
|
||||
posts: [],
|
||||
publishedAtFutureMoment1: moment().add(2, 'days').startOf('hour'),
|
||||
publishedAtFutureMoment3: moment().add(10, 'hours').startOf('hour'),
|
||||
// calculate the offset dynamically, because of DST
|
||||
timezoneOffset: moment.tz.zone('Europe/London').offset(now) - moment.tz.zone('America/Los_Angeles').offset(now),
|
||||
newTimezone: 'America/Los_Angeles',
|
||||
oldTimezone: 'Europe/London'
|
||||
publishedAtFutureMoment2: moment().add(2, 'hours').startOf('hour'),
|
||||
publishedAtFutureMoment3: moment().add(10, 'hours').startOf('hour')
|
||||
};
|
||||
|
||||
before(testUtils.teardown);
|
||||
@ -46,7 +43,6 @@ describe('Models: listeners', function () {
|
||||
|
||||
describe('db has scheduled posts', function () {
|
||||
beforeEach(function (done) {
|
||||
// will get rescheduled
|
||||
scope.posts.push(testUtils.DataGenerator.forKnex.createPost({
|
||||
published_at: scope.publishedAtFutureMoment1.toDate(),
|
||||
status: 'scheduled',
|
||||
@ -54,15 +50,13 @@ describe('Models: listeners', function () {
|
||||
slug: '1'
|
||||
}));
|
||||
|
||||
// will get drafted
|
||||
scope.posts.push(testUtils.DataGenerator.forKnex.createPost({
|
||||
published_at: moment().add(2, 'hours').toDate(),
|
||||
published_at: scope.publishedAtFutureMoment2.toDate(),
|
||||
status: 'scheduled',
|
||||
title: '2',
|
||||
slug: '2'
|
||||
}));
|
||||
|
||||
// will get rescheduled
|
||||
scope.posts.push(testUtils.DataGenerator.forKnex.createPost({
|
||||
published_at: scope.publishedAtFutureMoment3.toDate(),
|
||||
status: 'scheduled',
|
||||
@ -81,9 +75,30 @@ describe('Models: listeners', function () {
|
||||
});
|
||||
});
|
||||
|
||||
it('activeTimezone changes change', function (done) {
|
||||
it('activeTimezone changes from London to Los Angeles', function (done) {
|
||||
var timeout;
|
||||
|
||||
/**
|
||||
* From London +1
|
||||
* To Los Angeles -7
|
||||
*
|
||||
* We expect +420 minutes if DST. (otherwise +480)
|
||||
*
|
||||
* Image it's 11AM London time. 10AM UTC.
|
||||
* Imagine the post is scheduled for 8PM London time.
|
||||
* The database UTC string is e.g. 2017-04-18 19:00:00.
|
||||
* You switch the timezone to Los Angeles.
|
||||
* It's 3AM in the morning in Los Angeles.
|
||||
* If we don't change the database UTC string, the post is scheduled at 11AM in the morning! (19-7)
|
||||
* The post should be still scheduled for 8PM Los Angeles time.
|
||||
* So the database UTC string must be 2017-04-19 03:00:00. (-7 hours === 8 o'clock in Los Angeles)
|
||||
*/
|
||||
|
||||
// calculate the offset dynamically, because of DST
|
||||
scope.timezoneOffset = moment.tz.zone('America/Los_Angeles').offset(now) - moment.tz.zone('Europe/London').offset(now);
|
||||
scope.newTimezone = 'America/Los_Angeles';
|
||||
scope.oldTimezone = 'Europe/London';
|
||||
|
||||
eventsToRemember['settings.activeTimezone.edited']({
|
||||
attributes: {value: scope.newTimezone},
|
||||
_updatedAttributes: {value: scope.oldTimezone}
|
||||
@ -104,9 +119,10 @@ describe('Models: listeners', function () {
|
||||
|
||||
if (results.models.length === posts.length &&
|
||||
post1.get('status') === 'scheduled' &&
|
||||
post2.get('status') === 'draft' &&
|
||||
post2.get('status') === 'scheduled' &&
|
||||
post3.get('status') === 'scheduled' &&
|
||||
moment(post1.get('published_at')).diff(scope.publishedAtFutureMoment1.clone().add(scope.timezoneOffset, 'minutes')) === 0 &&
|
||||
moment(post2.get('published_at')).diff(scope.publishedAtFutureMoment2.clone().add(scope.timezoneOffset, 'minutes')) === 0 &&
|
||||
moment(post3.get('published_at')).diff(scope.publishedAtFutureMoment3.clone().add(scope.timezoneOffset, 'minutes')) === 0) {
|
||||
return done();
|
||||
}
|
||||
@ -118,10 +134,25 @@ describe('Models: listeners', function () {
|
||||
})();
|
||||
});
|
||||
|
||||
it('activeTimezone changes change: from a TZ to UTC', function (done) {
|
||||
it('activeTimezone changes from Baghdad to UTC', function (done) {
|
||||
var timeout;
|
||||
|
||||
scope.timezoneOffset = -180;
|
||||
/**
|
||||
* From Baghdad +3
|
||||
* To UTC +/-0
|
||||
*
|
||||
* We expect +180 minutes.
|
||||
*
|
||||
* Image it's 11AM Baghdad time.
|
||||
* Imagine the post is scheduled for 8PM Baghdad time.
|
||||
* The database UTC string is e.g. 2017-04-18 17:00:00.
|
||||
* You switch the timezone to UTC.
|
||||
* It's 9AM in the morning in UTC.
|
||||
* If we don't change the database UTC string, the post is scheduled at 5PM in the evening!
|
||||
* The post should be still scheduled for 8PM UTC time.
|
||||
* So the database UTC string must be 2017-04-19 20:00:00.
|
||||
*/
|
||||
scope.timezoneOffset = 180;
|
||||
scope.oldTimezone = 'Asia/Baghdad';
|
||||
scope.newTimezone = 'Etc/UTC';
|
||||
|
||||
@ -130,6 +161,63 @@ describe('Models: listeners', function () {
|
||||
_updatedAttributes: {value: scope.oldTimezone}
|
||||
});
|
||||
|
||||
(function retry() {
|
||||
models.Post.findAll({context: {internal: true}})
|
||||
.then(function (results) {
|
||||
var post1 = _.find(results.models, function (post) {
|
||||
return post.get('title') === '1';
|
||||
}),
|
||||
post2 = _.find(results.models, function (post) {
|
||||
return post.get('title') === '2';
|
||||
}),
|
||||
post3 = _.find(results.models, function (post) {
|
||||
return post.get('title') === '3';
|
||||
});
|
||||
|
||||
if (results.models.length === posts.length &&
|
||||
post1.get('status') === 'scheduled' &&
|
||||
post2.get('status') === 'scheduled' &&
|
||||
post3.get('status') === 'scheduled' &&
|
||||
moment(post1.get('published_at')).diff(scope.publishedAtFutureMoment1.clone().add(scope.timezoneOffset, 'minutes')) === 0 &&
|
||||
moment(post2.get('published_at')).diff(scope.publishedAtFutureMoment2.clone().add(scope.timezoneOffset, 'minutes')) === 0 &&
|
||||
moment(post3.get('published_at')).diff(scope.publishedAtFutureMoment3.clone().add(scope.timezoneOffset, 'minutes')) === 0) {
|
||||
return done();
|
||||
}
|
||||
|
||||
clearTimeout(timeout);
|
||||
timeout = setTimeout(retry, 500);
|
||||
})
|
||||
.catch(done);
|
||||
})();
|
||||
});
|
||||
|
||||
it('activeTimezone changes from Amsterdam to Seoul', function (done) {
|
||||
var timeout;
|
||||
|
||||
/**
|
||||
* From Amsterdam +2
|
||||
* To Seoul +9
|
||||
*
|
||||
* We expect -420 minutes.
|
||||
*
|
||||
* Image it's 11AM Amsterdam time. 9AM UTC.
|
||||
* Imagine the post is scheduled for 8PM Amsterdam time.
|
||||
* The database UTC string is e.g. 2017-04-18 18:00:00.
|
||||
* You switch the timezone to Seoul timezone.
|
||||
* It's 6PM in the evening in Seoul timezone.
|
||||
* If we don't change the database UTC string, the post is scheduled at 3AM in the evening on the next day!
|
||||
* The post should be still scheduled for 8PM UTC time.
|
||||
* So the database UTC string must be 2017-04-18 11:00:00.
|
||||
*/
|
||||
scope.timezoneOffset = -420;
|
||||
scope.oldTimezone = 'Europe/Amsterdam';
|
||||
scope.newTimezone = 'Asia/Seoul';
|
||||
|
||||
eventsToRemember['settings.activeTimezone.edited']({
|
||||
attributes: {value: scope.newTimezone},
|
||||
_updatedAttributes: {value: scope.oldTimezone}
|
||||
});
|
||||
|
||||
(function retry() {
|
||||
models.Post.findAll({context: {internal: true}})
|
||||
.then(function (results) {
|
||||
|
Loading…
Reference in New Issue
Block a user