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

chore(date formatting): clean up date formatting in the app #7584

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 7 additions & 12 deletions web/src/components/Time.tsx
Original file line number Diff line number Diff line change
@@ -1,37 +1,32 @@
import { useAtomValue } from 'jotai';
import { useParams } from 'react-router-dom';
import { RouteParameters } from 'types';
import { TimeRange } from 'utils/constants';
import { formatDate, formatDateRange } from 'utils/formatting';
import { formatDate } from 'utils/formatting';
import { getZoneTimezone } from 'utils/helpers';
import { timeRangeAtom } from 'utils/state/atoms';

export function FormattedTime({
datetime,
language,
timeRange,
className,
zoneId,
isTimeHeader = false,
endDatetime,
}: {
datetime: Date;
language: string;
timeRange?: TimeRange;
className?: string;
zoneId?: string;
isTimeHeader?: boolean;
endDatetime?: Date;
}) {
const timeRange = useAtomValue(timeRangeAtom);
const { zoneId: pathZoneId } = useParams<RouteParameters>();
const timeZoneZoneId = zoneId || pathZoneId;
const timezone = getZoneTimezone(timeZoneZoneId);
if (timeRange) {
return (
<time dateTime={datetime.toISOString()} className={className}>
{formatDate(datetime, language, timeRange, timezone)}
</time>
);
}
return (
<time dateTime={datetime.toISOString()} className={className}>
{endDatetime && formatDateRange(datetime, endDatetime, language, timezone)}
{formatDate(datetime, language, timeRange, timezone, isTimeHeader, endDatetime)}
</time>
);
}
9 changes: 1 addition & 8 deletions web/src/features/charts/tooltips/AreaGraphTooltipHeader.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,15 @@ import { HorizontalDivider } from 'components/Divider';
import EstimationBadge from 'components/EstimationBadge';
import { FormattedTime } from 'components/Time';
import { useGetEstimationTranslation } from 'hooks/getEstimationTranslation';
import { useAtomValue } from 'jotai';
import { CircleDashed, TrendingUpDown } from 'lucide-react';
import { useTranslation } from 'react-i18next';
import { EstimationMethods, TimeRange } from 'utils/constants';
import { endDatetimeAtom } from 'utils/state/atoms';
import { EstimationMethods } from 'utils/constants';

import ProductionSourceIcon from '../ProductionsSourceIcons';

interface AreaGraphToolTipHeaderProps {
squareColor: string;
datetime: Date;
timeRange: TimeRange;
title: string;
hasEstimationPill?: boolean;
estimatedPercentage?: number;
Expand All @@ -24,7 +21,6 @@ interface AreaGraphToolTipHeaderProps {
export default function AreaGraphToolTipHeader({
squareColor,
datetime,
timeRange,
title,
hasEstimationPill = false,
estimatedPercentage,
Expand All @@ -37,7 +33,6 @@ export default function AreaGraphToolTipHeader({
estimationMethod,
estimatedPercentage
);
const endDatetime = useAtomValue(endDatetimeAtom);
return (
<>
<div className="flex items-center gap-1 font-bold">
Expand All @@ -60,10 +55,8 @@ export default function AreaGraphToolTipHeader({
)}
</div>
<FormattedTime
endDatetime={endDatetime}
datetime={datetime}
language={i18n.languages[0]}
timeRange={timeRange}
className="text-sm"
/>
<HorizontalDivider />
Expand Down
33 changes: 14 additions & 19 deletions web/src/features/time/HistoricalTimeHeader.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,6 @@
import { Button } from 'components/Button';
import {
NewFeaturePopover,
POPOVER_ID,
} from 'components/NewFeaturePopover/NewFeaturePopover';
import { NewFeaturePopoverContent } from 'components/NewFeaturePopover/NewFeaturePopoverContent';
import { FormattedTime } from 'components/Time';
import { useFeatureFlag } from 'features/feature-flags/api';
import { addDays, subDays, subHours } from 'date-fns';
import { useAtomValue } from 'jotai';
import { ArrowRightToLine, ChevronLeft, ChevronRight } from 'lucide-react';
import { useMemo } from 'react';
Expand All @@ -25,20 +20,17 @@ export default function HistoricalTimeHeader() {
const isHourly = useAtomValue(isHourlyAtom);
const { urlDatetime } = useParams<RouteParameters>();
const navigate = useNavigateWithParameters();
const isNewFeaturePopoverEnabled = useFeatureFlag(POPOVER_ID);

const isWithinHistoricalLimit = useMemo(() => {
if (!urlDatetime) {
return true;
}

const targetDate = new Date(urlDatetime);
targetDate.setUTCHours(targetDate.getUTCDate() - 1);
let targetDate = new Date(urlDatetime);
let maxHistoricalDate = new Date();

const maxHistoricalDate = new Date();
maxHistoricalDate.setUTCDate(
maxHistoricalDate.getUTCDate() - MAX_HISTORICAL_LOOKBACK_DAYS
);
targetDate = subDays(targetDate, 1);
maxHistoricalDate = subDays(maxHistoricalDate, MAX_HISTORICAL_LOOKBACK_DAYS);

return targetDate >= maxHistoricalDate;
}, [urlDatetime]);
Expand All @@ -52,11 +44,12 @@ export default function HistoricalTimeHeader() {
});

const currentEndDatetime = new Date(endDatetime);
const nextDay = new Date(currentEndDatetime);
nextDay.setUTCDate(nextDay.getUTCDate() + 1);

const fourHoursAgo = new Date();
fourHoursAgo.setUTCHours(fourHoursAgo.getUTCHours() - 4);
let nextDay = new Date(currentEndDatetime);
nextDay = addDays(nextDay, 1);

let fourHoursAgo = new Date();
fourHoursAgo = subHours(fourHoursAgo, 4);

if (nextDay >= fourHoursAgo) {
navigate({ datetime: '' });
Expand All @@ -74,8 +67,8 @@ export default function HistoricalTimeHeader() {
});

const currentEndDatetime = new Date(endDatetime);
const previousDay = new Date(currentEndDatetime);
previousDay.setUTCDate(previousDay.getUTCDate() - 1);
let previousDay = new Date(currentEndDatetime);
previousDay = subDays(previousDay, 1);

navigate({ datetime: previousDay.toISOString() });
}
Expand All @@ -94,6 +87,7 @@ export default function HistoricalTimeHeader() {
datetime={startDatetime}
language={i18n.languages[0]}
endDatetime={endDatetime}
isTimeHeader
className="text-sm font-semibold"
/>
</div>
Expand Down Expand Up @@ -123,6 +117,7 @@ export default function HistoricalTimeHeader() {
<FormattedTime
datetime={startDatetime}
language={i18n.languages[0]}
isTimeHeader
endDatetime={endDatetime}
className="text-sm font-semibold"
/>
Expand Down
48 changes: 24 additions & 24 deletions web/src/utils/__snapshots__/formatting.test.ts.snap
Original file line number Diff line number Diff line change
@@ -1,49 +1,49 @@
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html

exports[`formatDate > handles daily data for de 1`] = `"1. Januar 2021"`;
exports[`formatDate > handles daily data for de 1`] = `"1.–2. Januar 2021"`;

exports[`formatDate > handles daily data for en 1`] = `"January 1, 2021"`;
exports[`formatDate > handles daily data for en 1`] = `"January 1 – 2, 2021"`;

exports[`formatDate > handles daily data for es 1`] = `"1 de enero de 2021"`;
exports[`formatDate > handles daily data for es 1`] = `"1–2 de enero de 2021"`;

exports[`formatDate > handles daily data for fr 1`] = `"1 janvier 2021"`;
exports[`formatDate > handles daily data for fr 1`] = `"1–2 janvier 2021"`;

exports[`formatDate > handles daily data for it 1`] = `"1 gennaio 2021"`;
exports[`formatDate > handles daily data for it 1`] = `"01–02 gennaio 2021"`;

exports[`formatDate > handles daily data for sv 1`] = `"1 januari 2021"`;
exports[`formatDate > handles daily data for sv 1`] = `"1–2 januari 2021"`;

exports[`formatDate > handles hourly data for de 1`] = `"1. Jan. 2021, 01:00 MEZ"`;
exports[`formatDate > handles hourly data for de 1`] = `"1. Jan. 2021, 00:00–01:00 Uhr UTC"`;

exports[`formatDate > handles hourly data for en 1`] = `"Jan 1, 2021, 1:00 AM GMT+1"`;
exports[`formatDate > handles hourly data for en 1`] = `"Jan 1, 2021, 12:00 – 1:00AM UTC"`;

exports[`formatDate > handles hourly data for es 1`] = `"1 ene 2021, 1:00 CET"`;
exports[`formatDate > handles hourly data for es 1`] = `"1 ene 2021, 0:00–1:00 UTC"`;

exports[`formatDate > handles hourly data for fr 1`] = `"1 janv. 2021, 01:00 UTC+1"`;
exports[`formatDate > handles hourly data for fr 1`] = `"1 janv. 2021, 00:00 – 01:00 UTC"`;

exports[`formatDate > handles hourly data for it 1`] = `"1 gen 2021, 01:00 CET"`;
exports[`formatDate > handles hourly data for it 1`] = `"1 gen 2021, 00:00–01:00 UTC"`;

exports[`formatDate > handles hourly data for sv 1`] = `"1 jan. 2021 01:00 CET"`;
exports[`formatDate > handles hourly data for sv 1`] = `"1 jan. 2021 00:00–01:00 UTC"`;

exports[`formatDate > handles monthly data for de 1`] = `"Januar 2021"`;
exports[`formatDate > handles monthly data for de 1`] = `"Januar–Februar 2021"`;

exports[`formatDate > handles monthly data for en 1`] = `"January 2021"`;
exports[`formatDate > handles monthly data for en 1`] = `"January – February 2021"`;

exports[`formatDate > handles monthly data for es 1`] = `"enero de 2021"`;
exports[`formatDate > handles monthly data for es 1`] = `"enero–febrero de 2021"`;

exports[`formatDate > handles monthly data for fr 1`] = `"janvier 2021"`;
exports[`formatDate > handles monthly data for fr 1`] = `"janvier – février 2021"`;

exports[`formatDate > handles monthly data for it 1`] = `"gennaio 2021"`;
exports[`formatDate > handles monthly data for it 1`] = `"gennaio–febbraio 2021"`;

exports[`formatDate > handles monthly data for sv 1`] = `"januari 2021"`;
exports[`formatDate > handles monthly data for sv 1`] = `"januari–februari 2021"`;

exports[`formatDate > handles yearly data for de 1`] = `"2021"`;
exports[`formatDate > handles yearly data for de 1`] = `"2021–2022"`;

exports[`formatDate > handles yearly data for en 1`] = `"2021"`;
exports[`formatDate > handles yearly data for en 1`] = `"2021 – 2022"`;

exports[`formatDate > handles yearly data for es 1`] = `"2021"`;
exports[`formatDate > handles yearly data for es 1`] = `"2021–2022"`;

exports[`formatDate > handles yearly data for fr 1`] = `"2021"`;
exports[`formatDate > handles yearly data for fr 1`] = `"2021–2022"`;

exports[`formatDate > handles yearly data for it 1`] = `"2021"`;
exports[`formatDate > handles yearly data for it 1`] = `"2021–2022"`;

exports[`formatDate > handles yearly data for sv 1`] = `"2021"`;
exports[`formatDate > handles yearly data for sv 1`] = `"2021–2022"`;
2 changes: 2 additions & 0 deletions web/src/utils/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ import { ElectricityModeType } from 'types';
export const metaTitleSuffix = ' | App | Electricity Maps';
export const baseUrl = 'https://app.electricitymaps.com';

export const UTC = 'UTC';

// The order here determines the order displayed
export enum TimeRange {
H24 = '24h',
Expand Down
2 changes: 1 addition & 1 deletion web/src/utils/formatting.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -496,7 +496,7 @@ describe('formatDate', () => {
'en',
'ThisAggregateDoesNotExist' as TimeRange
);
const expected = '1/1/2021';
const expected = '';
expect(actual).to.deep.eq(expected);
expect(consoleErrorSpy).toHaveBeenCalledWith(
'ThisAggregateDoesNotExist is not implemented'
Expand Down
Loading
Loading