/** * Live DateTime Display with Attributes * * Usage: *
* * * * Attributes: * - data-datetime: Activates live datetime * - data-format: Format string (default: "DD MMMM • hh:mm:ssA") * - data-timezone: Timezone (default: "Europe/Berlin") * - data-locale: Language (default: "en-US") * - data-update: Update interval in ms (default: 1000) */ (function() { 'use strict'; // Default configuration const DEFAULTS = { format: 'DD MMMM • hh:mm:ssA', timezone: 'Europe/Berlin', locale: 'en-US', updateInterval: 1000 }; // Month names const MONTHS = { 'de-DE': [ 'Januar', 'Februar', 'März', 'April', 'Mai', 'Juni', 'Juli', 'August', 'September', 'Oktober', 'November', 'Dezember' ], 'en-US': [ 'January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December' ] }; const MONTHS_SHORT = { 'de-DE': [ 'Jan', 'Feb', 'Mär', 'Apr', 'Mai', 'Jun', 'Jul', 'Aug', 'Sep', 'Okt', 'Nov', 'Dez' ], 'en-US': [ 'Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec' ] }; function initLiveDateTime() { console.log('🕐 Live DateTime initialized'); // Find all elements with data-datetime attribute const elements = document.querySelectorAll('[data-datetime]'); if (elements.length === 0) { console.log('ℹ️ No elements with [data-datetime] found'); return; } console.log(`✅ Found ${elements.length} datetime element(s)`); // Initialize each element elements.forEach((element, index) => { initElement(element, index); }); } function initElement(element, index) { // Get configuration from attributes const config = { format: element.getAttribute('data-format') || DEFAULTS.format, timezone: element.getAttribute('data-timezone') || DEFAULTS.timezone, locale: element.getAttribute('data-locale') || DEFAULTS.locale, updateInterval: parseInt(element.getAttribute('data-update')) || DEFAULTS.updateInterval }; console.log(`📊 DateTime #${index}:`, config); // Update immediately updateDateTime(element, config); // Setup interval for live updates setInterval(() => { updateDateTime(element, config); }, config.updateInterval); console.log(`🎬 DateTime #${index} setup (updates every ${config.updateInterval}ms)`); } function updateDateTime(element, config) { const now = new Date(); // Convert to specified timezone const formatter = new Intl.DateTimeFormat(config.locale, { timeZone: config.timezone, year: 'numeric', month: '2-digit', day: '2-digit', hour: '2-digit', minute: '2-digit', second: '2-digit', hour12: false }); const parts = formatter.formatToParts(now); const dateTime = {}; parts.forEach(part => { dateTime[part.type] = part.value; }); // Format according to format string const formatted = formatDateTime(dateTime, config); // Update element element.textContent = formatted; } function formatDateTime(dateTime, config) { let result = config.format; // Use placeholders to prevent collisions (e.g., "mm" in "November") const PLACEHOLDER = '___'; const replacements = []; // Helper to add replacement function addReplacement(pattern, value) { const placeholder = PLACEHOLDER + replacements.length + PLACEHOLDER; result = result.replace(pattern, placeholder); replacements.push(value); } // Parse values const day = parseInt(dateTime.day); const month = parseInt(dateTime.month); const monthIndex = month - 1; const year = parseInt(dateTime.year); let hour24 = parseInt(dateTime.hour); const minute = parseInt(dateTime.minute); const second = parseInt(dateTime.second); // 12-hour format let hour12 = hour24 % 12; if (hour12 === 0) hour12 = 12; const ampm = hour24 >= 12 ? 'PM' : 'AM'; // Month names const monthsFull = MONTHS[config.locale] || MONTHS['en-US']; const monthsShort = MONTHS_SHORT[config.locale] || MONTHS_SHORT['en-US']; // Replace in order (longest patterns first to avoid collisions) // Year addReplacement('YYYY', year); addReplacement('YY', year.toString().slice(-2)); // Month (full name first, then short, then numbers) addReplacement('MMMM', monthsFull[monthIndex]); addReplacement('MMM', monthsShort[monthIndex]); addReplacement('MM', pad(month, 2)); addReplacement('M', month); // Day addReplacement('DD', pad(day, 2)); addReplacement('D', day); // Hours (24h) addReplacement('HH', pad(hour24, 2)); addReplacement('H', hour24); // Hours (12h) addReplacement('hh', pad(hour12, 2)); addReplacement('h', hour12); // Minutes addReplacement('mm', pad(minute, 2)); addReplacement('m', minute); // Seconds addReplacement('ss', pad(second, 2)); addReplacement('s', second); // AM/PM addReplacement('A', ampm); addReplacement('a', ampm.toLowerCase()); // Replace all placeholders with actual values replacements.forEach((value, index) => { const placeholder = PLACEHOLDER + index + PLACEHOLDER; result = result.replace(placeholder, value); }); return result; } function pad(num, size) { let s = num.toString(); while (s.length < size) s = '0' + s; return s; } // Initialize when DOM is ready if (document.readyState === 'loading') { document.addEventListener('DOMContentLoaded', initLiveDateTime); } else { initLiveDateTime(); } })();