Add functionality for time-less date formatting

This commit is contained in:
Sam Becker 2025-01-22 19:31:47 -06:00
parent b02dc50b88
commit 59399bd703
3 changed files with 64 additions and 33 deletions

View File

@ -10,11 +10,13 @@ export default function ResponsiveDate({
className,
titleLabel,
timezone: timezoneFromProps,
hideTime,
}: {
date: Date
className?: string
titleLabel?: string
timezone?: Timezone
hideTime?: boolean,
}) {
const [timezone, setTimezone] = useState(timezoneFromProps);
@ -24,23 +26,30 @@ export default function ResponsiveDate({
}
}, [timezoneFromProps]);
const showPlaceholderContent = timezone === undefined;
const showPlaceholder = timezone === undefined;
const titleDateFormatted = formatDate(date, undefined, timezone)
const titleDateFormatted = formatDate({ date, timezone })
.toLocaleUpperCase();
const title = titleLabel
? `${titleLabel}: ${titleDateFormatted}`
: titleDateFormatted;
const contentClass = showPlaceholderContent && 'opacity-0 select-none';
const contentClass = showPlaceholder && 'opacity-0 select-none';
const formatDateProps = {
date,
timezone,
showPlaceholder,
hideTime,
} as const;
return (
<span
title={showPlaceholderContent ? 'LOADING LOCAL TIME' : title}
title={showPlaceholder ? 'LOADING LOCAL TIME' : title}
className={clsx(
'uppercase rounded-md transition-colors',
showPlaceholderContent && 'bg-dim',
showPlaceholder && 'bg-dim',
className,
)}
>
@ -49,20 +58,20 @@ export default function ResponsiveDate({
className={clsx('xs:hidden', contentClass)}
aria-hidden
>
{formatDate(date, 'short', timezone, showPlaceholderContent)}
{formatDate({ ...formatDateProps, length: 'short' })}
</span>
{/* Medium */}
<span
className={clsx('hidden xs:inline-block sm:hidden', contentClass)}
aria-hidden
>
{formatDate(date, 'medium', timezone,showPlaceholderContent)}
{formatDate({ ...formatDateProps, length: 'medium' })}
</span>
{/* Large */}
<span
className={clsx('hidden sm:inline-block', contentClass)}
>
{formatDate(date, undefined, timezone, showPlaceholderContent)}
{formatDate(formatDateProps)}
</span>
</span>
);

View File

@ -212,7 +212,10 @@ export const titleForPhoto = (
if (photo.title) {
return photo.title;
} else if (preferDateOverUntitled && (photo.takenAt || photo.createdAt)) {
return formatDate(photo.takenAt || photo.createdAt, 'tiny');
return formatDate({
date: photo.takenAt || photo.createdAt,
length: 'tiny',
});
} else {
return 'Untitled';
}

View File

@ -23,38 +23,57 @@ type AmbiguousTimestamp = number | string;
type Length = 'tiny' | 'short' | 'medium' | 'long';
export const formatDate = (
export const formatDate = ({
date,
length = 'long',
timezone,
hideTime,
showPlaceholder,
}: {
date: Date,
length: Length = 'long',
length?: Length,
timezone?: Timezone,
hideTime?: boolean,
showPlaceholder?: boolean,
) => {
switch (length) {
case 'tiny': return showPlaceholder
? DATE_STRING_FORMAT_TINY_PLACEHOLDER
: timezone
? formatInTimeZone(date, timezone, DATE_STRING_FORMAT_TINY)
: format(date, DATE_STRING_FORMAT_TINY);
case 'short': return showPlaceholder
? DATE_STRING_FORMAT_SHORT_PLACEHOLDER
: timezone
? formatInTimeZone(date, timezone, DATE_STRING_FORMAT_SHORT)
: format(date, DATE_STRING_FORMAT_SHORT);
case 'medium': return showPlaceholder
? DATE_STRING_FORMAT_MEDIUM_PLACEHOLDER
: timezone
? formatInTimeZone(date, timezone, DATE_STRING_FORMAT_MEDIUM)
: format(date, DATE_STRING_FORMAT_MEDIUM);
default: return showPlaceholder
}) => {
let formatString = !hideTime
? DATE_STRING_FORMAT_LONG
: DATE_STRING_FORMAT_SHORT;
let placeholderString = !hideTime
? DATE_STRING_FORMAT_LONG_PLACEHOLDER
: timezone
? formatInTimeZone(date, timezone, DATE_STRING_FORMAT_LONG)
: format(date, DATE_STRING_FORMAT_LONG);
: DATE_STRING_FORMAT_SHORT_PLACEHOLDER;
switch (length) {
case 'tiny':
formatString = DATE_STRING_FORMAT_TINY;
placeholderString = DATE_STRING_FORMAT_TINY_PLACEHOLDER;
break;
case 'short':
formatString = DATE_STRING_FORMAT_SHORT;
placeholderString = DATE_STRING_FORMAT_SHORT_PLACEHOLDER;
break;
case 'medium':
formatString = !hideTime
? DATE_STRING_FORMAT_MEDIUM
: DATE_STRING_FORMAT_TINY;
placeholderString = !hideTime
? DATE_STRING_FORMAT_MEDIUM_PLACEHOLDER
: DATE_STRING_FORMAT_TINY_PLACEHOLDER;
break;
}
return showPlaceholder
? placeholderString
: timezone
? formatInTimeZone(date, timezone, formatString)
: format(date, formatString);
};
export const formatDateFromPostgresString = (date: string, length?: Length) =>
formatDate(parse(date, DATE_STRING_FORMAT_POSTGRES, new Date()), length);
formatDate({
date: parse(date, DATE_STRING_FORMAT_POSTGRES, new Date()),
length,
});
export const formatDateForPostgres = (date: Date) =>
date.toISOString().replace(