1 import { format as formatDate, fromUnixTime, getUnixTime, isSameDay } from 'date-fns';
3 import { serverTime } from '@proton/crypto';
5 export type DateFnsOptions = Parameters<typeof formatDate>[2];
7 export type Options = DateFnsOptions & {
9 * Date format if `unixTime` argument is today. If false then force `format`. 'p' by default.
11 sameDayFormat?: string | false;
13 * Date format in general case. 'PP' by default.
19 * Convert UNIX timestamp into a readable time. The format of the readable time is:
20 * ** Hours and minutes if the UNIX timestamp is from the same day,
21 * ** Day, month and year otherwise
23 export const readableTime = (unixTime: number, options: Options = {}) => {
24 let { sameDayFormat, format, ...dateFnsOptions } = options;
25 sameDayFormat = sameDayFormat ?? 'p';
26 format = format ?? 'PP';
28 const date = fromUnixTime(unixTime);
30 if (sameDayFormat && isSameDay(date, Date.now())) {
31 return formatDate(date, sameDayFormat, dateFnsOptions);
34 return formatDate(date, format, dateFnsOptions);
37 export type OptionsWithIntl = {
39 * Locale code string, or an array of such strings like 'en' or 'en-US'.
41 localeCode?: string | string[];
43 * If true time will be shown in 12h format with AM/PM
47 * Intl format options.
49 intlOptions?: Intl.DateTimeFormatOptions;
51 * Intl options if readableTimeIntl `unixTime` argument is today.
53 sameDayIntlOptions?: Intl.DateTimeFormatOptions | false;
57 * Convert UNIX timestamp into a readable time with Intl.DateTimeFormat API. The format of the readable time is:
58 * ** Hours and minutes if the UNIX timestamp is from the same day,
59 * ** Day, month and year otherwise
60 * @param unixTime {number}
61 * @param {Object} options
62 * @param {Object} [options.intlOptions={month: 'short', day: 'numeric', year: 'numeric'}]
63 * @param {Object} [options.sameDayIntlOptions={month: 'short', day: 'numeric', year: 'numeric'}]
65 export const readableTimeIntl = (unixTime: number, options: OptionsWithIntl = {}) => {
66 let { sameDayIntlOptions, localeCode = 'en-US', hour12, intlOptions } = options;
67 // h12: 12:59 AM | h23: 00:59 (h24 would have produced: 24:59)
68 // We still want to let default Intl behavior if no hour12 params is pass, so we want to have undefined
69 const hourCycle = (hour12 === true && 'h12') || (hour12 === false && 'h23') || undefined;
71 const defaultIntlOptions: Intl.DateTimeFormatOptions = { month: 'short', day: 'numeric', year: 'numeric' };
72 intlOptions = intlOptions ?? defaultIntlOptions;
74 const defaultSameDayOptions: Intl.DateTimeFormatOptions = { hour: 'numeric', minute: 'numeric' };
75 sameDayIntlOptions = sameDayIntlOptions ?? defaultSameDayOptions;
77 const date = new Date(unixTime * 1000);
79 if (sameDayIntlOptions && isSameDay(date, Date.now())) {
80 return Intl.DateTimeFormat(localeCode, { hourCycle, ...sameDayIntlOptions }).format(date);
82 return Intl.DateTimeFormat(localeCode, { hourCycle, ...intlOptions }).format(date);
85 export const getCurrentUnixTimestamp = () => {
86 return getUnixTime(serverTime());