diff --git a/src/components/Proposal/ProposalResponseMatrix.vue b/src/components/Proposal/ProposalResponseMatrix.vue index fff643fb4f..94adba676c 100644 --- a/src/components/Proposal/ProposalResponseMatrix.vue +++ b/src/components/Proposal/ProposalResponseMatrix.vue @@ -201,7 +201,7 @@ export default { const groups = {} dates.forEach((d) => { // Apply timezone offset for grouping by day - const offset = getTimezoneOffset(d.date.toISOString(), this.timezoneId) + const offset = getTimezoneOffset(d.date, this.timezoneId) const key = moment(d.date).utcOffset(offset).format('YYYY-MM-DD') if (!groups[key]) { groups[key] = [] @@ -209,7 +209,7 @@ export default { groups[key].push(d) }) return Object.entries(groups).map(([key, grp]: [string, ProposalDate[]]) => { - const offset = getTimezoneOffset(grp[0].date.toISOString(), this.timezoneId) + const offset = getTimezoneOffset(grp[0].date, this.timezoneId) return { key, label: moment(grp[0].date).utcOffset(offset).format('dddd, MMMM Do'), @@ -230,7 +230,7 @@ export default { t, dateTimeSpan(date) { - const offset = getTimezoneOffset(date.toISOString(), this.timezoneId) + const offset = getTimezoneOffset(date, this.timezoneId) const startDate = moment(date).utcOffset(offset) const endDate = moment(date).utcOffset(offset).add(this.proposal.duration, 'minutes') @@ -255,7 +255,7 @@ export default { return '' } // Apply timezone offset and format very compact: "7/8 2PM" - const offset = getTimezoneOffset(date.toISOString(), this.timezoneId) + const offset = getTimezoneOffset(date, this.timezoneId) const adjustedDate = moment(date).utcOffset(offset) return adjustedDate.format('M/D LT').replace(':00', '').replace(' ', ' ') }, diff --git a/src/services/timezoneOffsetService.js b/src/services/timezoneOffsetService.js deleted file mode 100644 index 44f8d1e64a..0000000000 --- a/src/services/timezoneOffsetService.js +++ /dev/null @@ -1,52 +0,0 @@ -/** - * SPDX-FileCopyrightText: 2026 Nextcloud GmbH and Nextcloud contributors - * SPDX-License-Identifier: AGPL-3.0-or-later - */ - -const dtfCache = new Map() - -export function getTimezoneOffset(proposalDate, timezoneId) { - try { - const date = new Date(proposalDate) - if (isNaN(date)) { - return null - } - - let dtf = dtfCache.get(timezoneId) - if (!dtf) { - dtf = new Intl.DateTimeFormat('en-US', { - timeZone: timezoneId, - hour12: false, - year: 'numeric', - month: '2-digit', - day: '2-digit', - hour: '2-digit', - minute: '2-digit', - second: '2-digit', - }) - dtfCache.set(timezoneId, dtf) - } - - const parts = dtf.formatToParts(date) - const values = {} - - for (const { type, value } of parts) { - if (type !== 'literal') { - values[type] = value - } - } - - const asUTC = Date.UTC( - Number(values.year), - Number(values.month) - 1, - Number(values.day), - Number(values.hour), - Number(values.minute), - Number(values.second), - ) - - return Math.floor((asUTC - date.getTime()) / 60000) - } catch { - return null - } -} diff --git a/src/services/timezoneOffsetService.ts b/src/services/timezoneOffsetService.ts new file mode 100644 index 0000000000..c60bfb9968 --- /dev/null +++ b/src/services/timezoneOffsetService.ts @@ -0,0 +1,42 @@ +/** + * SPDX-FileCopyrightText: 2026 Nextcloud GmbH and Nextcloud contributors + * SPDX-License-Identifier: AGPL-3.0-or-later + */ +export function getTimezoneOffset(proposalDate: Date, timezoneId: string): number { + let timezoneOffset = 0 + + try { + const dtf = new Intl.DateTimeFormat('en-US', { + timeZone: timezoneId, + hour12: false, + year: 'numeric', + month: '2-digit', + day: '2-digit', + hour: '2-digit', + minute: '2-digit', + second: '2-digit', + }) + + const parts = dtf.formatToParts(proposalDate) + + const values: Record = {} + parts.forEach(({ type, value }) => { + if (type !== 'literal') values[type] = value + }) + + const asUTC = Date.UTC( + Number(values.year), + Number(values.month) - 1, + Number(values.day), + Number(values.hour), + Number(values.minute), + Number(values.second), + ) + + timezoneOffset = Math.round((asUTC - proposalDate.getTime()) / 60000) + } catch (e) { + timezoneOffset = 0 + } + + return timezoneOffset +}