Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: display departure times and search time in CET, regardless of which timezone the users is located in #234

Merged
merged 7 commits into from
Mar 1, 2024
23 changes: 19 additions & 4 deletions src/modules/search-time/selector/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import {
} from '@atb/translations';
import { SEARCH_MODES, SearchMode, SearchTime } from '../types';
import style from './selector.module.css';
import { setTimezoneIfNeeded } from '@atb/utils/date';

type SearchTimeSelectorProps = {
onChange: (state: SearchTime) => void;
Expand All @@ -22,8 +23,10 @@ export default function SearchTimeSelector({
}: SearchTimeSelectorProps) {
const { t } = useTranslation();
const [selectedMode, setSelectedMode] = useState<SearchTime>(initialState);
const initialDate =
'dateTime' in initialState ? new Date(initialState.dateTime) : new Date();
const initialDate = setTimezoneIfNeeded(
'dateTime' in initialState ? new Date(initialState.dateTime) : new Date(),
) as Date;

const [selectedDate, setSelectedDate] = useState(initialDate);
const [selectedTime, setSelectedTime] = useState(() =>
format(initialDate, 'HH:mm'),
Expand All @@ -47,11 +50,23 @@ export default function SearchTimeSelector({
};

const resetToCurrentTime = () => {
setSelectedTime(() => format(new Date(), 'HH:mm'));
const newState = {
mode: selectedMode.mode,
dateTime: setTimezoneIfNeeded(new Date()).getTime(),
};
setSelectedTime(() => format(newState.dateTime, 'HH:mm'));
setSelectedMode(newState);
onChange(newState);
};

const resetToCurrentDate = () => {
setSelectedDate(new Date());
const newState = {
mode: selectedMode.mode,
dateTime: setTimezoneIfNeeded(new Date()).getTime(),
};
setSelectedDate(new Date(newState.dateTime));
setSelectedMode(newState);
onChange(newState);
};

const isPastDate = (selectedDate: string) => {
Expand Down
13 changes: 12 additions & 1 deletion src/page-modules/assistant/client/journey-planner/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import { swrFetcher } from '@atb/modules/api-browser';
import useSWRInfinite from 'swr/infinite';
import { createTripQuery, tripQueryToQueryString } from '../../utils';
import { useEffect, useState } from 'react';
import { formatLocalTimeToCTE } from '@atb/utils/date';

const MAX_NUMBER_OF_INITIAL_SEARCH_ATTEMPTS = 3;
const INITIAL_NUMBER_OF_WANTED_TRIP_PATTERNS = 6;
Expand Down Expand Up @@ -37,7 +38,17 @@ export function useTripPatterns(
fallback?: TripData,
) {
const [numberOfTripPatterns, setNumberOfTripPatterns] = useState(0);
const query = createTripQuery(tripQuery);
const query = createTripQuery(
tripQuery.searchTime.mode === 'now'
? tripQuery
: {
...tripQuery,
searchTime: {
...tripQuery.searchTime,
dateTime: formatLocalTimeToCTE(tripQuery.searchTime.dateTime),
},
},
);
const { data, error, isLoading, isValidating, size, setSize } =
useSWRInfinite<TripApiReturnType>(
createKeyGetterOfQuery(query),
Expand Down
21 changes: 19 additions & 2 deletions src/utils/date.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,10 @@ import humanizeDuration from 'humanize-duration';
import { DEFAULT_LANGUAGE, Language } from '../translations';
import dictionary from '@atb/translations/dictionary';
import { TFunc } from '@leile/lobo-t';
import { FALLBACK_LANGUAGE } from '@atb/translations/commons';

const humanizer = humanizeDuration.humanizer({});
const CET = 'Europe/Oslo';

export function parseIfNeeded(a: string | Date): Date {
return a instanceof Date ? a : parseISO(a);
Expand Down Expand Up @@ -150,8 +152,9 @@ export function formatToClock(
showSeconds?: boolean,
) {
const parsed = parseIfNeeded(isoDate);
const rounded = !showSeconds ? roundMinute(parsed, roundingMethod) : parsed;
const seconds = showSeconds ? ':' + format(parsed, 'ss') : '';
const cet = setTimezoneIfNeeded(parsed);
const rounded = !showSeconds ? roundMinute(cet, roundingMethod) : cet;
const seconds = showSeconds ? ':' + format(cet, 'ss') : '';

return formatLocaleTime(rounded, language) + seconds;
}
Expand Down Expand Up @@ -354,3 +357,17 @@ export function formatTripDuration(

return { duration, departure, arrival };
}

export function setTimezoneIfNeeded(date: Date): Date {
if (Intl.DateTimeFormat().resolvedOptions().timeZone === CET) return date;
return new Date(date.toLocaleString(FALLBACK_LANGUAGE, { timeZone: CET }));
}

export function formatLocalTimeToCTE(localTime: number) {
jonasbrunvoll marked this conversation as resolved.
Show resolved Hide resolved
const offset = getOffsetTimezone();
return 3600000 * (offset - 1) + localTime;
}

function getOffsetTimezone() {
return (-1 * new Date().getTimezoneOffset()) / 60;
}
Loading