All good
This commit is contained in:
parent
6ea544a0f6
commit
6cc7288126
45 changed files with 929 additions and 1043 deletions
|
|
@ -68,6 +68,34 @@ const ROUTE_COLORS: Record<string, { color: string; darkText?: boolean }> = {
|
|||
};
|
||||
|
||||
const NON_TUBE_NAMES = new Set(['DLR', 'London Overground', 'Elizabeth line']);
|
||||
const GOOGLE_MAPS_DEPARTURE_TIME_ZONE = 'Europe/London';
|
||||
const londonDateFormatter = new Intl.DateTimeFormat('en-GB', {
|
||||
timeZone: GOOGLE_MAPS_DEPARTURE_TIME_ZONE,
|
||||
year: 'numeric',
|
||||
month: '2-digit',
|
||||
day: '2-digit',
|
||||
});
|
||||
const londonDateTimeFormatter = new Intl.DateTimeFormat('en-GB', {
|
||||
timeZone: GOOGLE_MAPS_DEPARTURE_TIME_ZONE,
|
||||
year: 'numeric',
|
||||
month: '2-digit',
|
||||
day: '2-digit',
|
||||
hour: '2-digit',
|
||||
minute: '2-digit',
|
||||
second: '2-digit',
|
||||
hour12: false,
|
||||
hourCycle: 'h23',
|
||||
});
|
||||
|
||||
function dateTimeParts(formatter: Intl.DateTimeFormat, date: Date): Record<string, number> {
|
||||
const parts: Record<string, number> = {};
|
||||
formatter.formatToParts(date).forEach((part) => {
|
||||
if (part.type !== 'literal') {
|
||||
parts[part.type] = Number(part.value);
|
||||
}
|
||||
});
|
||||
return parts;
|
||||
}
|
||||
|
||||
/** Strip trailing parenthesized GTFS route IDs and NaPTAN stop codes (e.g. "(6757261)", "(9400ZZLUCGT1)") */
|
||||
function stripId(label: string): string {
|
||||
|
|
@ -87,15 +115,48 @@ function getRouteDisplay(mode: string): { label: string; color: string; darkText
|
|||
return { label: clean, color: '#6b7280', darkText: false };
|
||||
}
|
||||
|
||||
/** Returns a Unix timestamp for the next Monday at 07:30 local time. */
|
||||
function londonOffsetMs(utcMs: number): number {
|
||||
const parts = dateTimeParts(londonDateTimeFormatter, new Date(utcMs));
|
||||
const londonAsUtcMs = Date.UTC(
|
||||
parts.year,
|
||||
parts.month - 1,
|
||||
parts.day,
|
||||
parts.hour,
|
||||
parts.minute,
|
||||
parts.second
|
||||
);
|
||||
return londonAsUtcMs - utcMs;
|
||||
}
|
||||
|
||||
function londonTimeToUtcMs(
|
||||
year: number,
|
||||
month: number,
|
||||
day: number,
|
||||
hour: number,
|
||||
minute: number
|
||||
): number {
|
||||
const localAsUtcMs = Date.UTC(year, month - 1, day, hour, minute, 0, 0);
|
||||
const offsetMs = londonOffsetMs(localAsUtcMs);
|
||||
const utcMs = localAsUtcMs - offsetMs;
|
||||
const correctedOffsetMs = londonOffsetMs(utcMs);
|
||||
return correctedOffsetMs === offsetMs ? utcMs : localAsUtcMs - correctedOffsetMs;
|
||||
}
|
||||
|
||||
/** Returns a Unix timestamp for the next Monday at 07:30 Europe/London time. */
|
||||
function nextMondayAt730(): number {
|
||||
const now = new Date();
|
||||
const day = now.getDay(); // 0=Sun … 6=Sat
|
||||
const today = dateTimeParts(londonDateFormatter, now);
|
||||
const day = new Date(Date.UTC(today.year, today.month - 1, today.day)).getUTCDay();
|
||||
const daysUntil = day === 0 ? 1 : day === 1 ? 7 : 8 - day;
|
||||
const monday = new Date(now);
|
||||
monday.setDate(now.getDate() + daysUntil);
|
||||
monday.setHours(7, 30, 0, 0);
|
||||
return Math.floor(monday.getTime() / 1000);
|
||||
const monday = new Date(Date.UTC(today.year, today.month - 1, today.day + daysUntil));
|
||||
const utcMs = londonTimeToUtcMs(
|
||||
monday.getUTCFullYear(),
|
||||
monday.getUTCMonth() + 1,
|
||||
monday.getUTCDate(),
|
||||
7,
|
||||
30
|
||||
);
|
||||
return Math.floor(utcMs / 1000);
|
||||
}
|
||||
|
||||
function googleMapsDestination(
|
||||
|
|
|
|||
|
|
@ -419,6 +419,7 @@ export default function MapPage({
|
|||
const { listings: actualListings } = useActualListings(mapData.bounds, {
|
||||
filterParam: actualListingsFilterParam,
|
||||
travelParam: actualListingsTravelParam,
|
||||
shareCode,
|
||||
});
|
||||
const [isAreaGroupExpanded, toggleAreaGroup] = useCollapsibleGroups(true);
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue