diff --git a/packages/app/src/components/time-series-chart/components/axes/components/axes.tsx b/packages/app/src/components/time-series-chart/components/axes/components/axes.tsx index 570bb8f5b4..2f407053db 100644 --- a/packages/app/src/components/time-series-chart/components/axes/components/axes.tsx +++ b/packages/app/src/components/time-series-chart/components/axes/components/axes.tsx @@ -15,7 +15,7 @@ import { isPresent } from 'ts-is-present'; import { memo, Ref, useCallback, useMemo } from 'react'; import { NumberValue, ScaleBand, ScaleLinear } from 'd3-scale'; import { scaleLinear } from '@visx/scale'; -import { TickInstance, createTimeTicks, createTimeTicksAllTimeFrame, createTimeTicksMonthlyTimeFrame } from '../logic/create-time-ticks'; +import { TickInstance, createTimeTicks, createTimeTicksAllTimeFrame, createTimeTicksMonthlyTimeFrame, getPrefferedTimeTicksAllTimeFrame } from '../logic/create-time-ticks'; import { useBreakpoints } from '~/utils/use-breakpoints'; import { useIntl } from '~/intl'; import { WeekNumbers } from '../../week-numbers'; @@ -100,21 +100,6 @@ export const Axes = memo(function Axes({ const formatYAxisPercentage: TickFormatter = useCallback((y: NumberValue) => `${formatPercentage(y as number)}%`, [formatPercentage]); - const prefferedDateTicksAllTimeFrame = () => { - /** - * This method gets the difference in years between endUnix and startUnix. - * The result is divided by 31557600 and rounded UP with .ceil - * 31557600 is calculated based on 86400 (seconds in a day) - * multiplied by 365.25 (number of days in a year and .25 to consider leap years) - * - * This logic is used to calculate the amount of January 1st dates the algorithm needs - * for displaying "all" timeframe. - */ - const yearsDifferenceInDomain = Math.ceil((endUnix - startUnix) / 31557600); - - return yearsDifferenceInDomain; - }; - const bottomAxesTickNumber = useMemo(() => { let value = 2; if (!isPresent(xTickNumber)) { @@ -124,23 +109,23 @@ export const Axes = memo(function Axes({ if (hasDatesAsRange) { value = 4; } else { - value = prefferedDateTicksAllTimeFrame(); + value = getPrefferedTimeTicksAllTimeFrame(startUnix, endUnix); } break; case TimeframeOption.THIRTY_DAYS: value = breakpoints.sm ? (hasDatesAsRange ? 4 : 5) : 4; break; case TimeframeOption.THREE_MONTHS: - value = 3; + value = breakpoints.sm ? (hasDatesAsRange ? 4 : 6) : 4; break; case TimeframeOption.SIX_MONTHS: - value = breakpoints.sm ? (hasDatesAsRange ? 4 : 6) : 4; + value = 4; break; case TimeframeOption.LAST_YEAR: value = breakpoints.sm ? (hasDatesAsRange ? 3 : 5) : 4; break; default: - value = 2; + value = 4; } } return value; diff --git a/packages/app/src/components/time-series-chart/components/axes/logic/create-time-ticks.ts b/packages/app/src/components/time-series-chart/components/axes/logic/create-time-ticks.ts index d9f5d2221c..9a21339946 100644 --- a/packages/app/src/components/time-series-chart/components/axes/logic/create-time-ticks.ts +++ b/packages/app/src/components/time-series-chart/components/axes/logic/create-time-ticks.ts @@ -1,11 +1,39 @@ import { Breakpoints } from '~/utils/use-breakpoints'; -import { subtractMonthToDate, extractYearFromDate, formatStyle, getFirstDayOfGivenYear, middleOfDayInSeconds, startOfDayInSeconds } from '@corona-dashboard/common'; +import { + subtractMonthToDate, + extractYearFromDate, + formatStyle, + getFirstDayOfGivenYear, + middleOfDayInSeconds, + startOfDayInSeconds, + extractMonthFromDate, + extractDayFromDate, +} from '@corona-dashboard/common'; export interface TickInstance { timestamp: number; formatStyle: formatStyle; } +export function getPrefferedTimeTicksAllTimeFrame(startUnix: number, endUnix: number): number { + /** + * For the All timeframe we are interested in the amount of January 1st dates inbetween + * startUnix and endUnix (e.g 07.09.2020 - 31.01.2024 will results in 4 ticks). + * + * The way it works is that we first check if the startDate is equal to January 1st. + * If so, the count will get +1 at the end since the start year is not included when + * making the difference between the endYear and startYear + * + * This function is used in the Axes component where the bottomAxesTickNumber value + * is being generated. + */ + const firstYearFirstOfJanuary = extractMonthFromDate(startUnix) == 0 && extractDayFromDate(startUnix) == 1; + + const count = extractYearFromDate(endUnix) - extractYearFromDate(startUnix); + + return firstYearFirstOfJanuary ? count + 1 : count; +} + function getDefault2ValuesForXAxis(startTick: number, endTick: number): TickInstance[] { return [ { timestamp: startTick, formatStyle: 'axis-with-day-month-year-short' }, @@ -25,13 +53,13 @@ export function createTimeTicksAllTimeFrame(startTick: number, endTick: number, return getDefault2ValuesForXAxis(start, end); } - const ticks: TickInstance[] = Array.from({ length: ticksNumber }, (_, index) => { + const ticks: TickInstance[] = Array.from({ length: ticksNumber }, (_, index = 1) => { const firstDayOfYearTimeStamp = getFirstDayOfGivenYear(startYear + index + 1); // 01.01.2021, 01.01.2022... etc. return { timestamp: startOfDayInSeconds(firstDayOfYearTimeStamp), formatStyle: 'axis-with-day-month-year-short' } as TickInstance; }); // This if statement ensures that first & second label of the all-values timeframe don't overlap - if (breakpoints.lg) { + if (breakpoints.lg && Math.floor((ticks[0].timestamp - startTick) / 86400) > 180) { ticks.unshift({ timestamp: start, formatStyle: 'axis-with-month-year-short' } as TickInstance); } diff --git a/packages/app/src/utils/create-date-from-custom-input.ts b/packages/app/src/utils/create-date-from-custom-input.ts new file mode 100644 index 0000000000..b60d2bd187 --- /dev/null +++ b/packages/app/src/utils/create-date-from-custom-input.ts @@ -0,0 +1,6 @@ +/** + * Some business logic requires dates with specific year/month/day + */ +export function createDateFromCustomInput(year: number, month = 0, day = 1) { + return new Date(year, month, day); +} diff --git a/packages/common/src/data-sorting.ts b/packages/common/src/data-sorting.ts index 49adc4fad8..69f2bd49fa 100644 --- a/packages/common/src/data-sorting.ts +++ b/packages/common/src/data-sorting.ts @@ -249,6 +249,16 @@ export function extractYearFromDate(seconds: number) { return date.getFullYear(); } +export function extractMonthFromDate(seconds: number) { + const date = new Date(seconds * 1000); + return date.getMonth(); +} + +export function extractDayFromDate(seconds: number) { + const date = new Date(seconds * 1000); + return date.getDay(); +} + export function getFirstDayOfGivenYear(year: number) { const date = new Date(year, 0, 1); return Math.floor(date.getTime() / 1000);