mirror of
https://github.com/Since-3/since3-portal.git
synced 2026-10-12 20:51:17 +00:00
38 lines
1.3 KiB
TypeScript
38 lines
1.3 KiB
TypeScript
"use client"
|
|
|
|
import { useSyncExternalStore } from "react"
|
|
|
|
function subscribe(onChange: () => void) {
|
|
const timer = setInterval(onChange, 1000)
|
|
return () => clearInterval(timer)
|
|
}
|
|
|
|
// Aktuelle Zeit im Sekundentakt; auf dem Server null, damit nichts beim Hydrieren abweicht
|
|
export function useNow() {
|
|
return useSyncExternalStore(subscribe, () => Math.floor(Date.now() / 1000) * 1000, () => null)
|
|
}
|
|
|
|
// "2026-11-30" gilt bis Tagesende (lokale Zeit), "2026-11-19T09:00" ab genau dieser Uhrzeit
|
|
export function useCountdown(target: string) {
|
|
const now = useNow()
|
|
const end = Date.parse(/^\d{4}-\d{2}-\d{2}$/.test(target) ? `${target}T23:59:59` : target)
|
|
if (now === null || Number.isNaN(end)) return null
|
|
|
|
const diff = Math.max(0, end - now)
|
|
return {
|
|
days: Math.floor(diff / 86_400_000),
|
|
hours: Math.floor(diff / 3_600_000) % 24,
|
|
minutes: Math.floor(diff / 60_000) % 60,
|
|
seconds: Math.floor(diff / 1000) % 60,
|
|
done: diff === 0,
|
|
}
|
|
}
|
|
|
|
// "08:30" → Minuten seit Mitternacht, sonst null
|
|
export function minutesOf(time: string) {
|
|
const match = time.trim().match(/^(\d{1,2}):(\d{2})$/)
|
|
return match ? Number(match[1]) * 60 + Number(match[2]) : null
|
|
}
|
|
|
|
export const splitList = (value: string, separator: string | RegExp = ",") =>
|
|
value.split(separator).map((part) => part.trim()).filter(Boolean)
|