DevTools Differenz: optionale Uhrzeit pro Seite, Sekunden/Minuten/Stunden nur bei Zeitangabe

This commit is contained in:
2026-06-01 10:20:27 +02:00
parent b38e0c1a08
commit 0dcd9f3543

View File

@@ -585,69 +585,49 @@ function DatetimeRechner({ mobile }) {
// ── Tab 2: Geburtstag ── // ── Tab 2: Geburtstag ──
const [bday, setBday] = useState(''); const [bday, setBday] = useState('');
const [bdayTime, setBdayTime] = useState('');
const [bdayResult, setBdayResult] = useState(null); const [bdayResult, setBdayResult] = useState(null);
function calcBday(date, time) { function calcBday(val) {
const dateVal = date ?? bday; setBday(val);
const timeVal = time ?? bdayTime; if (!val) { setBdayResult(null); return; }
setBday(dateVal); const birth = new Date(val);
setBdayTime(timeVal);
if (!dateVal) { setBdayResult(null); return; }
// Build birth datetime: if time given use it, else midnight
const birthStr = timeVal ? `${dateVal}T${timeVal}:00` : `${dateVal}T00:00:00`;
const birth = new Date(birthStr);
if (isNaN(birth)) { setBdayResult(null); return; } if (isNaN(birth)) { setBdayResult(null); return; }
const hasTime = !!timeVal;
const today = new Date(); const today = new Date();
// Age in years
let ageY = today.getFullYear() - birth.getFullYear(); let ageY = today.getFullYear() - birth.getFullYear();
let ageM = today.getMonth() - birth.getMonth(); let ageM = today.getMonth() - birth.getMonth();
let ageD = today.getDate() - birth.getDate(); let ageD = today.getDate() - birth.getDate();
if (ageD < 0) { ageM--; const prev = new Date(today.getFullYear(), today.getMonth(), 0); ageD += prev.getDate(); } if (ageD < 0) { ageM--; const prev = new Date(today.getFullYear(), today.getMonth(), 0); ageD += prev.getDate(); }
if (ageM < 0) { ageY--; ageM += 12; } if (ageM < 0) { ageY--; ageM += 12; }
// Hours and minutes since last birthday (only if time entered) const nextBday = new Date(today.getFullYear(), birth.getMonth(), birth.getDate());
let ageH = null, ageMi = null;
if (hasTime) {
ageH = today.getHours() - birth.getHours();
ageMi = today.getMinutes() - birth.getMinutes();
if (ageMi < 0) { ageH--; ageMi += 60; }
if (ageH < 0) { ageD--; ageH += 24;
if (ageD < 0) { ageM--; const prev = new Date(today.getFullYear(), today.getMonth(), 0); ageD += prev.getDate();
if (ageM < 0) { ageY--; ageM += 12; } } }
}
// Next birthday
const nextBday = new Date(today.getFullYear(), birth.getMonth(), birth.getDate(),
hasTime ? birth.getHours() : 0, hasTime ? birth.getMinutes() : 0, 0);
if (nextBday <= today) nextBday.setFullYear(today.getFullYear()+1); if (nextBday <= today) nextBday.setFullYear(today.getFullYear()+1);
const diffMs = nextBday - today; const diffMs = nextBday - today;
const diffD = (diffMs / 86400000).toFixed(1); const diffD = (diffMs / 86400000).toFixed(1);
const totalMs = today - birth; const totalD = ((today - birth) / 86400000).toFixed(1);
const totalD = (totalMs / 86400000).toFixed(1);
// Age string setBdayResult({
let ageStr = `${ageY} Jahre, ${ageM} Monate, ${ageD} Tage`; ageStr: `${ageY} Jahre, ${ageM} Monate, ${ageD} Tage`,
if (hasTime && ageH !== null) ageStr += `, ${ageH} Std. ${pad2(ageMi)} Min.`; diffD, totalD,
setBdayResult({ ageStr, diffD, totalD,
wday: WEEKDAYS[birth.getDay()], wday: WEEKDAYS[birth.getDay()],
geburtstag: `${pad2(birth.getDate())}.${pad2(birth.getMonth()+1)}.${birth.getFullYear()}${hasTime?' '+timeVal:''}`, geburtstag: `${pad2(birth.getDate())}.${pad2(birth.getMonth()+1)}.${birth.getFullYear()}`,
nextDate: `${pad2(nextBday.getDate())}.${pad2(nextBday.getMonth()+1)}.${nextBday.getFullYear()} (${WEEKDAYS[nextBday.getDay()]})`, nextDate: `${pad2(nextBday.getDate())}.${pad2(nextBday.getMonth()+1)}.${nextBday.getFullYear()} (${WEEKDAYS[nextBday.getDay()]})`,
}); });
} }
// ── Tab 3: Zeitdifferenz ── // ── Tab 3: Zeitdifferenz ──
const [dtA, setDtA] = useState(''); const [dtA, setDtA] = useState('');
const [dtATime, setDtATime] = useState('');
const [dtB, setDtB] = useState(''); const [dtB, setDtB] = useState('');
const [dtBTime, setDtBTime] = useState('');
const [diffResult, setDiffResult] = useState(null); const [diffResult, setDiffResult] = useState(null);
function calcDiff(a, b) { function calcDiff(a, aTime, b, bTime) {
if (!a || !b) { setDiffResult(null); return; } if (!a || !b) { setDiffResult(null); return; }
const dA = new Date(a), dB = new Date(b); const strA = aTime ? `${a}T${aTime}:00` : `${a}T00:00:00`;
const strB = bTime ? `${b}T${bTime}:00` : `${b}T00:00:00`;
const dA = new Date(strA), dB = new Date(strB);
if (isNaN(dA)||isNaN(dB)) { setDiffResult(null); return; } if (isNaN(dA)||isNaN(dB)) { setDiffResult(null); return; }
const hasTime = !!(aTime || bTime);
const ms = Math.abs(dB - dA); const ms = Math.abs(dB - dA);
const s = (ms / 1000).toFixed(1); const s = (ms / 1000).toFixed(1);
const m = (ms / 60000).toFixed(1); const m = (ms / 60000).toFixed(1);
@@ -656,7 +636,7 @@ function DatetimeRechner({ mobile }) {
const weeks = (ms / (86400000*7)).toFixed(2); const weeks = (ms / (86400000*7)).toFixed(2);
const dA2 = new Date(Math.min(dA,dB)), dB2 = new Date(Math.max(dA,dB)); const dA2 = new Date(Math.min(dA,dB)), dB2 = new Date(Math.max(dA,dB));
const months = Math.abs(dB2.getMonth()-dA2.getMonth() + (dB2.getFullYear()-dA2.getFullYear())*12); const months = Math.abs(dB2.getMonth()-dA2.getMonth() + (dB2.getFullYear()-dA2.getFullYear())*12);
setDiffResult({ ms, s, m, h, d, weeks, months }); setDiffResult({ ms, s, m, h, d, weeks, months, hasTime });
} }
const inp = { ...S.inp, fontSize:13, padding:'7px 9px', width:'100%', boxSizing:'border-box' }; const inp = { ...S.inp, fontSize:13, padding:'7px 9px', width:'100%', boxSizing:'border-box' };
@@ -731,16 +711,11 @@ function DatetimeRechner({ mobile }) {
<div style={{display:'flex',alignItems:'flex-end',gap:10,marginBottom:16,flexWrap:'wrap'}}> <div style={{display:'flex',alignItems:'flex-end',gap:10,marginBottom:16,flexWrap:'wrap'}}>
<div> <div>
<div style={lbl}>Geburtsdatum</div> <div style={lbl}>Geburtsdatum</div>
<input style={{...inp, maxWidth:180}} type="date" value={bday} <input style={{...inp, maxWidth:200}} type="date" value={bday}
onChange={e=>calcBday(e.target.value, null)}/> onChange={e=>calcBday(e.target.value)}/>
</div> </div>
<div> {!!bday && <button style={{...S.btn('#ff6b9d',false), fontSize:11, padding:'6px 14px'}}
<div style={lbl}>Uhrzeit (optional)</div> onClick={()=>{ setBday(''); setBdayResult(null); }}> Leeren</button>}
<input style={{...inp, maxWidth:130}} type="time" value={bdayTime}
onChange={e=>calcBday(null, e.target.value)}/>
</div>
{!!(bday||bdayTime) && <button style={{...S.btn('#ff6b9d',false), fontSize:11, padding:'6px 14px'}}
onClick={()=>{ setBday(''); setBdayTime(''); setBdayResult(null); }}> Leeren</button>}
</div> </div>
{bdayResult && ( {bdayResult && (
<div> <div>
@@ -753,7 +728,7 @@ function DatetimeRechner({ mobile }) {
)} )}
{!bdayResult && ( {!bdayResult && (
<div style={{color:'rgba(255,255,255,0.4)',fontFamily:'monospace',fontSize:11}}> <div style={{color:'rgba(255,255,255,0.4)',fontFamily:'monospace',fontSize:11}}>
Geburtsdatum eingeben · Uhrzeit ist optional Geburtsdatum eingeben
</div> </div>
)} )}
</div> </div>
@@ -761,26 +736,40 @@ function DatetimeRechner({ mobile }) {
{tab==='diff' && ( {tab==='diff' && (
<div> <div>
<div style={{display:'grid',gridTemplateColumns:mobile?'1fr':'1fr 1fr',gap:12,marginBottom:16}}> <div style={{display:'grid',gridTemplateColumns:mobile?'1fr':'1fr 1fr',gap:16,marginBottom:16}}>
<div> <div style={{display:'flex',flexDirection:'column',gap:8}}>
<div style={lbl}>Von</div> <div>
<input style={inp} type="date" value={dtA} <div style={lbl}>Von Datum</div>
onChange={e=>{ setDtA(e.target.value); calcDiff(e.target.value, dtB); }}/> <input style={inp} type="date" value={dtA}
onChange={e=>{ setDtA(e.target.value); calcDiff(e.target.value, dtATime, dtB, dtBTime); }}/>
</div>
<div>
<div style={lbl}>Von Uhrzeit (optional)</div>
<input style={inp} type="time" value={dtATime}
onChange={e=>{ setDtATime(e.target.value); calcDiff(dtA, e.target.value, dtB, dtBTime); }}/>
</div>
</div> </div>
<div> <div style={{display:'flex',flexDirection:'column',gap:8}}>
<div style={lbl}>Bis</div> <div>
<input style={inp} type="date" value={dtB} <div style={lbl}>Bis Datum</div>
onChange={e=>{ setDtB(e.target.value); calcDiff(dtA, e.target.value); }}/> <input style={inp} type="date" value={dtB}
onChange={e=>{ setDtB(e.target.value); calcDiff(dtA, dtATime, e.target.value, dtBTime); }}/>
</div>
<div>
<div style={lbl}>Bis Uhrzeit (optional)</div>
<input style={inp} type="time" value={dtBTime}
onChange={e=>{ setDtBTime(e.target.value); calcDiff(dtA, dtATime, dtB, e.target.value); }}/>
</div>
</div> </div>
</div> </div>
{!!(dtA||dtB) && <button style={{...S.btn('#ff6b9d',false), fontSize:11, padding:'6px 14px', marginBottom:16}} {!!(dtA||dtB||dtATime||dtBTime) && <button style={{...S.btn('#ff6b9d',false), fontSize:11, padding:'6px 14px', marginBottom:16}}
onClick={()=>{ setDtA(''); setDtB(''); setDiffResult(null); }}> Felder leeren</button>} onClick={()=>{ setDtA(''); setDtB(''); setDtATime(''); setDtBTime(''); setDiffResult(null); }}> Felder leeren</button>}
{diffResult && ( {diffResult && (
<div> <div>
<DtRow label="Millisekunden" value={Number(diffResult.ms).toLocaleString('de-DE')} muted/> {!!diffResult.hasTime && <DtRow label="Millisekunden" value={Number(diffResult.ms).toLocaleString('de-DE')} muted/>}
<DtRow label="Sekunden" value={Number(diffResult.s).toLocaleString('de-DE')}/> {!!diffResult.hasTime && <DtRow label="Sekunden" value={Number(diffResult.s).toLocaleString('de-DE')}/>}
<DtRow label="Minuten" value={Number(diffResult.m).toLocaleString('de-DE')}/> {!!diffResult.hasTime && <DtRow label="Minuten" value={Number(diffResult.m).toLocaleString('de-DE')}/>}
<DtRow label="Stunden" value={Number(diffResult.h).toLocaleString('de-DE')}/> {!!diffResult.hasTime && <DtRow label="Stunden" value={Number(diffResult.h).toLocaleString('de-DE')}/>}
<DtRow label="Tage" value={Number(diffResult.d).toLocaleString('de-DE')}/> <DtRow label="Tage" value={Number(diffResult.d).toLocaleString('de-DE')}/>
<DtRow label="Wochen" value={Number(diffResult.weeks).toLocaleString('de-DE')} muted/> <DtRow label="Wochen" value={Number(diffResult.weeks).toLocaleString('de-DE')} muted/>
<DtRow label="Monate (ca.)" value={`~${diffResult.months}`} muted/> <DtRow label="Monate (ca.)" value={`~${diffResult.months}`} muted/>
@@ -788,7 +777,7 @@ function DatetimeRechner({ mobile }) {
)} )}
{!diffResult && ( {!diffResult && (
<div style={{color:'rgba(255,255,255,0.4)',fontFamily:'monospace',fontSize:11}}> <div style={{color:'rgba(255,255,255,0.4)',fontFamily:'monospace',fontSize:11}}>
Zwei Datumswerte eingeben Zwei Datumswerte eingeben · Uhrzeit ist optional
</div> </div>
)} )}
</div> </div>