48 lines
1.9 KiB
JavaScript
48 lines
1.9 KiB
JavaScript
/**
|
|
* Kalendertage fuer die Finanzen als Zeichenkette YYYY-MM-DD ("ymd"). "Heute" ist immer der Berliner Tag
|
|
* (Europe/Berlin, MESZ/MEZ automatisch). Gerechnet wird mit UTC-Mitternacht des jeweiligen Tages, damit
|
|
* die Zeitumstellung (23- und 25-Stunden-Tage) keinen Tag verschluckt oder verdoppelt.
|
|
*/
|
|
|
|
const DAY_MS = 86_400_000
|
|
|
|
// Formatierer einmal anlegen (neu anlegen ist teuer); sv-SE liefert YYYY-MM-DD
|
|
const berlinDayFormat = new Intl.DateTimeFormat('sv-SE', { timeZone: 'Europe/Berlin', year: 'numeric', month: '2-digit', day: '2-digit' })
|
|
|
|
/** Kalendertag in Berlin (YYYY-MM-DD) zu einem Zeitpunkt. */
|
|
export function berlinDate(date = new Date()) {
|
|
return berlinDayFormat.format(date)
|
|
}
|
|
|
|
/** UTC-Mitternacht (Millisekunden) eines ymd; wirft bei Formfehlern und Tagen, die es nicht gibt (30.02.). */
|
|
function dayMs(ymd) {
|
|
const match = typeof ymd === 'string' ? ymd.match(/^(\d{4})-(\d{2})-(\d{2})$/) : null
|
|
if (match) {
|
|
const [year, month, day] = match.slice(1).map(Number)
|
|
const ms = Date.UTC(year, month - 1, day)
|
|
const check = new Date(ms)
|
|
if (check.getUTCFullYear() === year && check.getUTCMonth() === month - 1 && check.getUTCDate() === day) return ms
|
|
}
|
|
throw new Error(`Ungültiges Datum: ${typeof ymd === 'string' ? ymd : typeof ymd}`)
|
|
}
|
|
|
|
const ymdOf = (ms) => new Date(ms).toISOString().slice(0, 10)
|
|
|
|
/** ymd plus n ganze Tage (n darf negativ sein). */
|
|
export function addDays(ymd, n) {
|
|
if (!Number.isInteger(n)) throw new Error('Tage müssen eine ganze Zahl sein.')
|
|
return ymdOf(dayMs(ymd) + n * DAY_MS)
|
|
}
|
|
|
|
/** Ganze Tage von fromYmd bis toYmd (toYmd minus fromYmd, negativ wenn toYmd frueher liegt). */
|
|
export function daysBetween(fromYmd, toYmd) {
|
|
return Math.round((dayMs(toYmd) - dayMs(fromYmd)) / DAY_MS)
|
|
}
|
|
|
|
/** ymd als TT.MM.JJJJ. */
|
|
export function formatDe(ymd) {
|
|
dayMs(ymd)
|
|
const [year, month, day] = ymd.split('-')
|
|
return `${day}.${month}.${year}`
|
|
}
|