diff --git a/App/teacher.html b/App/teacher.html
index 2001ca4..ddff25e 100644
--- a/App/teacher.html
+++ b/App/teacher.html
@@ -1082,7 +1082,7 @@ function _cockpitStudentRow(s) {
sub += ' 📵 idle seit '+idleStr+' — Zeit pausiert';
}
} else if (s.status === 'heute') {
- var when = s.lastSeen ? new Date(s.lastSeen).toLocaleTimeString('de-AT',{hour:'2-digit',minute:'2-digit'}) : '';
+ var when = s.lastSeen ? _hhmm(s.lastSeen) : '';
sub = 'heute aktiv · zuletzt um '+when+'';
} else if (s.status === 'kalt') {
sub = 'heute noch nicht eingeloggt'+(s.lastSeen?' · zuletzt '+_cockpitFmtAgo(Math.floor((Date.now()-new Date(s.lastSeen).getTime())/1000)):'')+'';
@@ -1227,7 +1227,7 @@ async function _loadCockpitReflections() {
(data.modules || []).forEach(function(m){ simIcons[m.id] = m.icon || ''; });
var html = '
';
items.forEach(function(it) {
- var when = it.recordedAt ? new Date(it.recordedAt).toLocaleString('de-AT', {day:'2-digit',month:'2-digit',hour:'2-digit',minute:'2-digit'}) : '';
+ var when = it.recordedAt ? _vdt(it.recordedAt) : '';
html += '
'
+ '
'
+ '
' + _avatarHtml(it.avatarSlug, it.emoji, 1.2) + ' ' + esc(it.displayName||'—') + ''
@@ -1368,8 +1368,19 @@ function _liveIsActive(ls) {
return ls.last_seen_ms && (Date.now() - ls.last_seen_ms) <= _LIVE_PAUSE_SEC * 1000;
}
-// Uhrzeit HH:MM aus ms-Epoch.
-function _hhmm(ms){ if(!ms) return '—'; var d=new Date(ms); return ('0'+d.getHours()).slice(-2)+':'+('0'+d.getMinutes()).slice(-2); }
+// Uhrzeit/Datum IMMER in österreichischer Zeit (Europe/Vienna) — unabhängig von der
+// Zeitzone des Servers (läuft in UTC) ODER des Anzeigegeräts.
+// Eingabe: ms-Epoch (Zahl) ODER MySQL-Datetime-String (wird als UTC interpretiert).
+function _asMs(t){
+ if (t == null || t === '') return 0;
+ if (typeof t === 'number') return t;
+ var s = String(t).trim();
+ if (/^\d{4}-\d{2}-\d{2}[ T]\d{2}:\d{2}/.test(s) && !/[zZ]|[+-]\d{2}:?\d{2}$/.test(s))
+ return new Date(s.replace(' ', 'T') + 'Z').getTime(); // DB-Zeit ist UTC
+ return new Date(s).getTime();
+}
+function _hhmm(t){ var ms=_asMs(t); if(!ms) return '—'; return new Date(ms).toLocaleTimeString('de-AT',{timeZone:'Europe/Vienna',hour:'2-digit',minute:'2-digit'}); }
+function _vdt(t){ var ms=_asMs(t); if(!ms) return '—'; return new Date(ms).toLocaleString('de-AT',{timeZone:'Europe/Vienna',day:'2-digit',month:'2-digit',hour:'2-digit',minute:'2-digit'}); }
// Avatar als Bild rendern — egal ob der Slug in avatar_slug ODER als
// „avatar:" im emoji_avatar-Feld steckt (Daten sind uneinheitlich).
@@ -2160,8 +2171,7 @@ async function renderLiveSummary() {
var winSpanMs = winEnd - winStart;
function _msToPct(ms) { return ((ms - winStart) / winSpanMs) * 100; }
function _fmtHM(ms) {
- var d = new Date(ms);
- return ('0'+d.getHours()).slice(-2) + ':' + ('0'+d.getMinutes()).slice(-2);
+ return new Date(ms).toLocaleTimeString('de-AT', {timeZone:'Europe/Vienna', hour:'2-digit', minute:'2-digit'});
}
var activeCount = students.filter(function(s){return (s.sessions||[]).length>0;}).length;
@@ -2292,8 +2302,8 @@ async function openLiveSessionDetail(sessionKey) {
(sess.simIcon||'📚') + ' ' + (sess.simTitle||sess.simId) + (sess.lessonLabel?' · '+sess.lessonLabel:'');
var body = document.getElementById('sessdet-body');
var avatarHtml = _avatarHtml(sess.studentAvatarSlug, sess.studentEmoji, 2);
- var startTime = new Date(sess.startMs).toLocaleString('de-AT',{hour:'2-digit',minute:'2-digit',day:'2-digit',month:'2-digit'});
- var endTime = new Date(sess.endMs).toLocaleString('de-AT',{hour:'2-digit',minute:'2-digit'});
+ var startTime = _vdt(sess.startMs);
+ var endTime = _hhmm(sess.endMs);
var dur = _liveFmtMin(sess.durationSec||0);
var stars = sess.stars;
var starsHtml = stars != null
@@ -2433,7 +2443,7 @@ async function renderSpectator(studentId) {
html += 'Erfolgreich abgeschlossen: '+wonVal+'
';
}
}
- html += 'Aktualisiert alle 3 Sekunden · letztes Lebenszeichen: '+(data.last_seen_ms?new Date(data.last_seen_ms).toLocaleTimeString('de-AT'):'?')+'
';
+ html += 'Aktualisiert alle 3 Sekunden · letztes Lebenszeichen: '+(data.last_seen_ms?_hhmm(data.last_seen_ms):'?')+'
';
host.innerHTML = html;
}