fix: use UTC date components to prevent timezone off-by-one in due dates

This commit is contained in:
2026-01-28 19:09:05 +00:00
parent f9145f6a46
commit a20a5c5054
2 changed files with 10 additions and 7 deletions

2
dist/index.html vendored
View File

@@ -6,7 +6,7 @@
<meta name="viewport" content="width=device-width, initial-scale=1.0" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta name="description" content="Todo App - Task management made simple" /> <meta name="description" content="Todo App - Task management made simple" />
<title>Todo App</title> <title>Todo App</title>
<script type="module" crossorigin src="/assets/index-DtVMUKEv.js"></script> <script type="module" crossorigin src="/assets/index-CA4dNo0a.js"></script>
<link rel="stylesheet" crossorigin href="/assets/index-Bq_EO_v_.css"> <link rel="stylesheet" crossorigin href="/assets/index-Bq_EO_v_.css">
</head> </head>
<body> <body>

View File

@@ -8,12 +8,13 @@ export function cn(...inputs: ClassValue[]) {
export function formatDate(date: string | Date | undefined): string { export function formatDate(date: string | Date | undefined): string {
if (!date) return ''; if (!date) return '';
// Parse as UTC to avoid timezone shift (due dates are date-only values stored as midnight UTC)
const d = new Date(date); const d = new Date(date);
const now = new Date(); const now = new Date();
const today = new Date(now.getFullYear(), now.getMonth(), now.getDate()); const today = new Date(now.getFullYear(), now.getMonth(), now.getDate());
const tomorrow = new Date(today); const tomorrow = new Date(today);
tomorrow.setDate(tomorrow.getDate() + 1); tomorrow.setDate(tomorrow.getDate() + 1);
const taskDate = new Date(d.getFullYear(), d.getMonth(), d.getDate()); const taskDate = new Date(d.getUTCFullYear(), d.getUTCMonth(), d.getUTCDate());
if (taskDate.getTime() === today.getTime()) { if (taskDate.getTime() === today.getTime()) {
return 'Today'; return 'Today';
@@ -32,23 +33,25 @@ export function formatDate(date: string | Date | undefined): string {
const weekFromNow = new Date(today); const weekFromNow = new Date(today);
weekFromNow.setDate(weekFromNow.getDate() + 7); weekFromNow.setDate(weekFromNow.getDate() + 7);
if (taskDate > today && taskDate < weekFromNow) { if (taskDate > today && taskDate < weekFromNow) {
return d.toLocaleDateString('en-US', { weekday: 'long' }); return taskDate.toLocaleDateString('en-US', { weekday: 'long' });
} }
// Same year // Same year
if (d.getFullYear() === now.getFullYear()) { if (taskDate.getFullYear() === now.getFullYear()) {
return d.toLocaleDateString('en-US', { month: 'short', day: 'numeric' }); return taskDate.toLocaleDateString('en-US', { month: 'short', day: 'numeric' });
} }
return d.toLocaleDateString('en-US', { month: 'short', day: 'numeric', year: 'numeric' }); return taskDate.toLocaleDateString('en-US', { month: 'short', day: 'numeric', year: 'numeric' });
} }
export function isOverdue(date: string | Date | undefined): boolean { export function isOverdue(date: string | Date | undefined): boolean {
if (!date) return false; if (!date) return false;
// Parse as UTC to avoid timezone shift
const d = new Date(date); const d = new Date(date);
const taskDate = new Date(d.getUTCFullYear(), d.getUTCMonth(), d.getUTCDate());
const today = new Date(); const today = new Date();
today.setHours(0, 0, 0, 0); today.setHours(0, 0, 0, 0);
return d < today; return taskDate < today;
} }
export function getPriorityColor(priority: string): string { export function getPriorityColor(priority: string): string {