129 lines
3.8 KiB
JavaScript
129 lines
3.8 KiB
JavaScript
// Datumshilfen. Kalendertage sind Strings 'YYYY-MM-DD', Uhrzeiten 'HH:MM'.
|
|
// Monate sind 0-basiert wie bei JS Date.
|
|
|
|
export const WEEKDAYS = ['Mo', 'Di', 'Mi', 'Do', 'Fr', 'Sa', 'So'];
|
|
export const MONTHS = ['Januar', 'Februar', 'März', 'April', 'Mai', 'Juni',
|
|
'Juli', 'August', 'September', 'Oktober', 'November', 'Dezember'];
|
|
|
|
function pad(n) {
|
|
return String(n).padStart(2, '0');
|
|
}
|
|
|
|
export function toDateString(date) {
|
|
return `${date.getFullYear()}-${pad(date.getMonth() + 1)}-${pad(date.getDate())}`;
|
|
}
|
|
|
|
export function fromDateString(s) {
|
|
const [y, m, d] = s.split('-').map(Number);
|
|
return new Date(y, m - 1, d);
|
|
}
|
|
|
|
export function today() {
|
|
return toDateString(new Date());
|
|
}
|
|
|
|
export function addDays(s, n) {
|
|
const date = fromDateString(s);
|
|
date.setDate(date.getDate() + n);
|
|
return toDateString(date);
|
|
}
|
|
|
|
// Montag der Woche, in der s liegt.
|
|
export function startOfWeek(s) {
|
|
const date = fromDateString(s);
|
|
const offset = (date.getDay() + 6) % 7;
|
|
return addDays(s, -offset);
|
|
}
|
|
|
|
export function weekDays(s) {
|
|
const monday = startOfWeek(s);
|
|
return Array.from({length: 7}, (_, i) => addDays(monday, i));
|
|
}
|
|
|
|
// 42 Tage (6 Wochen) ab dem Montag der Woche des Monatsersten.
|
|
export function monthGrid(year, month) {
|
|
const first = toDateString(new Date(year, month, 1));
|
|
const start = startOfWeek(first);
|
|
return Array.from({length: 42}, (_, i) => addDays(start, i));
|
|
}
|
|
|
|
export function isoWeek(s) {
|
|
const date = fromDateString(s);
|
|
// Der Donnerstag derselben Woche bestimmt das ISO-Jahr.
|
|
const thursday = new Date(date);
|
|
thursday.setDate(date.getDate() - ((date.getDay() + 6) % 7) + 3);
|
|
const firstThursday = new Date(thursday.getFullYear(), 0, 4);
|
|
firstThursday.setDate(firstThursday.getDate() - ((firstThursday.getDay() + 6) % 7) + 3);
|
|
return 1 + Math.round((thursday - firstThursday) / (7 * 24 * 3600 * 1000));
|
|
}
|
|
|
|
export function formatMonth(year, month) {
|
|
return `${MONTHS[month]} ${year}`;
|
|
}
|
|
|
|
// 'Do, 17.09.2026'
|
|
export function formatDate(s) {
|
|
const date = fromDateString(s);
|
|
return `${WEEKDAYS[(date.getDay() + 6) % 7]}, ${formatDateInput(s)}`;
|
|
}
|
|
|
|
// '17.09.2026'
|
|
export function formatDateInput(s) {
|
|
const [y, m, d] = s.split('-');
|
|
return `${d}.${m}.${y}`;
|
|
}
|
|
|
|
// '17.09.'
|
|
export function formatDayMonth(s) {
|
|
const [, m, d] = s.split('-');
|
|
return `${d}.${m}.`;
|
|
}
|
|
|
|
// Akzeptiert '17.09.2026', '17.9.26', '17.9.' (aktuelles Jahr) und '2026-09-17'.
|
|
export function parseDateInput(text) {
|
|
const t = text.trim();
|
|
let y, m, d;
|
|
let match = t.match(/^(\d{1,2})\.(\d{1,2})\.(\d{2,4})?$/);
|
|
if (match) {
|
|
d = Number(match[1]);
|
|
m = Number(match[2]);
|
|
y = match[3] === undefined ? new Date().getFullYear() : Number(match[3]);
|
|
if (y < 100)
|
|
y += 2000;
|
|
} else {
|
|
match = t.match(/^(\d{4})-(\d{1,2})-(\d{1,2})$/);
|
|
if (!match)
|
|
return null;
|
|
[y, m, d] = [Number(match[1]), Number(match[2]), Number(match[3])];
|
|
}
|
|
const date = new Date(y, m - 1, d);
|
|
if (date.getFullYear() !== y || date.getMonth() !== m - 1 || date.getDate() !== d)
|
|
return null;
|
|
return toDateString(date);
|
|
}
|
|
|
|
// Akzeptiert '9:00', '09:00', '9.30', '14' → 'HH:MM'.
|
|
export function parseTimeInput(text) {
|
|
const match = text.trim().match(/^(\d{1,2})(?:[:.](\d{2}))?$/);
|
|
if (!match)
|
|
return null;
|
|
const h = Number(match[1]);
|
|
const min = match[2] === undefined ? 0 : Number(match[2]);
|
|
if (h > 23 || min > 59)
|
|
return null;
|
|
return `${pad(h)}:${pad(min)}`;
|
|
}
|
|
|
|
export function timeToMinutes(t) {
|
|
const [h, m] = t.split(':').map(Number);
|
|
return h * 60 + m;
|
|
}
|
|
|
|
export function minutesToTime(minutes) {
|
|
return `${pad(Math.floor(minutes / 60))}:${pad(minutes % 60)}`;
|
|
}
|
|
|
|
export function hourOf(t) {
|
|
return Number(t.split(':')[0]);
|
|
}
|