diff --git a/package-lock.json b/package-lock.json index 55d77a3b..326deff6 100644 --- a/package-lock.json +++ b/package-lock.json @@ -15,6 +15,7 @@ "@vueuse/core": "^9.13.0", "@vueuse/nuxt": "^9.13.0", "csv": "^6.2.7", + "date-fns-tz": "^3.1.3", "floating-vue": "^2.0.0-beta.20", "husky": "^8.0.3", "jiti": "^1.18.2", @@ -6369,6 +6370,26 @@ "node": ">=0.10" } }, + "node_modules/date-fns": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-3.6.0.tgz", + "integrity": "sha512-fRHTG8g/Gif+kSh50gaGEdToemgfj74aRX3swtiouboip5JDLAyDE9F11nHMIcvOaXeOC6D7SpNhi7uFyB7Uww==", + "license": "MIT", + "peer": true, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/kossnocorp" + } + }, + "node_modules/date-fns-tz": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/date-fns-tz/-/date-fns-tz-3.1.3.tgz", + "integrity": "sha512-ZfbMu+nbzW0mEzC8VZrLiSWvUIaI3aRHeq33mTe7Y38UctKukgqPR4nTDwcwS4d64Gf8GghnVsroBuMY3eiTeA==", + "license": "MIT", + "peerDependencies": { + "date-fns": "^3.0.0" + } + }, "node_modules/dayjs": { "version": "1.11.9", "resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.9.tgz", diff --git a/package.json b/package.json index 8661bf06..85464e7c 100644 --- a/package.json +++ b/package.json @@ -31,6 +31,7 @@ "@vueuse/core": "^9.13.0", "@vueuse/nuxt": "^9.13.0", "csv": "^6.2.7", + "date-fns-tz": "^3.1.3", "floating-vue": "^2.0.0-beta.20", "husky": "^8.0.3", "jiti": "^1.18.2", diff --git a/src/server/api/consume-opening-hours.ts b/src/server/api/consume-opening-hours.ts index 5acf894e..31e8cdb1 100644 --- a/src/server/api/consume-opening-hours.ts +++ b/src/server/api/consume-opening-hours.ts @@ -1,8 +1,11 @@ +import { fromZonedTime } from 'date-fns-tz'; import { Client } from '@microsoft/microsoft-graph-client'; import { ClientSecretCredential } from '@azure/identity'; import { TokenCredentialAuthenticationProvider } from '@microsoft/microsoft-graph-client/authProviders/azureTokenCredentials/index.js'; import { serverSupabaseServiceRole } from '#supabase/server'; +const timezone = 'Europe/Amsterdam'; + const { internalSecret, datoApiToken, microsoftGraph } = useRuntimeConfig(); const credential = new ClientSecretCredential( @@ -18,7 +21,7 @@ const authProvider = new TokenCredentialAuthenticationProvider(credential, { const graphClient = Client.initWithMiddleware({ authProvider: authProvider, fetchOptions: { - headers: { 'Prefer': 'outlook.timezone="Europe/Amsterdam"' }, + headers: { 'Prefer': `outlook.timezone="${timezone}"` }, }, }); @@ -83,15 +86,18 @@ export default defineEventHandler(async (event) => { }&$select=subject,start,end` ) .get() - .then((calendarView) => ({ - number: building.number, - openEvents: calendarView.value - .filter((event: CalendarEvent) => event.subject === 'Open') - .map((event: CalendarEvent) => ({ - start: new Date(event.start.dateTime).toISOString(), - end: new Date(event.end.dateTime).toISOString(), - })), - })) + .then((calendarView) => { + console.info(`Fetched opening hours of ${buildingsOpeningDates.length} buildings`); + return { + number: building.number, + openEvents: calendarView.value + .filter((event: CalendarEvent) => event.subject === 'Open') + .map((event: CalendarEvent) => ({ + start: fromZonedTime(event.start.dateTime, timezone).toISOString(), + end: fromZonedTime(event.end.dateTime, timezone).toISOString(), + })), + } + }) .catch((error) => { console.warn( `Failed to fetch data for building ${building.number}:`,