Fix week date range off-by-one in BST timezone
toISOString() returns UTC — in BST (UTC+1) dates computed from new Date() land one day early. Replace with local date components via fmt()/localStr(). Affects Weekly, Monthly, Rolling12Weeks, Rolling12Months. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
3e1851fa6d
commit
793e97dbbb
4 changed files with 17 additions and 7 deletions
|
|
@ -6,7 +6,9 @@ import {
|
||||||
import { getActuals, getScheduled, getNetSales, getBudgets, downloadExport } from '../api'
|
import { getActuals, getScheduled, getNetSales, getBudgets, downloadExport } from '../api'
|
||||||
import type { DeptActuals, WageBudget } from '../types'
|
import type { DeptActuals, WageBudget } from '../types'
|
||||||
|
|
||||||
function fmt(d: Date): string { return d.toISOString().slice(0, 10) }
|
function fmt(d: Date): string {
|
||||||
|
return `${d.getFullYear()}-${String(d.getMonth() + 1).padStart(2, '0')}-${String(d.getDate()).padStart(2, '0')}`
|
||||||
|
}
|
||||||
function addDays(d: Date, n: number): Date { const r = new Date(d); r.setDate(r.getDate() + n); return r }
|
function addDays(d: Date, n: number): Date { const r = new Date(d); r.setDate(r.getDate() + n); return r }
|
||||||
function daysInMonth(y: number, m: number): number { return new Date(y, m, 0).getDate() }
|
function daysInMonth(y: number, m: number): number { return new Date(y, m, 0).getDate() }
|
||||||
function fmtMoney(n: number): string { return `£${Math.round(n).toLocaleString('en-GB')}` }
|
function fmtMoney(n: number): string { return `£${Math.round(n).toLocaleString('en-GB')}` }
|
||||||
|
|
@ -15,7 +17,7 @@ function pctClass(pct: number): string { return pct <= 100 ? 'pct-green' : pct <
|
||||||
const DEPT_COLORS = ['#065f46','#059669','#0891b2','#7c3aed','#c2410c','#b45309','#0f766e','#4338ca','#be185d','#15803d']
|
const DEPT_COLORS = ['#065f46','#059669','#0891b2','#7c3aed','#c2410c','#b45309','#0f766e','#4338ca','#be185d','#15803d']
|
||||||
|
|
||||||
export default function Monthly() {
|
export default function Monthly() {
|
||||||
const todayStr = new Date().toISOString().slice(0, 10)
|
const todayStr = fmt(new Date())
|
||||||
const todayYear = parseInt(todayStr.slice(0, 4))
|
const todayYear = parseInt(todayStr.slice(0, 4))
|
||||||
const todayMonth = parseInt(todayStr.slice(5, 7))
|
const todayMonth = parseInt(todayStr.slice(5, 7))
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,9 @@ import {
|
||||||
import { getActuals, getNetSales, getBudgets, downloadExport } from '../api'
|
import { getActuals, getNetSales, getBudgets, downloadExport } from '../api'
|
||||||
import type { WageBudget } from '../types'
|
import type { WageBudget } from '../types'
|
||||||
|
|
||||||
function fmt(d: Date): string { return d.toISOString().slice(0, 10) }
|
function fmt(d: Date): string {
|
||||||
|
return `${d.getFullYear()}-${String(d.getMonth() + 1).padStart(2, '0')}-${String(d.getDate()).padStart(2, '0')}`
|
||||||
|
}
|
||||||
function fmtMoney(n: number): string { return `£${Math.round(n).toLocaleString('en-GB')}` }
|
function fmtMoney(n: number): string { return `£${Math.round(n).toLocaleString('en-GB')}` }
|
||||||
function pctClass(p: number): string { return p <= 100 ? 'pct-green' : p <= 110 ? 'pct-amber' : 'pct-red' }
|
function pctClass(p: number): string { return p <= 100 ? 'pct-green' : p <= 110 ? 'pct-amber' : 'pct-red' }
|
||||||
function daysInMonth(y: number, m: number): number { return new Date(y, m, 0).getDate() }
|
function daysInMonth(y: number, m: number): number { return new Date(y, m, 0).getDate() }
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,9 @@ import {
|
||||||
import { getActuals, getNetSales, getBudgets, downloadExport } from '../api'
|
import { getActuals, getNetSales, getBudgets, downloadExport } from '../api'
|
||||||
import type { WageBudget } from '../types'
|
import type { WageBudget } from '../types'
|
||||||
|
|
||||||
function fmt(d: Date): string { return d.toISOString().slice(0, 10) }
|
function fmt(d: Date): string {
|
||||||
|
return `${d.getFullYear()}-${String(d.getMonth() + 1).padStart(2, '0')}-${String(d.getDate()).padStart(2, '0')}`
|
||||||
|
}
|
||||||
function addDays(d: Date, n: number): Date { const r = new Date(d); r.setDate(r.getDate() + n); return r }
|
function addDays(d: Date, n: number): Date { const r = new Date(d); r.setDate(r.getDate() + n); return r }
|
||||||
function startOfWeek(d: Date): Date {
|
function startOfWeek(d: Date): Date {
|
||||||
const day = d.getDay()
|
const day = d.getDay()
|
||||||
|
|
|
||||||
|
|
@ -3,18 +3,22 @@ import { ChevronLeft, ChevronRight, Download } from 'lucide-react'
|
||||||
import { getActuals, getNetSales, getBudgets, downloadExport } from '../api'
|
import { getActuals, getNetSales, getBudgets, downloadExport } from '../api'
|
||||||
import type { DeptActuals, WageBudget } from '../types'
|
import type { DeptActuals, WageBudget } from '../types'
|
||||||
|
|
||||||
|
function localStr(d: Date): string {
|
||||||
|
return `${d.getFullYear()}-${String(d.getMonth() + 1).padStart(2, '0')}-${String(d.getDate()).padStart(2, '0')}`
|
||||||
|
}
|
||||||
|
|
||||||
function mondayOf(d: Date): string {
|
function mondayOf(d: Date): string {
|
||||||
const day = d.getDay()
|
const day = d.getDay()
|
||||||
const r = new Date(d)
|
const r = new Date(d)
|
||||||
r.setDate(d.getDate() + (day === 0 ? -6 : 1 - day))
|
r.setDate(d.getDate() + (day === 0 ? -6 : 1 - day))
|
||||||
r.setHours(0, 0, 0, 0)
|
r.setHours(0, 0, 0, 0)
|
||||||
return r.toISOString().slice(0, 10)
|
return localStr(r)
|
||||||
}
|
}
|
||||||
|
|
||||||
function addDaysStr(dateStr: string, n: number): string {
|
function addDaysStr(dateStr: string, n: number): string {
|
||||||
const d = new Date(dateStr + 'T00:00:00')
|
const d = new Date(dateStr + 'T00:00:00')
|
||||||
d.setDate(d.getDate() + n)
|
d.setDate(d.getDate() + n)
|
||||||
return d.toISOString().slice(0, 10)
|
return localStr(d)
|
||||||
}
|
}
|
||||||
|
|
||||||
function daysInMonthFor(dateStr: string): number {
|
function daysInMonthFor(dateStr: string): number {
|
||||||
|
|
@ -41,7 +45,7 @@ export default function Weekly() {
|
||||||
const [fromStr, setFromStr] = useState<string>(() => mondayOf(new Date()))
|
const [fromStr, setFromStr] = useState<string>(() => mondayOf(new Date()))
|
||||||
|
|
||||||
const toStr = addDaysStr(fromStr, 6)
|
const toStr = addDaysStr(fromStr, 6)
|
||||||
const todayStr = new Date().toISOString().slice(0, 10)
|
const todayStr = localStr(new Date())
|
||||||
|
|
||||||
const [depts, setDepts] = useState<DeptActuals[]>([])
|
const [depts, setDepts] = useState<DeptActuals[]>([])
|
||||||
const [netSales, setNetSales] = useState(0)
|
const [netSales, setNetSales] = useState(0)
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue