part of 'main.dart'; String formatDate(DateTime date) { final month = date.month.toString().padLeft(2, '0'); final day = date.day.toString().padLeft(2, '0'); return '${date.year}.$month.$day'; } String formatTime(DateTime date) { final hour = date.hour.toString().padLeft(2, '0'); final minute = date.minute.toString().padLeft(2, '0'); return '$hour:$minute'; } String formatTimeWithSeconds(DateTime date) { final hour = date.hour.toString().padLeft(2, '0'); final minute = date.minute.toString().padLeft(2, '0'); final second = date.second.toString().padLeft(2, '0'); return '$hour:$minute:$second'; } String formatShortDate(DateTime date) { final month = date.month.toString().padLeft(2, '0'); final day = date.day.toString().padLeft(2, '0'); return '$month.$day'; } int isoWeekNumber(DateTime date) { final thursday = date.add(Duration(days: 4 - date.weekday)); final firstThursday = DateTime(thursday.year, 1, 4); final firstWeekStart = firstThursday.subtract( Duration(days: firstThursday.weekday - 1), ); return thursday.difference(firstWeekStart).inDays ~/ 7 + 1; } DateTime startOfIsoWeek(DateTime date) { final normalized = DateTime(date.year, date.month, date.day); return normalized.subtract(Duration(days: normalized.weekday - 1)); } DateTime startOfDay(DateTime date) => DateTime(date.year, date.month, date.day); bool isSameDate(DateTime a, DateTime b) { return a.year == b.year && a.month == b.month && a.day == b.day; } DateTime? parseDate(String value) { final normalized = value.trim().replaceAll('-', '.'); final parts = normalized.split('.').where((part) => part.isNotEmpty).toList(); if (parts.length != 3) return null; final year = int.tryParse(parts[0]); final month = int.tryParse(parts[1]); final day = int.tryParse(parts[2]); if (year == null || month == null || day == null) return null; return DateTime(year, month, day); } DateTime? parseGoogleEventDate(Map value) { final dateTime = value['dateTime'] as String?; if (dateTime != null && dateTime.trim().isNotEmpty) { return DateTime.tryParse(dateTime)?.toLocal(); } final date = value['date'] as String?; if (date == null || date.trim().isEmpty) return null; final parsed = DateTime.tryParse(date); if (parsed == null) return null; return DateTime(parsed.year, parsed.month, parsed.day); } Color parseGoogleColor(String? value) { final raw = value?.trim(); if (raw == null || !raw.startsWith('#')) { return const Color(0xFF4285F4); } final hex = raw.substring(1); if (hex.length != 6) return const Color(0xFF4285F4); final colorValue = int.tryParse(hex, radix: 16); if (colorValue == null) return const Color(0xFF4285F4); return Color(0xFF000000 | colorValue); } String uniqueId() => DateTime.now().microsecondsSinceEpoch.toString(); String normalizeJarvisUrl(String value) { final trimmed = value.trim(); if (trimmed.isEmpty) return JarvisSettings.defaults().apiUrl; final withScheme = trimmed.startsWith('http://') || trimmed.startsWith('https://') ? trimmed : 'http://$trimmed'; return withScheme.endsWith('/') ? withScheme.substring(0, withScheme.length - 1) : withScheme; } String weatherDescription(int? code) { if (code == null) return 'id\u0151j\u00e1r\u00e1s'; if (code == 0) return 'der\u00fclt'; if ([1, 2, 3].contains(code)) return 'felh\u0151s'; if ([45, 48].contains(code)) return 'k\u00f6d'; if ([51, 53, 55, 56, 57].contains(code)) return 'szit\u00e1l\u00e1s'; if ([61, 63, 65, 66, 67, 80, 81, 82].contains(code)) return 'es\u0151'; if ([71, 73, 75, 77, 85, 86].contains(code)) return 'havaz\u00e1s'; if ([95, 96, 99].contains(code)) return 'zivatar'; return 'v\u00e1ltoz\u00e9kony'; } IconData weatherIcon(int? code) { if (code == null) return Icons.thermostat_outlined; if (code == 0) return Icons.wb_sunny_outlined; if ([1, 2, 3].contains(code)) return Icons.cloud_outlined; if ([45, 48].contains(code)) return Icons.foggy; if ([51, 53, 55, 56, 57, 61, 63, 65, 66, 67, 80, 81, 82].contains(code)) { return Icons.water_drop_outlined; } if ([71, 73, 75, 77, 85, 86].contains(code)) return Icons.ac_unit; if ([95, 96, 99].contains(code)) return Icons.thunderstorm_outlined; return Icons.cloud_queue; }