Refactor: centralize timezone utilities in src/utils/timezone.ts (#491)
Deduplicate resolveTimezone, resolveTimezoneId, convertEventDateTimeToISO, and getTimezoneOffset into a single canonical module, removing copies from EventApi, eventUtils, TimezoneSelector, EventUpdateModal, and calendarUtils. Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -1,7 +1,10 @@
|
||||
import { browserDefaultTimeZone } from "@/utils/timezone";
|
||||
import {
|
||||
browserDefaultTimeZone,
|
||||
getTimezoneOffset,
|
||||
resolveTimezone,
|
||||
} from "@/utils/timezone";
|
||||
import { TIMEZONES } from "@/utils/timezone-data";
|
||||
import { Button, Popover } from "@linagora/twake-mui";
|
||||
import moment from "moment";
|
||||
import { MouseEvent, useMemo, useState } from "react";
|
||||
import { useI18n } from "twake-i18n";
|
||||
import { TimezoneAutocomplete } from "../Timezone/TimezoneAutocomplete";
|
||||
@@ -99,28 +102,3 @@ export function useTimeZoneList() {
|
||||
return { zones, browserTz, getTimezoneOffset };
|
||||
}, []);
|
||||
}
|
||||
|
||||
export function resolveTimezone(tzName: string): string {
|
||||
if (TIMEZONES.zones[tzName]) {
|
||||
return tzName;
|
||||
}
|
||||
if (TIMEZONES.aliases[tzName]) {
|
||||
return TIMEZONES.aliases[tzName].aliasTo;
|
||||
}
|
||||
return tzName;
|
||||
}
|
||||
|
||||
export function getTimezoneOffset(
|
||||
tzName: string,
|
||||
date: Date = new Date()
|
||||
): string {
|
||||
const fmt = new Intl.DateTimeFormat(undefined, {
|
||||
timeZone: tzName,
|
||||
timeZoneName: "shortOffset",
|
||||
});
|
||||
|
||||
const currentDate = moment(date).isValid() ? date : new Date();
|
||||
const parts = fmt.formatToParts(currentDate);
|
||||
const offsetPart = parts.find((p) => p.type === "timeZoneName");
|
||||
return offsetPart?.value.replace("GMT", "UTC") ?? "";
|
||||
}
|
||||
|
||||
@@ -1,42 +1,15 @@
|
||||
import { detectDateTimeFormat } from "@/components/Event/utils/dateTimeHelpers";
|
||||
import { refreshSingularCalendar } from "@/components/Event/utils/eventUtils";
|
||||
import { Calendar } from "@/features/Calendars/CalendarTypes";
|
||||
import { getCalendarDetailAsync } from "@/features/Calendars/services";
|
||||
import { CalendarEvent } from "@/features/Events/EventsTypes";
|
||||
import { formatDateToYYYYMMDDTHHMMSS } from "@/utils/dateUtils";
|
||||
import { extractEventBaseUuid } from "@/utils/extractEventBaseUuid";
|
||||
import { convertEventDateTimeToISO } from "@/utils/timezone";
|
||||
import { SlotLabelContentArg } from "@fullcalendar/core";
|
||||
import { ThunkDispatch } from "@reduxjs/toolkit";
|
||||
import moment from "moment-timezone";
|
||||
import { useI18n } from "twake-i18n";
|
||||
|
||||
function convertEventDateTimeToISO(
|
||||
datetime: string,
|
||||
eventTimezone: string,
|
||||
isAllDay: boolean
|
||||
): string {
|
||||
if (!datetime || isAllDay) return datetime;
|
||||
|
||||
if (datetime.includes("Z") || datetime.match(/[+-]\d{2}:\d{2}$/)) {
|
||||
return datetime;
|
||||
}
|
||||
|
||||
const dateOnlyRegex = /^\d{4}-(0[1-9]|1[0-2])-(0[1-9]|[12]\d|3[01])$/;
|
||||
if (dateOnlyRegex.test(datetime)) {
|
||||
return datetime;
|
||||
}
|
||||
|
||||
const format = detectDateTimeFormat(datetime);
|
||||
const momentDate = moment.tz(datetime, format, eventTimezone);
|
||||
if (!momentDate.isValid()) {
|
||||
console.warn(
|
||||
`[convertEventDateTimeToISO] Invalid datetime: "${datetime}" with format "${format}" in timezone "${eventTimezone}"`
|
||||
);
|
||||
return datetime;
|
||||
}
|
||||
return momentDate.toISOString();
|
||||
}
|
||||
|
||||
export const updateSlotLabelVisibility = (
|
||||
currentTime: Date,
|
||||
slotLabel: SlotLabelContentArg,
|
||||
@@ -114,22 +87,18 @@ export const eventToFullCalendarFormat = (
|
||||
};
|
||||
|
||||
if (!isAllDay && e.start && eventTimezone) {
|
||||
const startISO = convertEventDateTimeToISO(
|
||||
e.start,
|
||||
eventTimezone,
|
||||
isAllDay
|
||||
);
|
||||
const startISO = convertEventDateTimeToISO(e.start, eventTimezone, {
|
||||
isAllDay,
|
||||
});
|
||||
if (startISO) {
|
||||
convertedEvent.start = startISO;
|
||||
}
|
||||
}
|
||||
|
||||
if (!isAllDay && e.end && eventTimezone) {
|
||||
const endISO = convertEventDateTimeToISO(
|
||||
e.end,
|
||||
eventTimezone,
|
||||
isAllDay
|
||||
);
|
||||
const endISO = convertEventDateTimeToISO(e.end, eventTimezone, {
|
||||
isAllDay,
|
||||
});
|
||||
if (endISO) {
|
||||
convertedEvent.end = endISO;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user