From 9f64169cd845c979dafc61c89989d0169367e7f9 Mon Sep 17 00:00:00 2001 From: Richard Dinh Date: Mon, 11 Mar 2024 23:10:55 -0400 Subject: [PATCH] painful date manipulation --- src/reducers/query/query.js | 48 ++++++++++-------- src/reducers/query/query.spec.js | 86 ++++++++++++++------------------ src/utils/index.js | 21 ++++---- 3 files changed, 78 insertions(+), 77 deletions(-) diff --git a/src/reducers/query/query.js b/src/reducers/query/query.js index 24ac33d4..72e2c541 100644 --- a/src/reducers/query/query.js +++ b/src/reducers/query/query.js @@ -6,6 +6,7 @@ import { coalesce, enablePer1000, processUrlArrayParams, + shortIsoFormat, startOfToday, } from '../../utils'; import { enforceValues, validateTrendsReducer } from '../../utils/reducers'; @@ -17,7 +18,7 @@ import { REQUERY_HITS_ONLY, REQUERY_NEVER, } from '../../constants'; -import { formatDate, formatDateModel } from '../../utils/formatDate'; +import { formatDateModel } from '../../utils/formatDate'; const queryString = require('query-string'); @@ -28,10 +29,10 @@ export const queryState = { dataNormalization: types.GEO_NORM_NONE, dateInterval: 'Month', dateRange: '3y', - date_received_max: startOfToday(), - date_received_min: formatDate( + date_received_max: dayjs(startOfToday()).toISOString(), + date_received_min: dayjs( new Date(dayjs(startOfToday()).subtract(3, 'years')), - ), + ).toISOString(), enablePer1000: false, focus: '', from: 0, @@ -176,13 +177,13 @@ export const querySlice = createSlice({ // eslint-disable-next-line complexity reducer: (state, action) => { const dateRange = enforceValues(action.payload.dateRange, 'dateRange'); - const maxDate = startOfToday(); + const maxDate = dayjs(startOfToday()).toISOString(); const res = { - All: types.DATE_RANGE_MIN, - '3m': formatDate(dayjs(maxDate).subtract(3, 'months')), - '6m': formatDate(dayjs(maxDate).subtract(6, 'months')), - '1y': formatDate(dayjs(maxDate).subtract(1, 'year')), - '3y': formatDate(dayjs(maxDate).subtract(3, 'years')), + All: dayjs(types.DATE_RANGE_MIN).toISOString(), + '3m': dayjs(maxDate).subtract(3, 'months').toISOString(), + '6m': dayjs(maxDate).subtract(6, 'months').toISOString(), + '1y': dayjs(maxDate).subtract(1, 'year').toISOString(), + '3y': dayjs(maxDate).subtract(3, 'years').toISOString(), }; state.dateRange = dateRange; state.date_received_min = res[dateRange] @@ -226,10 +227,10 @@ export const querySlice = createSlice({ } minDate = dayjs(minDate).isValid() - ? formatDate(dayjs(minDate).startOf('day')) + ? dayjs(minDate).startOf('day').toISOString() : null; maxDate = dayjs(maxDate).isValid() - ? formatDate(dayjs(maxDate).startOf('day')) + ? dayjs(maxDate).startOf('day').toISOString() : null; const datesChanged = @@ -462,8 +463,8 @@ export const querySlice = createSlice({ // adjust date filter for max and min ranges state.dateRange = 'All'; /* eslint-disable camelcase */ - state.date_received_min = formatDate(types.DATE_RANGE_MIN); - state.date_received_max = formatDate(startOfToday()); + state.date_received_min = types.DATE_RANGE_MIN; + state.date_received_max = startOfToday(); state.focus = ''; state.queryString = stateToQS(state); state.search = stateToURL(state); @@ -900,10 +901,10 @@ export function alignDateRange(state) { } const rangeMap = { - '3y': formatDate(dayjs(dateMax).subtract(3, 'years')), - '3m': formatDate(dayjs(dateMax).subtract(3, 'months')), - '6m': formatDate(dayjs(dateMax).subtract(6, 'months')), - '1y': formatDate(dayjs(dateMax).subtract(1, 'year')), + '3y': dayjs(dateMax).subtract(3, 'years'), + '3m': dayjs(dateMax).subtract(3, 'months'), + '6m': dayjs(dateMax).subtract(6, 'months'), + '1y': dayjs(dateMax).subtract(1, 'year'), }; const ranges = Object.keys(rangeMap); let matched = false; @@ -1082,7 +1083,7 @@ export function stateToQS(state) { // Process dates if (types.dateFilters.indexOf(field) !== -1) { - value = formatDate(value); + value = shortIsoFormat(value); } // Process boolean flags @@ -1177,7 +1178,14 @@ export function stateToURL(state) { if (['queryString', 'url', 'breakPoints'].includes(field)) { return; } - params[field] = state[field]; + + let value = state[field]; + + // Process date filters url-friendly display + if (types.dateFilters.indexOf(field) !== -1) { + value = shortIsoFormat(value); + } + params[field] = value; }); // list of API params diff --git a/src/reducers/query/query.spec.js b/src/reducers/query/query.spec.js index 135e4a8c..7ea58415 100644 --- a/src/reducers/query/query.spec.js +++ b/src/reducers/query/query.spec.js @@ -42,15 +42,15 @@ import { updateDataSubLens, } from '../trends/trends'; import { formatDate } from '../../utils/formatDate'; -import { processHitsResults } from '../results/results'; +import { complaintsReceived } from '../results/results'; const maxDate = startOfToday(); describe('reducer:query', () => { - let action, result, state; - const test_date_received_max = maxDate; - const test_date_received_min = new Date( - dayjs(startOfToday()).subtract(3, 'years'), + let result, state; + const test_date_received_max = dayjs(maxDate).toISOString(); + const test_date_received_min = dayjs( + new Date(dayjs(startOfToday()).subtract(3, 'years')).toISOString(), ); describe('default', () => { it('has a default state', () => { @@ -61,17 +61,14 @@ describe('reducer:query', () => { dataNormalization: types.GEO_NORM_NONE, dateInterval: 'Month', dateRange: '3y', - date_received_max: test_date_received_max, - date_received_min: test_date_received_min, + date_received_max: '2020-05-05T04:00:00.000Z', + date_received_min: '2017-05-05T04:00:00.000Z', enablePer1000: false, focus: '', from: 0, lens: 'Product', mapWarningEnabled: true, - queryString: - '?date_received_max=2020-05-05&date_received_min=' + - '2017-05-05&field=all&lens=product&sub_lens=sub_product&' + - 'trend_depth=5&trend_interval=month', + queryString: '', searchText: '', searchField: 'all', page: 1, @@ -83,28 +80,25 @@ describe('reducer:query', () => { totalPages: 0, trendDepth: 5, trendsDateWarningEnabled: false, - search: - '?chartType=line&dateInterval=Month&dateRange=3y&date_received_max=2020-05-05&date_received_min=2017-05-05&lens=Product&searchField=all&subLens=sub_product&tab=Trends', + search: '', }); }); }); describe('COMPLAINTS_RECEIVED actions', () => { it('updates total number of pages', () => { - action = { - data: { - _meta: { - break_points: { - 2: [2, 2], - 3: [3, 2], - 4: [4, 2], - 5: [5, 2], - }, - }, - hits: { - total: { value: 10000 }, + const payload = { + _meta: { + break_points: { + 2: [2, 2], + 3: [3, 2], + 4: [4, 2], + 5: [5, 2], }, }, + hits: { + total: { value: 10000 }, + }, }; state = { @@ -114,7 +108,7 @@ describe('reducer:query', () => { totalPages: 5, }; - expect(target(state, processHitsResults(action))).toEqual({ + expect(target(state, complaintsReceived(payload))).toEqual({ ...state, breakPoints: { 2: [2, 2], @@ -130,20 +124,18 @@ describe('reducer:query', () => { }); it('limits the current page correctly', () => { - action = { - data: { - _meta: { - break_points: { - 2: [2, 2], - 3: [3, 2], - 4: [4, 2], - 5: [5, 2], - }, - }, - hits: { - total: { value: 10000 }, + const payload = { + _meta: { + break_points: { + 2: [2, 2], + 3: [3, 2], + 4: [4, 2], + 5: [5, 2], }, }, + hits: { + total: { value: 10000 }, + }, }; state = { @@ -152,7 +144,7 @@ describe('reducer:query', () => { size: 100, }; - expect(target(state, processHitsResults(action))).toEqual({ + expect(target(state, complaintsReceived(payload))).toEqual({ ...state, breakPoints: { 2: [2, 2], @@ -1423,8 +1415,8 @@ describe('reducer:query', () => { ).toEqual({ ...testState, breakPoints: {}, - date_received_min: new Date(2001, 0, 30), - date_received_max: new Date(2013, 1, 3), + date_received_min: '2001-01-30T05:00:00.000Z', + date_received_max: '2013-02-03T05:00:00.000Z', from: 0, page: 1, queryString: @@ -1489,9 +1481,7 @@ describe('reducer:query', () => { it('handles All range', () => { action = 'All'; result = target({}, changeDateRange(action)); - expect(result.date_received_min).toEqual( - new Date(types.DATE_RANGE_MIN), - ); + expect(result.date_received_min).toEqual('2011-12-01T12:00:00.000Z'); }); it('handles 1y range', () => { @@ -1502,8 +1492,8 @@ describe('reducer:query', () => { breakPoints: {}, dateInterval: 'Month', dateRange: '1y', - date_received_max: new Date('2020-05-05T04:00:00.000Z'), - date_received_min: new Date('2019-05-05T04:00:00.000Z'), + date_received_max: '2020-05-05T04:00:00.000Z', + date_received_min: '2019-05-05T04:00:00.000Z', from: 0, page: 1, queryString: @@ -1523,8 +1513,8 @@ describe('reducer:query', () => { ...queryState, breakPoints: {}, dateRange: '3y', - date_received_min: new Date('2017-05-05T04:00:00.000Z'), - date_received_max: new Date('2020-05-05T04:00:00.000Z'), + date_received_min: '2017-05-05T04:00:00.000Z', + date_received_max: '2020-05-05T04:00:00.000Z', from: 0, page: 1, queryString: diff --git a/src/utils/index.js b/src/utils/index.js index b19a1ca8..e2487d6c 100644 --- a/src/utils/index.js +++ b/src/utils/index.js @@ -6,7 +6,6 @@ import { } from '../constants/index'; import Analytics from '../actions/analytics'; import dayjs from 'dayjs'; -import { formatDate } from './formatDate'; /** * Breaks up '123' to '1 2 3' to help screen readers read digits individually @@ -25,15 +24,14 @@ export function ariaReadoutNumbers(digits) { export const calculateDateRange = (minDate, maxDate) => { // only check intervals if the end date is today // round off the date so the partial times don't mess up calculations - // const today = startOfToday(); + const today = startOfToday(); const end = dayjs(maxDate).startOf('day'); const start = dayjs(minDate).startOf('day'); - /* Commenting this out because it seems to run contrary to expected behavior in the tests */ // make sure end date is the same as today's date - //if (end.diff(today, 'days') !== 0) { - // return ''; - //} + if (end.diff(today, 'days') !== 0) { + return ''; + } // is the start date the same as the oldest document? if (dayjs(minDate).isSame(DATE_RANGE_MIN, 'day')) { @@ -259,11 +257,16 @@ export function shortFormat(date) { /** * Convert a date to a truncated ISO-8601 string * - * @param {Date} date - the date to convert + * @param {string | object | Date} date - the date to convert * @returns {string} the date formatted as yyyy-mm-ddd */ export function shortIsoFormat(date) { - return date ? date.toISOString().substring(0, 10) : ''; + if (typeof date === 'string') { + return date ? date.slice(0, 10) : ''; + } else if (typeof date === 'object') { + return dayjs(date).toISOString().slice(0, 10); + } + return date; } /** @@ -286,7 +289,7 @@ export function startOfToday() { } // Always return a clone so the global is not exposed or changed - return formatDate(new Date(window.MAX_DATE)); + return new Date(window.MAX_DATE.valueOf()); } // ----------------------------------------------------------------------------