Fix schedule using wrong month at the beginning hours of month (#15290)

* Fix schedule using wrong month at the beginning hours of month

* fix broken test

* fix switchover for time based matchers

* Fix scheduling issue related to timezones

* Fix end date creating issues
This commit is contained in:
Phillip Thelen
2024-08-06 19:35:05 +02:00
committed by GitHub
parent 6293a4b936
commit 63918b3c20
4 changed files with 67 additions and 11 deletions

View File

@@ -47,9 +47,9 @@ describe('shops', () => {
describe('premium hatching potions', () => { describe('premium hatching potions', () => {
it('contains current scheduled premium hatching potions', async () => { it('contains current scheduled premium hatching potions', async () => {
clock = sinon.useFakeTimers(new Date('2024-04-01')); clock = sinon.useFakeTimers(new Date('2024-04-01T09:00:00.000Z'));
const potions = shared.shops.getMarketCategories(user).find(x => x.identifier === 'premiumHatchingPotions'); const potions = shared.shops.getMarketCategories(user).find(x => x.identifier === 'premiumHatchingPotions');
expect(potions.items.length).to.eql(2); expect(potions.items.length).to.eql(3);
}); });
it('does not contain past scheduled premium hatching potions', async () => { it('does not contain past scheduled premium hatching potions', async () => {
@@ -73,9 +73,9 @@ describe('shops', () => {
}); });
it('does not contain locked quest premium hatching potions', async () => { it('does not contain locked quest premium hatching potions', async () => {
clock = sinon.useFakeTimers(new Date('2024-04-01')); clock = sinon.useFakeTimers(new Date('2024-04-01T09:00:00.000Z'));
const potions = shared.shops.getMarketCategories(user).find(x => x.identifier === 'premiumHatchingPotions'); const potions = shared.shops.getMarketCategories(user).find(x => x.identifier === 'premiumHatchingPotions');
expect(potions.items.length).to.eql(2); expect(potions.items.length).to.eql(3);
expect(potions.items.filter(x => x.key === 'Bronze' || x.key === 'BlackPearl').length).to.eql(0); expect(potions.items.filter(x => x.key === 'Bronze' || x.key === 'BlackPearl').length).to.eql(0);
}); });

View File

@@ -18,12 +18,19 @@ function validateMatcher (matcher, checkedDate) {
describe('Content Schedule', () => { describe('Content Schedule', () => {
let switchoverTime; let switchoverTime;
let clock;
beforeEach(() => { beforeEach(() => {
switchoverTime = nconf.get('CONTENT_SWITCHOVER_TIME_OFFSET') || 0; switchoverTime = nconf.get('CONTENT_SWITCHOVER_TIME_OFFSET') || 0;
clearCachedMatchers(); clearCachedMatchers();
}); });
afterEach(() => {
if (clock) {
clock.restore();
}
});
it('assembles scheduled items on january 15th', () => { it('assembles scheduled items on january 15th', () => {
const date = new Date('2024-01-15'); const date = new Date('2024-01-15');
const matchers = getAllScheduleMatchingGroups(date); const matchers = getAllScheduleMatchingGroups(date);
@@ -105,8 +112,14 @@ describe('Content Schedule', () => {
expect(matchers.backgrounds.end).to.eql(moment.utc(`2024-05-07T${String(switchoverTime).padStart(2, '0')}:00:00.000Z`).toDate()); expect(matchers.backgrounds.end).to.eql(moment.utc(`2024-05-07T${String(switchoverTime).padStart(2, '0')}:00:00.000Z`).toDate());
}); });
it('sets the end date if its on the release day', () => { it('sets the end date if its on the release day before switchover', () => {
const date = new Date('2024-05-07T07:00:00.000Z'); const date = new Date('2024-05-07T07:00:00.000+00:00');
const matchers = getAllScheduleMatchingGroups(date);
expect(matchers.backgrounds.end).to.eql(moment.utc(`2024-05-07T${String(switchoverTime).padStart(2, '0')}:00:00.000Z`).toDate());
});
it('sets the end date if its on the release day after switchover', () => {
const date = new Date('2024-05-07T09:00:00.000+00:00');
const matchers = getAllScheduleMatchingGroups(date); const matchers = getAllScheduleMatchingGroups(date);
expect(matchers.backgrounds.end).to.eql(moment.utc(`2024-06-07T${String(switchoverTime).padStart(2, '0')}:00:00.000Z`).toDate()); expect(matchers.backgrounds.end).to.eql(moment.utc(`2024-06-07T${String(switchoverTime).padStart(2, '0')}:00:00.000Z`).toDate());
}); });
@@ -129,6 +142,42 @@ describe('Content Schedule', () => {
expect(matchers.seasonalGear.end).to.eql(moment.utc(`2025-03-21T${String(switchoverTime).padStart(2, '0')}:00:00.000Z`).toDate()); expect(matchers.seasonalGear.end).to.eql(moment.utc(`2025-03-21T${String(switchoverTime).padStart(2, '0')}:00:00.000Z`).toDate());
}); });
it('uses correct date for first hours of the month', () => {
// if the date is checked before CONTENT_SWITCHOVER_TIME_OFFSET,
// it should be considered the previous month
const date = new Date('2024-05-01T02:00:00.000Z');
const matchers = getAllScheduleMatchingGroups(date);
expect(matchers.petQuests.items).to.contain('snake');
expect(matchers.petQuests.items).to.not.contain('horse');
expect(matchers.timeTravelers.match('202304'), '202304').to.be.true;
expect(matchers.timeTravelers.match('202404'), '202404').to.be.false;
expect(matchers.timeTravelers.match('202305'), '202305').to.be.false;
});
it('uses correct date after switchover time', () => {
// if the date is checked after CONTENT_SWITCHOVER_TIME_OFFSET,
// it should be considered the current
const date = new Date('2024-05-01T09:00:00.000Z');
const matchers = getAllScheduleMatchingGroups(date);
expect(matchers.petQuests.items).to.contain('snake');
expect(matchers.petQuests.items).to.not.contain('horse');
expect(matchers.timeTravelers.match('202304'), '202304').to.be.false;
expect(matchers.timeTravelers.match('202305'), '202305').to.be.true;
expect(matchers.timeTravelers.match('202405'), '202405').to.be.false;
});
it('uses UTC timezone', () => {
// if the date is checked after CONTENT_SWITCHOVER_TIME_OFFSET,
// it should be considered the current
clock = sinon.useFakeTimers(new Date('2024-05-01T05:00:00.000-04:00'));
const matchers = getAllScheduleMatchingGroups();
expect(matchers.petQuests.items).to.contain('snake');
expect(matchers.petQuests.items).to.not.contain('horse');
expect(matchers.timeTravelers.match('202304'), '202304').to.be.false;
expect(matchers.timeTravelers.match('202305'), '202305').to.be.true;
expect(matchers.timeTravelers.match('202405'), '202405').to.be.false;
});
it('contains content for repeating events', () => { it('contains content for repeating events', () => {
const date = new Date('2024-04-15'); const date = new Date('2024-04-15');
const matchers = getAllScheduleMatchingGroups(date); const matchers = getAllScheduleMatchingGroups(date);

View File

@@ -45,7 +45,7 @@ describe('time-travelers store', () => {
describe('on may 1st', () => { describe('on may 1st', () => {
beforeEach(() => { beforeEach(() => {
date = new Date('2024-05-01'); date = new Date('2024-05-01T09:00:00.000Z');
}); });
it('returns the correct gear', () => { it('returns the correct gear', () => {
const items = timeTravelers.timeTravelerStore(user, date); const items = timeTravelers.timeTravelerStore(user, date);

View File

@@ -809,7 +809,9 @@ function getMonth (date) {
if (date === undefined) { if (date === undefined) {
return 0; return 0;
} }
return date instanceof moment ? date.month() : date.getMonth(); const checkDate = new Date(date.getTime());
checkDate.setHours(checkDate.getHours() - SWITCHOVER_TIME);
return checkDate.getMonth();
} }
function getGalaIndex (date) { function getGalaIndex (date) {
@@ -892,7 +894,7 @@ function makeEndDate (checkedDate, matcher) {
end.year(checkedDate.getFullYear() + 1); end.year(checkedDate.getFullYear() + 1);
} }
end.month(matcher.endMonth); end.month(matcher.endMonth);
} else if (end.date() <= checkedDate.getDate()) { } else if (end.valueOf() <= checkedDate.getTime()) {
end = moment(end).add(1, 'months'); end = moment(end).add(1, 'months');
} }
return end.toDate(); return end.toDate();
@@ -904,7 +906,7 @@ export function clearCachedMatchers () {
} }
export function getAllScheduleMatchingGroups (date) { export function getAllScheduleMatchingGroups (date) {
const checkedDate = date || new Date(); const checkedDate = date || moment.utc().toDate();
if (cacheDate !== null && (getDay(checkedDate) !== getDay(cacheDate) if (cacheDate !== null && (getDay(checkedDate) !== getDay(cacheDate)
|| getMonth(checkedDate) !== getMonth(cacheDate))) { || getMonth(checkedDate) !== getMonth(cacheDate))) {
// Clear cached matchers, since they are old // Clear cached matchers, since they are old
@@ -914,9 +916,14 @@ export function getAllScheduleMatchingGroups (date) {
// No matchers exist, make new ones // No matchers exist, make new ones
cacheDate = new Date(); cacheDate = new Date();
cachedScheduleMatchers = {}; cachedScheduleMatchers = {};
// subtract switchover time for the matcher classes, but
// NOT to decide which matchers to assemble.
// assembly uses getDate and getMonth which already adjust for switchover time
const adjustedDate = new Date(checkedDate.getTime());
adjustedDate.setHours(adjustedDate.getHours() - SWITCHOVER_TIME);
assembleScheduledMatchers(checkedDate).forEach(matcher => { assembleScheduledMatchers(checkedDate).forEach(matcher => {
if (!cachedScheduleMatchers[matcher.type]) { if (!cachedScheduleMatchers[matcher.type]) {
cachedScheduleMatchers[matcher.type] = makeMatcherClass(checkedDate); cachedScheduleMatchers[matcher.type] = makeMatcherClass(adjustedDate);
} }
cachedScheduleMatchers[matcher.type].end = makeEndDate(checkedDate, matcher); cachedScheduleMatchers[matcher.type].end = makeEndDate(checkedDate, matcher);
if (matcher.matcher instanceof Function) { if (matcher.matcher instanceof Function) {