From 4864c283b76afad9fedcfb59c3a91f79888313c8 Mon Sep 17 00:00:00 2001 From: Bruno Bernardino Date: Thu, 21 Aug 2025 17:09:32 +0100 Subject: [PATCH] Fix timezone display issues with formatted dates Fixes #88 Also update Deno, hoping it might help with #87, but it's unlikely --- .dvmrc | 2 +- .env.sample | 1 + Dockerfile | 2 +- components/expenses/ListExpenses.tsx | 11 +++++++++-- components/expenses/MainExpenses.tsx | 13 ++++++++++++- components/files/ListFiles.tsx | 11 +++++++++-- components/files/ListPhotos.tsx | 11 +++++++++-- components/files/SearchFiles.tsx | 11 +++++++++-- docker-compose.yml | 2 +- islands/news/Articles.tsx | 9 ++++++++- islands/news/Feeds.tsx | 9 ++++++++- 11 files changed, 68 insertions(+), 14 deletions(-) diff --git a/.dvmrc b/.dvmrc index 8e8299d..79a6144 100644 --- a/.dvmrc +++ b/.dvmrc @@ -1 +1 @@ -2.4.2 +2.4.4 diff --git a/.env.sample b/.env.sample index 0a501ae..6fd4106 100644 --- a/.env.sample +++ b/.env.sample @@ -1,3 +1,4 @@ +TZ="UTC" # optional, forces the server timezone to be UTC, which is the default, anyway PORT=8000 POSTGRESQL_HOST="postgresql" # docker container name or external hostname/IP diff --git a/Dockerfile b/Dockerfile index 7253f75..34314d0 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,4 +1,4 @@ -FROM denoland/deno:ubuntu-2.4.2 +FROM denoland/deno:ubuntu-2.4.4 EXPOSE 8000 diff --git a/components/expenses/ListExpenses.tsx b/components/expenses/ListExpenses.tsx index 8b251a3..c9069e2 100644 --- a/components/expenses/ListExpenses.tsx +++ b/components/expenses/ListExpenses.tsx @@ -13,10 +13,17 @@ export default function ListExpenses( onClickEditExpense, }: ListExpensesProps, ) { - const dateFormat = new Intl.DateTimeFormat('en-US', { + const dateFormatOptions: Intl.DateTimeFormatOptions = { month: 'short', day: 'numeric', - }); + }; + + // Force timeZone to UTC for the server rendering + if (typeof window === 'undefined') { + dateFormatOptions.timeZone = 'UTC'; + } + + const dateFormat = new Intl.DateTimeFormat('en-US', dateFormatOptions); return (
diff --git a/components/expenses/MainExpenses.tsx b/components/expenses/MainExpenses.tsx index 7e369e2..09cb488 100644 --- a/components/expenses/MainExpenses.tsx +++ b/components/expenses/MainExpenses.tsx @@ -63,7 +63,18 @@ export default function MainExpenses({ initialBudgets, initialExpenses, initialM const shouldResetBudgetModal = useSignal(false); const searchTimeout = useSignal>(0); - const dateFormat = new Intl.DateTimeFormat('en-GB', { year: 'numeric', month: 'long' }); + const dateFormatOptions: Intl.DateTimeFormatOptions = { + year: 'numeric', + month: 'long', + }; + + // Force timeZone to UTC for the server rendering + if (typeof window === 'undefined') { + dateFormatOptions.timeZone = 'UTC'; + } + + const dateFormat = new Intl.DateTimeFormat('en-GB', dateFormatOptions); + const thisMonth = new Date().toISOString().substring(0, 7); function onClickImportFile() { diff --git a/components/files/ListFiles.tsx b/components/files/ListFiles.tsx index 3c26f68..6bbfa5a 100644 --- a/components/files/ListFiles.tsx +++ b/components/files/ListFiles.tsx @@ -44,14 +44,21 @@ export default function ListFiles( fileShareId, }: ListFilesProps, ) { - const dateFormat = new Intl.DateTimeFormat('en-GB', { + const dateFormatOptions: Intl.DateTimeFormatOptions = { year: 'numeric', month: 'long', day: 'numeric', hour12: false, hour: '2-digit', minute: '2-digit', - }); + }; + + // Force timeZone to UTC for the server rendering + if (typeof window === 'undefined') { + dateFormatOptions.timeZone = 'UTC'; + } + + const dateFormat = new Intl.DateTimeFormat('en-GB', dateFormatOptions); let routePath = fileShareId ? `file-share/${fileShareId}` : 'files'; let itemSingleLabel = 'file'; diff --git a/components/files/ListPhotos.tsx b/components/files/ListPhotos.tsx index 9a2cb8a..25ba052 100644 --- a/components/files/ListPhotos.tsx +++ b/components/files/ListPhotos.tsx @@ -26,14 +26,21 @@ export default function ListFiles( isShowingNotes, }: ListFilesProps, ) { - const dateFormat = new Intl.DateTimeFormat('en-GB', { + const dateFormatOptions: Intl.DateTimeFormatOptions = { year: 'numeric', month: 'long', day: 'numeric', hour12: false, hour: '2-digit', minute: '2-digit', - }); + }; + + // Force timeZone to UTC for the server rendering + if (typeof window === 'undefined') { + dateFormatOptions.timeZone = 'UTC'; + } + + const dateFormat = new Intl.DateTimeFormat('en-GB', dateFormatOptions); const routePath = isShowingNotes ? 'notes' : 'files'; const itemSingleLabel = isShowingNotes ? 'note' : 'file'; diff --git a/components/files/SearchFiles.tsx b/components/files/SearchFiles.tsx index 195044c..fffd117 100644 --- a/components/files/SearchFiles.tsx +++ b/components/files/SearchFiles.tsx @@ -13,13 +13,20 @@ export default function SearchFiles({}: SearchFilesProps) { const searchTimeout = useSignal>(0); const closeTimeout = useSignal>(0); - const dateFormat = new Intl.DateTimeFormat('en-GB', { + const dateFormatOptions: Intl.DateTimeFormatOptions = { year: 'numeric', month: 'long', day: 'numeric', hour: 'numeric', minute: '2-digit', - }); + }; + + // Force timeZone to UTC for the server rendering + if (typeof window === 'undefined') { + dateFormatOptions.timeZone = 'UTC'; + } + + const dateFormat = new Intl.DateTimeFormat('en-GB', dateFormatOptions); function searchFiles(searchTerm: string) { if (searchTimeout.value) { diff --git a/docker-compose.yml b/docker-compose.yml index e3bd5ac..7e48973 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -1,6 +1,6 @@ services: website: - image: ghcr.io/bewcloud/bewcloud:v2.4.0 + image: ghcr.io/bewcloud/bewcloud:v2.4.1 restart: always ports: - 127.0.0.1:8000:8000 diff --git a/islands/news/Articles.tsx b/islands/news/Articles.tsx index 17482ed..4f9cd33 100644 --- a/islands/news/Articles.tsx +++ b/islands/news/Articles.tsx @@ -22,7 +22,14 @@ export default function Articles({ initialArticles }: ArticlesProps) { const sessionReadArticleIds = useSignal>(new Set()); const isFilterDropdownOpen = useSignal(false); - const dateFormat = new Intl.DateTimeFormat('en-GB', { dateStyle: 'medium' }); + const dateFormatOptions: Intl.DateTimeFormatOptions = { dateStyle: 'medium' }; + + // Force timeZone to UTC for the server rendering + if (typeof window === 'undefined') { + dateFormatOptions.timeZone = 'UTC'; + } + + const dateFormat = new Intl.DateTimeFormat('en-GB', dateFormatOptions); async function refreshArticles() { if (isRefreshing.value) { diff --git a/islands/news/Feeds.tsx b/islands/news/Feeds.tsx index 883b405..6ac109d 100644 --- a/islands/news/Feeds.tsx +++ b/islands/news/Feeds.tsx @@ -57,7 +57,14 @@ export default function Feeds({ initialFeeds }: FeedsProps) { const feeds = useSignal(initialFeeds); const isOptionsDropdownOpen = useSignal(false); - const dateFormat = new Intl.DateTimeFormat('en-GB', { dateStyle: 'medium', timeStyle: 'short' }); + const dateFormatOptions: Intl.DateTimeFormatOptions = { dateStyle: 'medium', timeStyle: 'short' }; + + // Force timeZone to UTC for the server rendering + if (typeof window === 'undefined') { + dateFormatOptions.timeZone = 'UTC'; + } + + const dateFormat = new Intl.DateTimeFormat('en-GB', dateFormatOptions); async function onClickAddFeed() { if (isAdding.value) {