diff --git a/web/src/pages/skill-detail.tsx b/web/src/pages/skill-detail.tsx index 99f5c5a3..cd539d1d 100644 --- a/web/src/pages/skill-detail.tsx +++ b/web/src/pages/skill-detail.tsx @@ -9,6 +9,7 @@ import { RatingInput } from '@/features/social/rating-input' import { StarButton } from '@/features/social/star-button' import { useAuth } from '@/features/auth/use-auth' import { adminApi } from '@/api/client' +import { formatLocalDateTime } from '@/shared/lib/date-time' import { NamespaceBadge } from '@/shared/components/namespace-badge' import { Tabs, TabsList, TabsTrigger, TabsContent } from '@/shared/ui/tabs' import { Button } from '@/shared/ui/button' @@ -191,7 +192,7 @@ export function SkillDetailPage() { - {new Date(version.publishedAt).toLocaleDateString(i18n.language)} + {formatLocalDateTime(version.publishedAt, i18n.language)} {version.changelog && ( diff --git a/web/src/shared/lib/date-time.ts b/web/src/shared/lib/date-time.ts new file mode 100644 index 00000000..ff229610 --- /dev/null +++ b/web/src/shared/lib/date-time.ts @@ -0,0 +1,21 @@ +function parseServerDateTime(value: string): Date { + if (/[zZ]$|[+-]\d{2}:\d{2}$/.test(value)) { + return new Date(value) + } + + const [datePart, timePart = '00:00:00'] = value.split('T') + const [year, month, day] = datePart.split('-').map(Number) + const [rawTime, fractional = ''] = timePart.split('.') + const [hours = 0, minutes = 0, seconds = 0] = rawTime.split(':').map(Number) + const milliseconds = Number((fractional + '000').slice(0, 3)) + + return new Date(year, (month || 1) - 1, day || 1, hours, minutes, seconds, milliseconds) +} + +export function formatLocalDateTime( + value: string, + locale: string, + options: Intl.DateTimeFormatOptions = { dateStyle: 'medium', timeStyle: 'short' }, +) { + return new Intl.DateTimeFormat(locale, options).format(parseServerDateTime(value)) +}