feat: local time (#7)

Co-authored-by: terraputix <terraputix@mailbox.org>
Reviewed-on: useweb/open-meteo-blue#7
This commit was merged in pull request #7.
This commit is contained in:
2026-02-16 11:41:34 +01:00
co-authored by terraputix
parent 381ffaf3f6
commit 9946cd5851
16 changed files with 948 additions and 701 deletions
+61
View File
@@ -0,0 +1,61 @@
import { formatInTimeZone, toZonedTime } from 'date-fns-tz';
import { isSameDay as isSameDayDateFns } from 'date-fns';
/**
* Formats a UTC Date into a string for a specific timezone using date-fns patterns.
* Patterns: 'HH:mm' for 24h time, 'EEE' for short weekday, etc.
*/
export function formatZoned(date: Date, timeZone: string, pattern: string): string {
return formatInTimeZone(date, timeZone, pattern);
}
/**
* Checks if two dates are the same day in a specific timezone.
* Important for comparing weather forecast days against a selected date.
*/
export function isSameDayInZone(date1: Date, date2: Date, timeZone: string): boolean {
const z1 = toZonedTime(date1, timeZone);
const z2 = toZonedTime(date2, timeZone);
return isSameDayDateFns(z1, z2);
}
/**
* Gets the numeric hour (0-23) for a date in a specific timezone.
*/
export function getZonedHour(date: Date, timeZone: string): number {
return parseInt(formatInTimeZone(date, timeZone, 'H'), 10);
}
/**
* Returns a relative label like "Today", "Tomorrow", "Yesterday",
* or a formatted date string, all relative to the target timezone.
*/
export function getRelativeDayLabel(date: Date, timeZone: string): string {
const now = new Date();
const zonedDate = toZonedTime(date, timeZone);
const zonedNow = toZonedTime(now, timeZone);
if (isSameDayDateFns(zonedDate, zonedNow)) return 'Today';
const tomorrow = new Date(zonedNow);
tomorrow.setDate(tomorrow.getDate() + 1);
if (isSameDayDateFns(zonedDate, tomorrow)) return 'Tomorrow';
const yesterday = new Date(zonedNow);
yesterday.setDate(yesterday.getDate() - 1);
if (isSameDayDateFns(zonedDate, yesterday)) return 'Yesterday';
return formatInTimeZone(date, timeZone, 'EEE d MMM');
}
/**
* Formats a UTC offset in seconds to a string like "UTC+1" or "UTC-05:00"
*/
export function formatUtcOffset(offsetSeconds: number): string {
const sign = offsetSeconds >= 0 ? '+' : '-';
const abs = Math.abs(offsetSeconds);
const hours = Math.floor(abs / 3600);
const minutes = Math.floor((abs % 3600) / 60);
const pad = (n: number) => n.toString().padStart(2, '0');
return minutes === 0 ? `UTC${sign}${hours}` : `UTC${sign}${hours}:${pad(minutes)}`;
}