Files
formbricks/apps/web/lib/time.ts
2026-03-23 07:23:07 +00:00

89 lines
2.8 KiB
TypeScript

import { type Locale, formatDistance } from "date-fns";
import { de, enUS, es, fr, hu, ja, nl, pt, ptBR, ro, ru, sv, zhCN, zhTW } from "date-fns/locale";
import { TUserLocale } from "@formbricks/types/user";
import { formatDateForDisplay } from "./utils/datetime";
const DEFAULT_LOCALE: TUserLocale = "en-US";
const TIME_SINCE_LOCALES: Record<TUserLocale, Locale> = {
"de-DE": de,
"en-US": enUS,
"es-ES": es,
"fr-FR": fr,
"hu-HU": hu,
"ja-JP": ja,
"nl-NL": nl,
"pt-BR": ptBR,
"pt-PT": pt,
"ro-RO": ro,
"ru-RU": ru,
"sv-SE": sv,
"zh-Hans-CN": zhCN,
"zh-Hant-TW": zhTW,
};
const isUserLocale = (locale: string): locale is TUserLocale => Object.hasOwn(TIME_SINCE_LOCALES, locale);
/** Maps locale strings to date-fns locales and falls back to English for unsupported inputs. */
const getLocaleForTimeSince = (locale: string): Locale =>
isUserLocale(locale) ? TIME_SINCE_LOCALES[locale] : enUS;
export const timeSince = (dateString: string, locale: string = DEFAULT_LOCALE) => {
const date = new Date(dateString);
return formatDistance(date, new Date(), {
addSuffix: true,
locale: getLocaleForTimeSince(locale),
});
};
export const timeSinceDate = (date: Date, locale: string = DEFAULT_LOCALE) => {
return formatDistance(date, new Date(), {
addSuffix: true,
locale: getLocaleForTimeSince(locale),
});
};
export const formatDate = (date: Date, locale: string = DEFAULT_LOCALE) => {
return formatDateForDisplay(date, locale, {
year: "numeric",
month: "long",
day: "numeric",
});
};
export const getTodaysDateTimeFormatted = (seperator: string) => {
const date = new Date();
const formattedDate = date.toISOString().split("T")[0].split("-").join(seperator);
const formattedTime = date.toTimeString().split(" ")[0].split(":").join(seperator);
return [formattedDate, formattedTime].join(seperator);
};
export const convertDatesInObject = <T>(obj: T, keysToIgnore?: Set<string>): T => {
if (obj === null || typeof obj !== "object") {
return obj; // Return if obj is not an object
}
if (Array.isArray(obj)) {
// Handle arrays by mapping each element through the function
return obj.map((item) => convertDatesInObject(item, keysToIgnore)) as unknown as T;
}
const newObj: Record<string, unknown> = {};
for (const key in obj) {
if (keysToIgnore?.has(key)) {
newObj[key] = obj[key];
continue;
}
if (
(key === "createdAt" || key === "updatedAt") &&
typeof obj[key] === "string" &&
!isNaN(Date.parse(obj[key] as unknown as string))
) {
newObj[key] = new Date(obj[key] as unknown as string);
} else if (typeof obj[key] === "object" && obj[key] !== null) {
newObj[key] = convertDatesInObject(obj[key], keysToIgnore);
} else {
newObj[key] = obj[key];
}
}
return newObj as T;
};