init
This commit is contained in:
128
desktop@marha.de/dates.js
Normal file
128
desktop@marha.de/dates.js
Normal file
@@ -0,0 +1,128 @@
|
||||
// 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]);
|
||||
}
|
||||
Reference in New Issue
Block a user