From c7bc924ea7da7d51f990667b3b5ed7524e2299db Mon Sep 17 00:00:00 2001 From: Oli Zimpasser Date: Fri, 22 Mar 2024 22:32:25 +0100 Subject: [PATCH] Fix early bird utc problem --- package-lock.json | 20 +++++ package.json | 1 + src/service/eliteEarlyBirdService.test.ts | 37 +++------ src/service/eliteEarlyBirdService.ts | 92 +++++++---------------- 4 files changed, 59 insertions(+), 91 deletions(-) diff --git a/package-lock.json b/package-lock.json index 530d847..bf3b240 100644 --- a/package-lock.json +++ b/package-lock.json @@ -21,6 +21,7 @@ "dotenv": "^16.0.3", "google-auth-library": "^8.7.0", "googleapis": "^110.0.0", + "moment-timezone": "^0.5.45", "node-fetch": "^3.3.0", "node-schedule": "^2.1.1", "sqlite3": "^5.1.6", @@ -5872,6 +5873,25 @@ "node": ">=10" } }, + "node_modules/moment": { + "version": "2.30.1", + "resolved": "https://registry.npmjs.org/moment/-/moment-2.30.1.tgz", + "integrity": "sha512-uEmtNhbDOrWPFS+hdjFCBfy9f2YoyzRpwcl+DqpC6taX21FzsTLQVbMV/W7PzNSX6x/bhC1zA3c2UQ5NzH6how==", + "engines": { + "node": "*" + } + }, + "node_modules/moment-timezone": { + "version": "0.5.45", + "resolved": "https://registry.npmjs.org/moment-timezone/-/moment-timezone-0.5.45.tgz", + "integrity": "sha512-HIWmqA86KcmCAhnMAN0wuDOARV/525R2+lOLotuGFzn4HO+FH+/645z2wx0Dt3iDv6/p61SIvKnDstISainhLQ==", + "dependencies": { + "moment": "^2.29.4" + }, + "engines": { + "node": "*" + } + }, "node_modules/ms": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", diff --git a/package.json b/package.json index e74d0d6..b1e522d 100644 --- a/package.json +++ b/package.json @@ -18,6 +18,7 @@ "dotenv": "^16.0.3", "google-auth-library": "^8.7.0", "googleapis": "^110.0.0", + "moment-timezone": "^0.5.45", "node-fetch": "^3.3.0", "node-schedule": "^2.1.1", "sqlite3": "^5.1.6", diff --git a/src/service/eliteEarlyBirdService.test.ts b/src/service/eliteEarlyBirdService.test.ts index f591ea6..f880805 100644 --- a/src/service/eliteEarlyBirdService.test.ts +++ b/src/service/eliteEarlyBirdService.test.ts @@ -1,92 +1,75 @@ import { expect, test } from '@jest/globals' import { parse } from './eliteEarlyBirdService' +import moment = require('moment-timezone') test('full time - at 13:37', async () => { - const now = new Date() - const midnight = new Date(now.getFullYear(), now.getMonth(), now.getDate(), 0, 0, 0, 0).getTime() const result = parse('13:37:37.137') expect(result).toBeDefined() if (result) { - expect(result - midnight).toBe(13 * 60 * 60 * 1000 + 37 * 60 * 1000 + 37 * 1000 + 137) + expect(result).toBe(moment.tz('13:37:37.137', 'hh:mm:ss.SSS', 'Europe/Berlin').valueOf()) } }) test('full time - early morning', async () => { - const now = new Date() - const midnight = new Date(now.getFullYear(), now.getMonth(), now.getDate(), 0, 0, 0, 0).getTime() const result = parse('2:37:37.137') expect(result).toBeDefined() if (result) { - expect(result - midnight).toBe(2 * 60 * 60 * 1000 + 37 * 60 * 1000 + 37 * 1000 + 137) + expect(result).toBe(moment.tz('02:37:37.137', 'hh:mm:ss.SSS', 'Europe/Berlin').valueOf()) } }) test('full time - early morning - single digits', async () => { - const now = new Date() - const midnight = new Date(now.getFullYear(), now.getMonth(), now.getDate(), 0, 0, 0, 0).getTime() const result = parse('2:02:02.1') expect(result).toBeDefined() if (result) { - expect(result - midnight).toBe(2 * 60 * 60 * 1000 + 2 * 60 * 1000 + 2 * 1000 + 100) + expect(result).toBe(moment.tz('02:02:02.100', 'hh:mm:ss.SSS', 'Europe/Berlin').valueOf()) } }) test('time without millis - early morning - single digits', async () => { - const now = new Date() - const midnight = new Date(now.getFullYear(), now.getMonth(), now.getDate(), 0, 0, 0, 0).getTime() const result = parse('2:02:02') expect(result).toBeDefined() if (result) { - expect(result - midnight).toBe(2 * 60 * 60 * 1000 + 2 * 60 * 1000 + 2 * 1000) + expect(result).toBe(moment.tz('02:02:02', 'hh:mm:ss', 'Europe/Berlin').valueOf()) } }) test('time without hour - single digits', async () => { - const now = new Date() - const midnight = new Date(now.getFullYear(), now.getMonth(), now.getDate(), 0, 0, 0, 0).getTime() const result = parse('2:02') expect(result).toBeDefined() if (result) { - expect(result - midnight).toBe(13 * 60 * 60 * 1000 + 2 * 60 * 1000 + 2 * 1000) + expect(result).toBe(moment.tz('13:02:02', 'hh:mm:ss', 'Europe/Berlin').valueOf()) } }) test('time just in seconcs', async () => { - const now = new Date() - const midnight = new Date(now.getFullYear(), now.getMonth(), now.getDate(), 0, 0, 0, 0).getTime() const result = parse('37') expect(result).toBeDefined() if (result) { - expect(result - midnight).toBe(13 * 60 * 60 * 1000 + 37 * 60 * 1000 + 37 * 1000) + expect(result).toBe(moment.tz('13:37:37', 'hh:mm:ss', 'Europe/Berlin').valueOf()) } }) test('time just in seconcs and millis(3 digit pending 0)', async () => { - const now = new Date() - const midnight = new Date(now.getFullYear(), now.getMonth(), now.getDate(), 0, 0, 0, 0).getTime() const result = parse('3.370') expect(result).toBeDefined() if (result) { - expect(result - midnight).toBe(13 * 60 * 60 * 1000 + 37 * 60 * 1000 + 3 * 1000 + 370) + expect(result).toBe(moment.tz('13:37:03.370', 'hh:mm:ss.SSS', 'Europe/Berlin').valueOf()) } }) test('time just in seconcs and millis(2 digits)', async () => { - const now = new Date() - const midnight = new Date(now.getFullYear(), now.getMonth(), now.getDate(), 0, 0, 0, 0).getTime() const result = parse('3.37') expect(result).toBeDefined() if (result) { - expect(result - midnight).toBe(13 * 60 * 60 * 1000 + 37 * 60 * 1000 + 3 * 1000 + 370) + expect(result).toBe(moment.tz('13:37:03.37', 'hh:mm:ss.SS', 'Europe/Berlin').valueOf()) } }) test('time just in seconcs and millis(3 digits, leading 0)', async () => { - const now = new Date() - const midnight = new Date(now.getFullYear(), now.getMonth(), now.getDate(), 0, 0, 0, 0).getTime() const result = parse('3.037') expect(result).toBeDefined() if (result) { - expect(result - midnight).toBe(13 * 60 * 60 * 1000 + 37 * 60 * 1000 + 3 * 1000 + 37) + expect(result).toBe(moment.tz('13:37:03.037', 'hh:mm:ss.SSS', 'Europe/Berlin').valueOf()) } }) diff --git a/src/service/eliteEarlyBirdService.ts b/src/service/eliteEarlyBirdService.ts index 303cf5c..72f22bf 100644 --- a/src/service/eliteEarlyBirdService.ts +++ b/src/service/eliteEarlyBirdService.ts @@ -1,91 +1,55 @@ +import moment from "moment-timezone" +/** + * Converts a time string in German format to UTC time in millis since epoc + * + * @param dateToParse must be a string to parse in German format for the German timezone, e.g. 13:37:37.137 + * @returns time in UTC in millis since epoc e.g. 1710419768333 for 13.03.2024 23:05 + */ export function parse(dateToParse: string | number | boolean): undefined | number { if (typeof dateToParse !== 'string') { return undefined } - const now = new Date() - const midnight = new Date(now.getFullYear(), now.getMonth(), now.getDate(), 0, 0, 0, 0).getTime() if (/^\d{1,2}:\d{1,2}:\d{1,2}\.\d{1,3}$/g.test(dateToParse)) { - const splitByColon = dateToParse.split(':') - if (splitByColon.length !== 3) { - return undefined - } - const hours = parseInt(splitByColon[0]) - const minutes = parseInt(splitByColon[1]) - const seconds = parseFloat(splitByColon[2]) - if (hours < 0 || hours > 23) { - return undefined - } - if (minutes < 0 || minutes > 59) { - return undefined - } - if (seconds < 0 || seconds >= 60) { - return undefined - } - return midnight + (seconds * 1000) + (minutes * 60 * 1000) + (hours * 60 * 60 * 1000) + return moment.tz(dateToParse, 'hh:mm:ss.SSS', 'Europe/Berlin').valueOf() } if (/^\d{1,2}:\d{1,2}:\d{1,2}$/g.test(dateToParse)) { - const splitByColon = dateToParse.split(':') - if (splitByColon.length !== 3) { - return undefined - } - const hours = parseInt(splitByColon[0]) - const minutes = parseInt(splitByColon[1]) - const seconds = parseInt(splitByColon[2]) - if (hours < 0 || hours > 23) { - return undefined - } - if (minutes < 0 || minutes > 59) { - return undefined - } - if (seconds < 0 || seconds > 59) { - return undefined - } - return midnight + (seconds * 1000) + (minutes * 60 * 1000) + (hours * 60 * 60 * 1000) + return moment.tz(`${dateToParse}.000`, 'hh:mm:ss.SSS', 'Europe/Berlin').valueOf() } if (/^\d{1,2}:\d{1,2}$/g.test(dateToParse)) { - const splitByColon = dateToParse.split(':') - if (splitByColon.length !== 2) { - return undefined - } - const minutes = parseInt(splitByColon[0]) - const seconds = parseInt(splitByColon[1]) - if (minutes < 0 || minutes > 59) { - return undefined - } - if (seconds < 0 || seconds > 59) { - return undefined - } - return midnight + (seconds * 1000) + (minutes * 60 * 1000) + (13 * 60 * 60 * 1000) + return moment.tz(`13:${dateToParse}.000`, 'hh:mm:ss.SSS', 'Europe/Berlin').valueOf() } if (/^\d{1,2}\.\d{1,3}$/g.test(dateToParse)) { - const seconds = parseFloat(dateToParse) - if (seconds < 0 || seconds >= 60) { - return undefined - } - return midnight + (seconds * 1000) + (37 * 60 * 1000) + (13 * 60 * 60 * 1000) + return moment.tz(`13:37:${dateToParse}`, 'hh:mm:ss.SSS', 'Europe/Berlin').valueOf() } if (/^\d{1,2}$/g.test(dateToParse)) { - const seconds = parseInt(dateToParse) - if (seconds < 0 || seconds > 59) { - return undefined - } - return midnight + seconds * 1000 + (37 * 60 * 1000) + (13 * 60 * 60 * 1000) + return moment.tz(`13:37:${dateToParse}.000`, 'hh:mm:ss.SSS', 'Europe/Berlin').valueOf() } return undefined } +/** + * Add the penalty time to the playTime (maybe in UTC or any other timezone, so result will be in the same timezone) + * + * @param playTime time in millis since epoc e.g. 1710419768333 for 13.03.2024 23:05 + * @returns the valid starting time in millis since epoc e.g. 1710419768333 for 13.03.2024 23:05 + */ export function calcValidFrom(playTime: number): number { - const now = new Date() + if (playTime < 32472190800) { + // playTime is in seconds (and less than 1.1.2999) + playTime = playTime * 1000 + } + const now = new Date(Date.now()) // now in UTC date + const berlinDate = new Date(now.toLocaleString('en-US', { timeZone: 'Europe/Berlin' })) let offset = 999 // rules: Mitternacht tippt sind es 65s, wenn man um 8 Uhr tippt 30s, um 12 Uhr -> 7s, 13 Uhr -> 3s, ab 13:37 dann 0s - if (now.getHours() >= 0 && now.getHours() <= 7) { + if (berlinDate.getHours() >= 0 && berlinDate.getHours() <= 7) { offset = 65 - } else if (now.getHours() >= 8 && now.getHours() <= 11) { + } else if (berlinDate.getHours() >= 8 && berlinDate.getHours() <= 11) { offset = 30 - } else if (now.getHours() === 12) { + } else if (berlinDate.getHours() === 12) { offset = 7 - } else if (now.getHours() === 13) { + } else if (berlinDate.getHours() === 13) { offset = 3 } return playTime + offset * 1000