Files
flights_web/src/shared/utils/datetime/index.ts
T
gnezim b3ab73253d Add data model types, datetime utils, and dictionary hook
Port Angular flight types (ISimpleFlight, IFlightLeg, ITimesSet, etc.)
to minimal React-friendly interfaces. Add formatDuration/formatTime/
formatDate/isDayChange as pure functions. Stub useCityName hook as
passthrough pending customer dictionary API endpoint.
2026-04-15 07:55:00 +03:00

91 lines
2.7 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/**
* Datetime utility functions.
*
* Pure functions ported from Angular pipes (DurationPipe, DatePipe).
* No Angular dependencies, no side effects.
*/
/**
* Format a duration given in total minutes into a human-readable string.
*
* @example formatDuration(150) => "2h 30m"
* @example formatDuration(150, "ru") => "2ч 30м"
* @example formatDuration(0) => "0h 0m"
*/
export function formatDuration(
minutes: number,
locale: string = "en",
): string {
if (minutes < 0) return locale === "ru" ? "Неизвестно" : "Unknown";
const days = Math.floor(minutes / (60 * 24));
const hours = Math.floor((minutes % (60 * 24)) / 60);
const mins = Math.floor(minutes % 60);
const units =
locale === "ru"
? { d: "д", h: "ч", m: "м" }
: { d: "d", h: "h", m: "m" };
const daysPart = days > 0 ? `${days}${units.d} ` : "";
return `${daysPart}${hours}${units.h} ${mins}${units.m}`;
}
/**
* Format a date/ISO string into "HH:mm" time.
*
* @example formatTime("2025-01-15T10:30:00") => "10:30"
* @example formatTime(new Date(2025, 0, 15, 10, 30)) => "10:30"
*/
export function formatTime(date: string | Date): string {
const d = typeof date === "string" ? new Date(date) : date;
if (Number.isNaN(d.getTime())) return "";
const hours = String(d.getHours()).padStart(2, "0");
const minutes = String(d.getMinutes()).padStart(2, "0");
return `${hours}:${minutes}`;
}
/**
* Format a date into a localized date string.
*
* @example formatDate("2025-01-15", "ru") => "15 января 2025 г."
* @example formatDate("2025-01-15", "en") => "January 15, 2025"
*/
export function formatDate(
date: string | Date,
locale: string = "en",
): string {
const d = typeof date === "string" ? new Date(date) : date;
if (Number.isNaN(d.getTime())) return "";
return d.toLocaleDateString(locale === "ru" ? "ru-RU" : "en-US", {
year: "numeric",
month: "long",
day: "numeric",
});
}
/**
* Calculate the day offset between two dates (ignoring time).
* Returns 0 if same day, +1 if actual is the next day, etc.
*
* @example isDayChange("2025-01-15T23:00", "2025-01-16T01:00") => 1
*/
export function isDayChange(
scheduledDate: string | Date,
actualDate: string | Date,
): number {
const s = typeof scheduledDate === "string" ? new Date(scheduledDate) : scheduledDate;
const a = typeof actualDate === "string" ? new Date(actualDate) : actualDate;
if (Number.isNaN(s.getTime()) || Number.isNaN(a.getTime())) return 0;
// Compare calendar dates (ignoring time)
const sDay = new Date(s.getFullYear(), s.getMonth(), s.getDate());
const aDay = new Date(a.getFullYear(), a.getMonth(), a.getDate());
const diffMs = aDay.getTime() - sDay.getTime();
return Math.round(diffMs / (24 * 60 * 60 * 1000));
}