diff --git a/app/src/components/blog/BlogPostCard.tsx b/app/src/components/blog/BlogPostCard.tsx index 9029f9c5b..14fbc12dd 100644 --- a/app/src/components/blog/BlogPostCard.tsx +++ b/app/src/components/blog/BlogPostCard.tsx @@ -1,5 +1,6 @@ import { IconArrowRight } from '@tabler/icons-react'; import { Link } from 'react-router-dom'; +import { formatPostDate } from '@/components/home/blogPreviewUtils'; import { Text } from '@/components/ui'; import OptimisedImage from '@/components/ui/OptimisedImage'; import { locationLabels, topicLabels } from '@/data/posts/postTransformers'; @@ -16,11 +17,7 @@ export function BlogPostCard({ item, countryId }: BlogPostCardProps) { ? `/${item.countryId}/${item.slug}` : `/${countryId}/research/${item.slug}`; - const formattedDate = new Date(item.date).toLocaleDateString('en-US', { - year: 'numeric', - month: 'short', - day: 'numeric', - }); + const formattedDate = formatPostDate(item.date); const displayTags = item.tags .filter((tag) => topicLabels[tag] || locationLabels[tag]) diff --git a/app/src/components/home/blogPreviewUtils.ts b/app/src/components/home/blogPreviewUtils.ts index b0fabedd8..579da951c 100644 --- a/app/src/components/home/blogPreviewUtils.ts +++ b/app/src/components/home/blogPreviewUtils.ts @@ -10,12 +10,12 @@ export function getPostImageUrl(post: BlogPost): string { return `/assets/posts/${post.image}`; } -export function formatPostDate(dateStr: string): string { +export function formatPostDate(dateStr: string, month: 'short' | 'long' = 'short'): string { // Append T12:00:00 to date-only strings to avoid UTC midnight timezone shift const normalized = /^\d{4}-\d{2}-\d{2}$/.test(dateStr) ? `${dateStr}T12:00:00` : dateStr; return new Date(normalized).toLocaleDateString('en-US', { year: 'numeric', - month: 'short', + month, day: 'numeric', }); } diff --git a/app/src/pages/Blog.page.tsx b/app/src/pages/Blog.page.tsx index ce7dfd240..a12b25d68 100644 --- a/app/src/pages/Blog.page.tsx +++ b/app/src/pages/Blog.page.tsx @@ -11,6 +11,7 @@ import { blogSpacing } from '@/components/blog/blogStyles'; import { MarkdownFormatter } from '@/components/blog/MarkdownFormatter'; import { NotebookRenderer } from '@/components/blog/NotebookRenderer'; import { useDisplayCategory } from '@/components/blog/useDisplayCategory'; +import { formatPostDate } from '@/components/home/blogPreviewUtils'; import StaticPageLayout from '@/components/shared/static/StaticPageLayout'; import { Container, Spinner, Text } from '@/components/ui'; import OptimisedImage from '@/components/ui/OptimisedImage'; @@ -109,11 +110,7 @@ export default function BlogPage() { }, [post?.filename, isNotebook]); // Format date - const formattedDate = new Date(post.date).toLocaleDateString('en-US', { - year: 'numeric', - month: 'long', - day: 'numeric', - }); + const formattedDate = formatPostDate(post.date, 'long'); if (loading) { return ( diff --git a/app/src/tests/unit/components/home/blogPreviewUtils.test.ts b/app/src/tests/unit/components/home/blogPreviewUtils.test.ts index f66b0917c..74d765591 100644 --- a/app/src/tests/unit/components/home/blogPreviewUtils.test.ts +++ b/app/src/tests/unit/components/home/blogPreviewUtils.test.ts @@ -49,3 +49,21 @@ describe('formatPostDate', () => { expect(result).toBe('Jan 12, 2026'); }); }); + +describe('formatPostDate month style', () => { + test('given date-only string then long month reads as the same calendar day', () => { + // When + const result = formatPostDate('2026-09-15', 'long'); + + // Then + expect(result).toBe('September 15, 2026'); + }); + + test('given date-only string then short month is the default', () => { + // When + const result = formatPostDate('2026-09-15'); + + // Then + expect(result).toBe('Sep 15, 2026'); + }); +});