You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

107 lines
2.5 KiB

type DateTime = {
/** The date formatted as a string
* @example
* 'January 1, 2022'
* 'December 31, 2022'
*/
asString: string;
/** The date formatted as an ISO string
* @example
* '2022-01-01T00:00:00.000Z'
*/
asISOString: string;
/** The date formatted as a relative time string
* @example
* '2 days ago'
* '3 weeks ago'
*/
asRelativeTimeString: string;
/** A boolean indicating if the date is fresh, i.e. less than 4 days old */
isFresh: boolean;
};
const dateFormatter = new Intl.DateTimeFormat('en-US', {
month: 'long',
day: 'numeric',
year: 'numeric',
});
const relativeTimeFormatter = new Intl.RelativeTimeFormat('en-US', {
numeric: 'auto',
});
/**
* Formats a date string into a {@link DateTime} object.
* @example
* const dateTime = formatDateTime('2022-01-01');
* // dateTime = {
* // asString: 'January 1, 2022',
* // asISOString: '2022-01-01T00:00:00.000Z',
* // asRelativeTimeString: '2 days ago',
* // isFresh: true
* // }
*/
export function formatDateTime(dateString: string): DateTime {
const date = new Date(dateString);
if (isNaN(date.getTime())) {
return {
asString: 'Invalid Date',
asISOString: 'Invalid Date',
asRelativeTimeString: 'Invalid Date',
isFresh: false,
};
}
const { relativeTime, isFresh } = getRelativeTime(date);
return {
asString: dateFormatter.format(date),
asISOString: date.toISOString(),
asRelativeTimeString: relativeTime,
isFresh,
};
}
/**
* Formats a date into a relative time.
* @returns The relative time string and a boolean indicating if the date is fresh,
* i.e. less than 4 days old
* @example
* const { relativeTime, isFresh } = getRelativeTime(someDate);
* // relativeTime = '3 weeks ago'
* // isFresh = false
*/
function getRelativeTime(date: Date) {
const timeDiff = date.getTime() - new Date().getTime();
const days = Math.ceil(timeDiff / (1000 * 60 * 60 * 24));
if (days > -14) {
return {
relativeTime: relativeTimeFormatter.format(days, 'day'),
isFresh: days > -4,
};
}
const weeks = Math.floor(days / 7);
if (weeks > -8) {
return {
relativeTime: relativeTimeFormatter.format(weeks, 'week'),
isFresh: false,
};
}
const months = Math.floor(days / 30);
if (months > -12) {
return {
relativeTime: relativeTimeFormatter.format(months, 'month'),
isFresh: false,
};
}
const years = Math.floor(days / 365);
return {
relativeTime: relativeTimeFormatter.format(years, 'year'),
isFresh: false,
};
}