import QtQuick Item { id: root property date now: new Date() property string compact: formatClock(now).display readonly property var weekdays: ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"] readonly property var monthNames: ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"] function pad(value) { return value < 10 ? `0${value}` : `${value}`; } function parsed(iso) { return new Date(String(iso)); } function formatClock(value) { const hour = value.getHours(); const minute = value.getMinutes(); const second = value.getSeconds(); return { "hour": hour, "minute": minute, "second": second, "display": `${pad(hour)}:${pad(minute)}`, "statusDisplay": `${pad(hour)}:${pad(minute)}:${pad(second)}` }; } function odometerClock(value) { const display = formatClock(value).display; const cells = []; const chars = display.split(""); for (let i = 0; i < chars.length; i++) { const ch = chars[i]; const digit = ch >= "0" && ch <= "9"; cells.push(digit ? { "kind": "digit", "value": Number(ch), "motion": "vertical-digit-roll" } : { "kind": "separator", "value": ch, "hard": true }); } return { "source": "Nuguland Clock.qml ClockNumber.qml", "ownedBy": "Bar.qml", "display": display, "motion": "vertical-digit-roll", "font": "IBM Plex Mono", "hardSeparators": [":"], "noGlow": true, "settingsBacked": false, "cells": cells }; } function formatDate(value) { const year = value.getFullYear(); const month = value.getMonth() + 1; const day = value.getDate(); const weekday = weekdays[value.getDay()]; const monthName = monthNames[month - 1]; return { "year": year, "month": month, "day": day, "weekday": weekday, "monthName": monthName, "isoDay": isoDay(value), "line": `${weekday} ${day} ${monthName}` }; } function isoDay(value) { return `${value.getFullYear()}-${pad(value.getMonth() + 1)}-${pad(value.getDate())}`; } function relativeText(fromDate, toDate) { const seconds = Math.max(0, Math.floor((toDate.getTime() - fromDate.getTime()) / 1000)); if (seconds < 10) return "now"; if (seconds < 60) return `${seconds}s ago`; const minutes = Math.floor(seconds / 60); if (minutes < 60) return `${minutes}m ago`; const hours = Math.floor(minutes / 60); if (hours < 24) return `${hours}h ago`; return `${Math.floor(hours / 24)}d ago`; } function personalAgenda(value) { return [ { "id": "nuguland-focus", "title": "Nuguland focus", "time": `${formatClock(value).display}`, "source": "personal-constant", "role": "ui.accent" } ]; } function stateObject(value) { return { "backend": "Time.qml", "source": "shared-service-timer", "widgetProcesses": "forbidden", "helperProcesses": [], "font": "IBM Plex Mono", "timezone": "local", "iso": value.toISOString(), "clock": formatClock(value), "odometerClock": odometerClock(value), "date": formatDate(value), "relativeSamples": { "minute": relativeText(new Date(value.getTime() - 60000), value), "hour": relativeText(new Date(value.getTime() - 3.6e+06), value) }, "agenda": personalAgenda(value) }; } function stateJson() { return JSON.stringify(stateObject(now)); } function stateAt(iso) { return JSON.stringify(stateObject(parsed(iso))); } function relative(fromIso, toIso) { const fromDate = parsed(fromIso); const toDate = parsed(toIso); return JSON.stringify({ "backend": "Time.qml", "from": fromDate.toISOString(), "to": toDate.toISOString(), "text": relativeText(fromDate, toDate) }); } function calendar(year, month, selectedDay) { const first = new Date(year, month - 1, 1); const mondayOffset = (first.getDay() + 6) % 7; const cursor = new Date(first.getFullYear(), first.getMonth(), first.getDate() - mondayOffset); const todayIso = `${year}-${pad(month)}-${pad(selectedDay)}`; const weeks = []; for (let week = 0; week < 6; week++) { const days = []; for (let day = 0; day < 7; day++) { const current = new Date(cursor.getTime()); const inMonth = current.getMonth() === month - 1; const currentDay = current.getDate(); const currentIso = isoDay(current); days.push({ "iso": currentIso, "day": currentDay, "inMonth": inMonth, "selected": inMonth && currentDay === selectedDay, "today": currentIso === todayIso }); cursor.setDate(cursor.getDate() + 1); } weeks.push(days); } return JSON.stringify({ "backend": "Time.qml", "year": year, "month": month, "selectedDay": selectedDay, "weekStartsOn": "Mon", "weeks": weeks }); } Timer { interval: 1000 running: true repeat: true onTriggered: root.now = new Date() } }