From 655abbb7c76fecee4f4f5737fc62f2968ec7aac1 Mon Sep 17 00:00:00 2001 From: Erwan Guyader Date: Mon, 10 Oct 2022 08:34:56 +0200 Subject: [PATCH] deps: Upgrade date-fns to v2.29.3 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We want to use the `add` and `sub` functions that are not available in v1.30.1. Since there's a large gap between the two versions, we have a lot of modifications to accomodate API changes: - imports of functions whose names are made of multiple words have changed from a snake case format to a camel case one - locales are not exposed as separate modules anymore; they need to be imported from `date-fns/locales` - the format used by `format()` and `parse()` is now based on Unicode Technical Standard #35 (see https://www.unicode.org/reports/tr35/tr35-dates.html#Date_Field_Symbol_Table) with a few additions (see https://date-fns.org/v2.29.3/docs/format) → `YYYY` becomes `yyyy` → `D` becomes `d` → `DD` becomes `dd` → `ddd` becomes `EEE` → the escape character is now `'` (single quote) instead of `[` - all `date-fns` functions now require arguments to be `Date` objects or numbers and do not accept strings anymore. Therefore, all date strings are now parsed before being passed as `date-fns` function arguments and all test data mocks have been updated to use only ISO formatted date strings - `isWithinRange` becomes `isWithinInterval` which is inclusive (i.e. `isWithinRange(3, 1, 3) === false` vs `isWithinInterval(3, { start: 1, end: 3 }) === true`) --- package.json | 2 +- scripts/visualizer/static/form.js | 11 +-- src/components/SelectDates/SelectDates.jsx | 7 +- src/components/SelectDates/utils.js | 6 +- src/doctypes.js | 4 +- src/ducks/account/helpers.js | 9 ++- src/ducks/account/helpers.spec.js | 4 +- src/ducks/balance/History.jsx | 6 +- src/ducks/balance/helpers.js | 27 ++++--- src/ducks/balance/helpers.spec.js | 31 ++++---- src/ducks/billsMatching/Linker/Linker.js | 3 +- src/ducks/billsMatching/Linker/Linker.spec.js | 20 +++--- .../Linker/billsToOperation/helpers.js | 12 ++-- .../Linker/billsToOperation/helpers.spec.js | 26 +++---- .../billsToOperation/operationsFilters.js | 10 ++- .../operationsFilters.spec.js | 43 ++++++----- src/ducks/billsMatching/matchFromBills.js | 5 +- .../billsMatching/matchFromTransactions.js | 14 ++-- .../matchFromTransactions.spec.js | 6 +- src/ducks/budgetAlerts/index.js | 12 ++-- src/ducks/categorization/services.js | 3 +- src/ducks/chart/selectors.js | 8 ++- src/ducks/filters/index.js | 30 +++++--- src/ducks/future/selectors.js | 10 +-- src/ducks/notifications/DelayedDebit/index.js | 11 +-- .../LateHealthReimbursement/index.js | 18 +++-- .../LateHealthReimbursement/index.spec.js | 10 +-- .../notifications/TransactionGreater/index.js | 2 +- src/ducks/notifications/index.js | 7 +- src/ducks/recurrence/Bundles.jsx | 10 ++- src/ducks/recurrence/DateSlider.jsx | 2 +- src/ducks/recurrence/service.js | 2 +- src/ducks/recurrence/utils.js | 10 +-- src/ducks/reimbursements/Reimbursements.jsx | 7 +- .../reimbursements/ReimbursementsPage.jsx | 17 +++-- src/ducks/search/EarliestTransactionDate.jsx | 6 +- src/ducks/search/SearchPage.jsx | 2 +- .../TransactionModal.spec.jsx | 2 +- .../TransactionModalInfoContent.jsx | 20 ++++-- .../transactions/TransactionModal/helpers.js | 4 +- .../TransactionRow/TransactionDate.jsx | 13 +++- .../transactions/TransactionSelectDates.jsx | 25 +++---- .../TransactionSelectDates.spec.jsx | 12 ++-- src/ducks/transactions/Transactions.jsx | 2 + src/ducks/transactions/helpers.js | 40 +++++++---- src/ducks/transactions/queries.js | 14 ++-- src/ducks/transfers/transfers.js | 2 +- .../konnectorAlerts/createTriggerAt.js | 7 +- .../konnectorAlerts/createTriggerAt.spec.js | 9 ++- .../services/konnectorAlerts/helpers.js | 19 +---- .../services/konnectorAlerts/helpers.spec.js | 72 +++---------------- .../services/konnectorAlerts/shouldNotify.js | 6 +- .../konnectorAlerts/shouldNotify.spec.js | 2 +- src/utils/token.js | 4 +- test/fixtures/helpers/freshDate.js | 4 +- yarn.lock | 7 +- 56 files changed, 352 insertions(+), 325 deletions(-) diff --git a/package.json b/package.json index 9ea1da7d57..296eb9bd41 100644 --- a/package.json +++ b/package.json @@ -179,7 +179,7 @@ "cozy-stack-client": "33.2.0", "cozy-ui": "^75.4.0", "d3": "5.11.0", - "date-fns": "1.30.1", + "date-fns": "2.29.3", "detect-node": "2.0.4", "diacritics": "^1.3.0", "element-scroll-polyfill": "1.0.1", diff --git a/scripts/visualizer/static/form.js b/scripts/visualizer/static/form.js index 8bccfe7785..58ec9b5c75 100644 --- a/scripts/visualizer/static/form.js +++ b/scripts/visualizer/static/form.js @@ -1,5 +1,6 @@ -import { format, parse } from 'date-fns' -import frLocale from 'date-fns/locale/fr' +import format from 'date-fns/format' +import parseISO from 'date-fns/parseISO' +import { fr as frLocale } from 'date-fns/locale' const serialize = formData => { const res = {} @@ -10,13 +11,13 @@ const serialize = formData => { } function formatDate(d) { - return `${format(parse(d), 'D MMM YYYY', { + return `${format(parseISO(d), 'd MMM yyyy', { locale: frLocale })}` } const comp = fn => { - return function(a, b) { + return function (a, b) { const resa = fn(a) const resb = fn(b) if (resa == resb) { @@ -108,7 +109,7 @@ const renderText = results => { ) } -const renderResults = function(results) { +const renderResults = function (results) { results = JSON.parse(results) const node = document.querySelector('#results') node.innerHTML = `${renderText(results)}` diff --git a/src/components/SelectDates/SelectDates.jsx b/src/components/SelectDates/SelectDates.jsx index ae06f23276..1ad951cb0a 100644 --- a/src/components/SelectDates/SelectDates.jsx +++ b/src/components/SelectDates/SelectDates.jsx @@ -8,7 +8,8 @@ import findLast from 'lodash/findLast' import find from 'lodash/find' import uniqBy from 'lodash/uniqBy' -import { format, parse } from 'date-fns' +import format from 'date-fns/format' +import parse from 'date-fns/parse' import { translate } from 'cozy-ui/transpiled/react/I18n' import withBreakpoints from 'cozy-ui/transpiled/react/helpers/withBreakpoints' @@ -147,8 +148,8 @@ class SelectDates extends PureComponent { // create options const { f, options } = this.props return options.map(option => { - const date = parse(option.yearMonth, 'YYYY-MM') - const year = format(date, 'YYYY') + const date = parse(option.yearMonth, 'yyyy-MM', new Date()) + const year = format(date, 'yyyy') return { value: option.yearMonth, year, diff --git a/src/components/SelectDates/utils.js b/src/components/SelectDates/utils.js index ac8774955f..582dfaf6bb 100644 --- a/src/components/SelectDates/utils.js +++ b/src/components/SelectDates/utils.js @@ -1,6 +1,6 @@ -import startOfMonth from 'date-fns/start_of_month' -import addMonths from 'date-fns/add_months' -import isSameDay from 'date-fns/is_same_day' +import startOfMonth from 'date-fns/startOfMonth' +import addMonths from 'date-fns/addMonths' +import isSameDay from 'date-fns/isSameDay' const rangedSome = (arr, predicate, start, end) => { const realStart = Math.max(start, 0) diff --git a/src/doctypes.js b/src/doctypes.js index 48abfe1020..240438abf8 100644 --- a/src/doctypes.js +++ b/src/doctypes.js @@ -5,7 +5,7 @@ import CozyClient, { Q, HasMany } from 'cozy-client' -import subYears from 'date-fns/sub_years' +import subYears from 'date-fns/subYears' import format from 'date-fns/format' import flag from 'cozy-flags' @@ -305,7 +305,7 @@ export const transactionsConn = { } export const makeBalanceTransactionsConn = () => { - const fromDate = format(subYears(new Date(), 1), 'YYYY-MM-DD') + const fromDate = format(subYears(new Date(), 1), 'yyyy-MM-dd') return { as: 'home/transactions', fetchPolicy: neverReload, diff --git a/src/ducks/account/helpers.js b/src/ducks/account/helpers.js index 144bddeff5..312e4f0562 100644 --- a/src/ducks/account/helpers.js +++ b/src/ducks/account/helpers.js @@ -8,6 +8,10 @@ import compose from 'lodash/flowRight' import overEvery from 'lodash/overEvery' import sumBy from 'lodash/sumBy' import get from 'lodash/get' +import differenceInCalendarDays from 'date-fns/differenceInCalendarDays' +import isAfter from 'date-fns/isAfter' +import subMonths from 'date-fns/subMonths' +import parseISO from 'date-fns/parseISO' import { models } from 'cozy-client' import { @@ -21,7 +25,6 @@ import { isProfessionalExpense, getCategoryIdFromName } from 'ducks/categories/helpers' -import { differenceInCalendarDays, isAfter, subMonths } from 'date-fns' import { ACCOUNT_DOCTYPE, CONTACT_DOCTYPE } from 'doctypes' const { @@ -130,7 +133,7 @@ export const getAccountUpdatedAt = (account, jobTrigger) => { const updatedAtTrigger = triggerStates.getLastSuccess(jobTrigger) const updateDate = updatedAtTrigger || updatedAtAccount const updateDistance = updateDate - ? differenceInCalendarDays(today, updateDate) + ? differenceInCalendarDays(today, parseISO(updateDate)) : null const updateDistanceInWords = distanceInWords(updateDistance) @@ -160,7 +163,7 @@ const buildReimbursementsVirtualAccount = specs => transactions => { const combinedFilter = overEvery( [ specs.filter, - compose(isWithin6Months(), getDate), + compose(isWithin6Months(), parseISO, getDate), hasPendingReimbursement ].filter(Boolean) ) diff --git a/src/ducks/account/helpers.spec.js b/src/ducks/account/helpers.spec.js index 07252b8b4d..54dd01a842 100644 --- a/src/ducks/account/helpers.spec.js +++ b/src/ducks/account/helpers.spec.js @@ -28,7 +28,9 @@ describe('getAccountUpdatedAt', () => { }) const jobTrigger = triggersFixtures[1].attributes - const account = { cozyMetadata: { updatedAt: new Date(2019, 0, 10) } } + const account = { + cozyMetadata: { updatedAt: new Date(2019, 0, 10).toISOString() } + } it('should work when jobTrigger does not exist', () => { expect(getAccountUpdatedAt(account, null)).toEqual({ params: { nbDays: 2 }, diff --git a/src/ducks/balance/History.jsx b/src/ducks/balance/History.jsx index 9414944ca5..7813c23be8 100644 --- a/src/ducks/balance/History.jsx +++ b/src/ducks/balance/History.jsx @@ -1,6 +1,8 @@ import React, { Component } from 'react' import PropTypes from 'prop-types' -import { format as formatDate, subYears, isAfter } from 'date-fns' +import formatDate from 'date-fns/format' +import subYears from 'date-fns/subYears' +import isAfter from 'date-fns/isAfter' import memoize from 'lodash/memoize' import max from 'lodash/max' import groupBy from 'lodash/groupBy' @@ -97,7 +99,7 @@ class History extends Component { const data = this.getChartData() const nbTicks = uniq( - Object.keys(groupBy(data, i => formatDate(i.x, 'YYYY-MM'))) + Object.keys(groupBy(data, i => formatDate(i.x, 'yyyy-MM'))) ).length const intervalBetweenMonths = isMobile ? 52 : 89 diff --git a/src/ducks/balance/helpers.js b/src/ducks/balance/helpers.js index 61537764b9..1dc426bebb 100644 --- a/src/ducks/balance/helpers.js +++ b/src/ducks/balance/helpers.js @@ -3,15 +3,14 @@ import uniq from 'lodash/uniq' import sumBy from 'lodash/sumBy' import groupBy from 'lodash/groupBy' import flatten from 'lodash/flatten' -import { - min as getEarliestDate, - isAfter as isDateAfter, - isEqual as isDateEqual, - subDays, - parse as parseDate, - format as formatDate, - isValid as isDateValid -} from 'date-fns' +import getEarliestDate from 'date-fns/min' +import isDateAfter from 'date-fns/isAfter' +import isDateEqual from 'date-fns/isEqual' +import subDays from 'date-fns/subDays' +import parseISO from 'date-fns/parseISO' +import formatDate from 'date-fns/format' +import isDateValid from 'date-fns/isValid' + import { getAccountBalance } from 'ducks/account/helpers' import { isReimbursementsVirtualGroup } from 'ducks/groups/helpers' @@ -21,23 +20,23 @@ import { isReimbursementsVirtualGroup } from 'ducks/groups/helpers' * @param {Object[]} transactions - The transactions of the account * @param {Date} to - The date to which you want the history * @param {Date} from - The date from you want the history - * @returns {Object} The balance history indexed by dates (YYYY-MM-DD) + * @returns {Object} The balance history indexed by dates (yyyy-MM-dd) */ export const getBalanceHistory = (account, transactions, to, from) => { let clonedFrom = from - const DATE_FORMAT = 'YYYY-MM-DD' + const DATE_FORMAT = 'yyyy-MM-dd' const transactionsByDate = groupBy(transactions, t => formatDate( // do not take .realisationDate as we are interested in the debit date - t.date, + parseISO(t.date), DATE_FORMAT ) ) if (!clonedFrom) { const earliestTransactionDate = getEarliestDate( - ...Object.keys(transactionsByDate) + Object.keys(transactionsByDate).map(parseISO) ) clonedFrom = isDateValid(earliestTransactionDate) ? earliestTransactionDate @@ -147,7 +146,7 @@ export const balanceHistoryToChartData = history => { const dates = getAllDates([history]).sort() const data = dates.map(date => ({ - x: parseDate(date), + x: parseISO(date), y: history[date] })) diff --git a/src/ducks/balance/helpers.spec.js b/src/ducks/balance/helpers.spec.js index 19751bc8c6..f832e2f349 100644 --- a/src/ducks/balance/helpers.spec.js +++ b/src/ducks/balance/helpers.spec.js @@ -7,7 +7,8 @@ import { balanceHistoryToChartData, getPanelsState } from './helpers' -import { format as formatDate, parse as parseDate } from 'date-fns' +import formatDate from 'date-fns/format' +import parseISO from 'date-fns/parseISO' describe('filterTransactionsByAccount', () => { describe('With included relationship', () => { @@ -56,7 +57,7 @@ describe('getBalanceHistory', () => { const account = { _id: 'test', balance: 8000 } const transactions = [] const to = new Date() - const date = formatDate(to, 'YYYY-MM-DD') + const date = formatDate(to, 'yyyy-MM-dd') const history = getBalanceHistory(account, transactions, to) expect(Object.keys(history)).toEqual([date]) @@ -66,8 +67,8 @@ describe('getBalanceHistory', () => { it('should return the same balance for all dates if there is no transaction and from is specified', () => { const account = { _id: 'test', balance: 8000 } const transactions = [] - const to = parseDate('2018-06-26') - const from = parseDate('2018-06-24') + const to = parseISO('2018-06-26') + const from = parseISO('2018-06-24') const history = getBalanceHistory(account, transactions, to, from) expect(history).toEqual({ @@ -91,7 +92,7 @@ describe('getBalanceHistory', () => { amount: -15 } ] - const to = parseDate('2018-06-27') + const to = parseISO('2018-06-27') const history = getBalanceHistory(account, transactions, to) expect(history).toEqual({ @@ -112,8 +113,8 @@ describe('getBalanceHistory', () => { { date: '2018-06-23T00:00:00Z', amount: -300 }, { date: '2018-06-22T00:00:00Z', amount: -15 } ] - const to = parseDate('2018-06-26') - const from = parseDate('2018-06-24') + const to = parseISO('2018-06-26') + const from = parseISO('2018-06-24') const history = getBalanceHistory(account, transactions, to, from) expect(history).toEqual({ @@ -165,8 +166,8 @@ describe('getBalanceHistories', () => { getBalanceHistories( [], [], - parseDate('2019-01-02'), - parseDate('2019-01-01') + parseISO('2019-01-02'), + parseISO('2019-01-01') ) ).toEqual({ __no_accounts__: { @@ -184,7 +185,7 @@ describe('getBalanceHistories', () => { ] const transactions = [] - const to = parseDate('2018-06-26') + const to = parseISO('2018-06-26') const histories = getBalanceHistories(accounts, transactions, to) expect(Object.keys(histories)).toEqual(['acc1', 'acc2', 'acc3']) @@ -199,8 +200,8 @@ describe('getBalanceHistories', () => { const transactions = [] - const to = parseDate('2018-06-26') - const from = parseDate('2018-06-24') + const to = parseISO('2018-06-26') + const from = parseISO('2018-06-24') const histories = getBalanceHistories(accounts, transactions, to, from) @@ -234,8 +235,8 @@ describe('getBalanceHistories', () => { { account: 'acc2', amount: 1000, date: '2018-11-20' } ] - const to = parseDate('2018-11-22') - const from = parseDate('2018-11-20') + const to = parseISO('2018-11-22') + const from = parseISO('2018-11-20') const histories = getBalanceHistories(accounts, transactions, to, from) @@ -258,7 +259,7 @@ describe('balanceHistoryToChartData', () => { const history = { '2018-11-22': 1000, '2018-11-21': 500, '2018-11-20': 600 } const expected = ['2018-11-20', '2018-11-21', '2018-11-22'] const chartData = balanceHistoryToChartData(history) - const dates = chartData.map(item => formatDate(item.x, 'YYYY-MM-DD')) + const dates = chartData.map(item => formatDate(item.x, 'yyyy-MM-dd')) expect(dates).toEqual(expected) }) diff --git a/src/ducks/billsMatching/Linker/Linker.js b/src/ducks/billsMatching/Linker/Linker.js index cd455339d4..e911129b85 100644 --- a/src/ducks/billsMatching/Linker/Linker.js +++ b/src/ducks/billsMatching/Linker/Linker.js @@ -14,6 +14,7 @@ const omit = require('lodash/omit') const max = require('lodash/max') const geco = require('geco') const format = require('date-fns/format') +const parseISO = require('date-fns/parseISO') const { getBillDate, log } = require('../utils') const { getTracker } = require('ducks/tracking/node') const { Transaction, Bill } = require('models') @@ -558,7 +559,7 @@ class Linker { groupBills(bills) { const billsToGroup = bills.filter(bill => this.billCanBeGrouped(bill)) const groups = groupBy(billsToGroup, bill => { - return [format(getBillDate(bill), 'YYYY-MM-DD'), bill.vendor] + return [format(parseISO(getBillDate(bill)), 'yyyy-MM-dd'), bill.vendor] }) return Object.values(groups) diff --git a/src/ducks/billsMatching/Linker/Linker.spec.js b/src/ducks/billsMatching/Linker/Linker.spec.js index 1f34ca41e4..b0891435fc 100644 --- a/src/ducks/billsMatching/Linker/Linker.spec.js +++ b/src/ducks/billsMatching/Linker/Linker.spec.js @@ -426,59 +426,59 @@ describe('linker', () => { const bills = [ { _id: 'b1', - originalDate: new Date(2018, 2, 10), + originalDate: new Date(2018, 2, 10).toISOString(), vendor: 'Ameli', type: 'health_costs' }, { _id: 'b2', - originalDate: new Date(2018, 2, 10), + originalDate: new Date(2018, 2, 10).toISOString(), vendor: 'Numéricable', type: 'health_costs' }, { _id: 'b3', - originalDate: new Date(2018, 2, 10), + originalDate: new Date(2018, 2, 10).toISOString(), vendor: 'Ameli', type: 'health_costs' }, { _id: 'b4', - originalDate: new Date(2018, 2, 15), + originalDate: new Date(2018, 2, 15).toISOString(), vendor: 'Ameli', type: 'health_costs' }, { _id: 'b5', - originalDate: new Date(2018, 2, 15), + originalDate: new Date(2018, 2, 15).toISOString(), vendor: 'Ameli', type: 'health_costs' }, { _id: 'b6', - originalDate: new Date(2018, 2, 20), + originalDate: new Date(2018, 2, 20).toISOString(), vendor: 'Numéricable' }, { _id: 'b7', - originalDate: new Date(2018, 2, 20), + originalDate: new Date(2018, 2, 20).toISOString(), vendor: 'Ameli', type: 'health_costs' }, { _id: 'b8', - originalDate: new Date(2018, 2, 20), + originalDate: new Date(2018, 2, 20).toISOString(), vendor: 'Numéricable' }, { _id: 'b9', - originalDate: new Date(2018, 2, 20), + originalDate: new Date(2018, 2, 20).toISOString(), vendor: 'Ameli', type: 'health_costs' }, { _id: 'b10', - originalDate: new Date(2018, 2, 30), + originalDate: new Date(2018, 2, 30).toISOString(), vendor: 'Numéricable' } ] diff --git a/src/ducks/billsMatching/Linker/billsToOperation/helpers.js b/src/ducks/billsMatching/Linker/billsToOperation/helpers.js index e601ee3b59..c5c2af0b12 100644 --- a/src/ducks/billsMatching/Linker/billsToOperation/helpers.js +++ b/src/ducks/billsMatching/Linker/billsToOperation/helpers.js @@ -1,8 +1,10 @@ const sortBy = require('lodash/sortBy') const get = require('lodash/get') -const addDays = require('date-fns/add_days') -const subDays = require('date-fns/sub_days') -const differenceInDays = require('date-fns/difference_in_days') +const addDays = require('date-fns/addDays') +const subDays = require('date-fns/subDays') +const parseISO = require('date-fns/parseISO') +const differenceInDays = require('date-fns/differenceInDays') + const { getBrands } = require('ducks/brandDictionary') const getOperationAmountFromBill = (bill, options) => { @@ -84,7 +86,9 @@ const sortedOperations = (bill, operations) => { const opAmount = getOperationAmountFromBill(bill) return operation => { - const dateDiff = Math.abs(differenceInDays(opDate, operation.date)) + const dateDiff = Math.abs( + differenceInDays(opDate, parseISO(operation.date)) + ) const amountDiff = Math.abs(opAmount - operation.amount) return dateWeight * dateDiff + amountWeight * amountDiff diff --git a/src/ducks/billsMatching/Linker/billsToOperation/helpers.spec.js b/src/ducks/billsMatching/Linker/billsToOperation/helpers.spec.js index 6fc497a345..aa189a5cea 100644 --- a/src/ducks/billsMatching/Linker/billsToOperation/helpers.spec.js +++ b/src/ducks/billsMatching/Linker/billsToOperation/helpers.spec.js @@ -162,40 +162,40 @@ describe('getterHelper', () => { }) describe('sortedOperations', () => { - const bill = { date: new Date(2017, 0, 17), amount: 10 } + const bill = { date: new Date(2017, 0, 17).toISOString(), amount: 10 } test('op.date === bill.date && op.amount === bill.amount', () => { const operations = [ - { id: 1, date: new Date(2017, 0, 16), amount: -10 }, - { id: 3, date: new Date(2017, 0, 17), amount: -10 }, - { id: 2, date: new Date(2017, 0, 17), amount: -11 } + { id: 1, date: new Date(2017, 0, 16).toISOString(), amount: -10 }, + { id: 3, date: new Date(2017, 0, 17).toISOString(), amount: -10 }, + { id: 2, date: new Date(2017, 0, 17).toISOString(), amount: -11 } ] expect(sortedOperations(bill, operations)[0]).toEqual(operations[1]) }) test('op.date === bill.date, so only amount is important', () => { const operations = [ - { id: 1, date: new Date(2017, 0, 17), amount: -8 }, - { id: 2, date: new Date(2017, 0, 17), amount: -9 }, - { id: 3, date: new Date(2017, 0, 17), amount: -12 } + { id: 1, date: new Date(2017, 0, 17).toISOString(), amount: -8 }, + { id: 2, date: new Date(2017, 0, 17).toISOString(), amount: -9 }, + { id: 3, date: new Date(2017, 0, 17).toISOString(), amount: -12 } ] expect(sortedOperations(bill, operations)[0]).toEqual(operations[1]) }) test('op.amount === bill.amount, so only date is important', () => { const operations = [ - { id: 1, date: new Date(2017, 0, 15), amount: -10 }, - { id: 2, date: new Date(2017, 0, 18), amount: -10 }, - { id: 3, date: new Date(2017, 0, 19), amount: -10 } + { id: 1, date: new Date(2017, 0, 15).toISOString(), amount: -10 }, + { id: 2, date: new Date(2017, 0, 18).toISOString(), amount: -10 }, + { id: 3, date: new Date(2017, 0, 19).toISOString(), amount: -10 } ] expect(sortedOperations(bill, operations)[0]).toEqual(operations[1]) }) test('amount & date are different', () => { const operations = [ - { id: 1, date: new Date(2017, 0, 16), amount: -12 }, - { id: 2, date: new Date(2017, 0, 18), amount: -11 }, - { id: 3, date: new Date(2017, 0, 19), amount: -13 } + { id: 1, date: new Date(2017, 0, 16).toISOString(), amount: -12 }, + { id: 2, date: new Date(2017, 0, 18).toISOString(), amount: -11 }, + { id: 3, date: new Date(2017, 0, 19).toISOString(), amount: -13 } ] expect(sortedOperations(bill, operations)[0]).toEqual(operations[1]) }) diff --git a/src/ducks/billsMatching/Linker/billsToOperation/operationsFilters.js b/src/ducks/billsMatching/Linker/billsToOperation/operationsFilters.js index 594753ba52..10f08e77d7 100644 --- a/src/ducks/billsMatching/Linker/billsToOperation/operationsFilters.js +++ b/src/ducks/billsMatching/Linker/billsToOperation/operationsFilters.js @@ -1,5 +1,9 @@ +// XXX: We use `require` instead of `import` in this file to be able to change +// the name of filter functions. Otherwise they would be read-only. const sumBy = require('lodash/sumBy') -const isWithinRange = require('date-fns/is_within_range') +const parseISO = require('date-fns/parseISO') +const isWithinInterval = require('date-fns/isWithinInterval') + const { log } = require('../../utils') const { getCategoryId } = require('../../../transactions/helpers') @@ -54,8 +58,8 @@ const filterByBrand = bill => { const filterByDates = ({ minDate, maxDate }) => { const dateFilter = operation => { - const operationDate = operation.realisationDate || operation.date - return isWithinRange(operationDate, minDate, maxDate) + const operationDate = parseISO(operation.realisationDate || operation.date) + return isWithinInterval(operationDate, { start: minDate, end: maxDate }) } dateFilter.name = 'byDates' diff --git a/src/ducks/billsMatching/Linker/billsToOperation/operationsFilters.spec.js b/src/ducks/billsMatching/Linker/billsToOperation/operationsFilters.spec.js index 9665a100a0..d941408314 100644 --- a/src/ducks/billsMatching/Linker/billsToOperation/operationsFilters.spec.js +++ b/src/ducks/billsMatching/Linker/billsToOperation/operationsFilters.spec.js @@ -51,11 +51,11 @@ describe('operations filters', () => { } const fByDates = filterByDates(rangeDates) - expect(fByDates({ date: new Date(2018, 0, 15) })).toBeFalsy() - expect(fByDates({ date: new Date(2018, 0, 16) })).toBeTruthy() - expect(fByDates({ date: new Date(2018, 0, 17) })).toBeTruthy() - expect(fByDates({ date: new Date(2018, 0, 18) })).toBeTruthy() - expect(fByDates({ date: new Date(2018, 0, 19) })).toBeFalsy() + expect(fByDates({ date: new Date(2018, 0, 15).toISOString() })).toBeFalsy() + expect(fByDates({ date: new Date(2018, 0, 16).toISOString() })).toBeTruthy() + expect(fByDates({ date: new Date(2018, 0, 17).toISOString() })).toBeTruthy() + expect(fByDates({ date: new Date(2018, 0, 18).toISOString() })).toBeTruthy() + expect(fByDates({ date: new Date(2018, 0, 19).toISOString() })).toBeFalsy() }) describe('filtering by amount range', () => { @@ -171,46 +171,51 @@ describe('operations filters', () => { amount: -20, label: 'Visite chez le médecin', _id: 'o1', - date: new Date(2017, 11, 13), + date: new Date(2017, 11, 13).toISOString(), manualCategoryId: '400610' }, { amount: 5, label: 'Remboursement CPAM', _id: 'o2', - date: new Date(2017, 11, 15), + date: new Date(2017, 11, 15).toISOString(), manualCategoryId: '400610' }, { amount: -120, label: 'Facture SFR', _id: 'o3', - date: new Date(2017, 11, 8) + date: new Date(2017, 11, 8).toISOString() }, { amount: -30, label: 'Facture SFR', _id: 'o4', - date: new Date(2017, 11, 7) + date: new Date(2017, 11, 7).toISOString() }, { amount: -80, label: "Matériel d'escalade", _id: 'o5', - date: new Date(2017, 11, 7) + date: new Date(2017, 11, 7).toISOString() }, { amount: -5.5, label: 'Burrito', _id: 'o6', - date: new Date(2017, 11, 5) + date: new Date(2017, 11, 5).toISOString() + }, + { + amount: -2.6, + label: 'Salade', + _id: 'o7', + date: new Date(2017, 11, 6).toISOString() }, - { amount: -2.6, label: 'Salade', _id: 'o7', date: new Date(2017, 11, 6) }, { amount: 50, label: 'Remboursement CPAM', _id: 'o8', - date: new Date(2017, 11, 15), + date: new Date(2017, 11, 15).toISOString(), manualCategoryId: '400610', reimbursements: [{ amount: 50 }] }, @@ -219,7 +224,7 @@ describe('operations filters', () => { label: 'Visite chez le dentiste', _id: 'o9', manualCategoryId: '400610', - date: new Date(2017, 11, 16), + date: new Date(2017, 11, 16).toISOString(), reimbursements: [] }, { @@ -227,7 +232,7 @@ describe('operations filters', () => { label: 'Dafalgan', _id: 'o10', manualCategoryId: '400610', - date: new Date(2017, 11, 16), + date: new Date(2017, 11, 16).toISOString(), reimbursements: [] }, { @@ -235,7 +240,7 @@ describe('operations filters', () => { label: 'Remboursement CPAM', _id: 'o11', manualCategoryId: '400610', - date: new Date(2017, 11, 16), + date: new Date(2017, 11, 16).toISOString(), reimbursements: [] } ] @@ -253,7 +258,7 @@ describe('operations filters', () => { originalAmount: 20, type: 'health_costs', originalDate: new Date(2017, 11, 13), - date: new Date(2017, 11, 15), + date: new Date(2017, 11, 15).toISOString(), isRefund: true, vendor: 'Ameli' } @@ -277,7 +282,7 @@ describe('operations filters', () => { describe('not health bill', () => { const bill = { amount: 30, - date: new Date(2017, 11, 8), + date: new Date(2017, 11, 8).toISOString(), vendor: 'SFR' } @@ -299,7 +304,7 @@ describe('operations filters', () => { const bill = { amount: 50, groupAmount: 57.5, - date: new Date(2017, 11, 16), + date: new Date(2017, 11, 16).toISOString(), vendor: 'Ameli', type: 'health_costs', isRefund: true diff --git a/src/ducks/billsMatching/matchFromBills.js b/src/ducks/billsMatching/matchFromBills.js index 59bf491738..0671612727 100644 --- a/src/ducks/billsMatching/matchFromBills.js +++ b/src/ducks/billsMatching/matchFromBills.js @@ -1,12 +1,13 @@ +import formatDate from 'date-fns/format' + import Linker, { DEFAULT_DATE_LOWER_DELTA, DEFAULT_DATE_UPPER_DELTA } from './Linker/Linker' -import { format as formatDate } from 'date-fns' import { Transaction } from 'models' import { getDateRangeFromBill } from './Linker/billsToOperation/helpers' -const DATE_FORMAT = 'YYYY-MM-DD' +const DATE_FORMAT = 'yyyy-MM-dd' export default async function matchFromBills(bills) { const options = { diff --git a/src/ducks/billsMatching/matchFromTransactions.js b/src/ducks/billsMatching/matchFromTransactions.js index e859b1c2ca..7413e7047d 100644 --- a/src/ducks/billsMatching/matchFromTransactions.js +++ b/src/ducks/billsMatching/matchFromTransactions.js @@ -1,18 +1,24 @@ import min from 'lodash/min' import max from 'lodash/max' -import { format as formatDate, addYears, subYears } from 'date-fns' +import formatDate from 'date-fns/format' +import addYears from 'date-fns/addYears' +import subYears from 'date-fns/subYears' +import parseISO from 'date-fns/parseISO' + import { Bill } from 'models' import Linker from './Linker/Linker' export default async function matchFromTransactions(transactions) { - const transactionsDates = transactions.map(transaction => transaction.date) + const transactionsDates = transactions.map(transaction => + parseISO(transaction.date) + ) const dateMin = subYears(min(transactionsDates), 1) const dateMax = addYears(max(transactionsDates), 1) const selector = { date: { - $gt: formatDate(dateMin, 'YYYY-MM-DD'), - $lt: formatDate(dateMax, 'YYYY-MM-DD') + $gt: formatDate(dateMin, 'yyyy-MM-dd'), + $lt: formatDate(dateMax, 'yyyy-MM-dd') } } diff --git a/src/ducks/billsMatching/matchFromTransactions.spec.js b/src/ducks/billsMatching/matchFromTransactions.spec.js index 213a01d6e9..4e85f5818a 100644 --- a/src/ducks/billsMatching/matchFromTransactions.spec.js +++ b/src/ducks/billsMatching/matchFromTransactions.spec.js @@ -4,9 +4,9 @@ import { Bill } from 'models' jest.mock('./Linker/Linker') const transactions = [ - { date: '2019-07-01' }, - { date: '2019-07-20' }, - { date: '2019-08-21' } + { date: '2019-07-01T00:00:00.000Z' }, + { date: '2019-07-20T00:00:00.000Z' }, + { date: '2019-08-21T00:00:00.000Z' } ] beforeEach(() => { diff --git a/src/ducks/budgetAlerts/index.js b/src/ducks/budgetAlerts/index.js index 26f8f3a705..50d1b84f81 100644 --- a/src/ducks/budgetAlerts/index.js +++ b/src/ducks/budgetAlerts/index.js @@ -1,10 +1,14 @@ import logger from 'cozy-logger' +import sumBy from 'lodash/sumBy' +import startOfMonth from 'date-fns/startOfMonth' +import endOfMonth from 'date-fns/endOfMonth' +import addDays from 'date-fns/addDays' +import format from 'date-fns/format' + import { TRANSACTION_DOCTYPE, ACCOUNT_DOCTYPE, GROUP_DOCTYPE } from 'doctypes' import { getCategoryId } from 'ducks/transactions/helpers' import { isParentOf } from 'ducks/categories/categoriesMap' -import sumBy from 'lodash/sumBy' import { fetchCategoryAlerts } from 'ducks/settings/helpers' -import { startOfMonth, endOfMonth, addDays, format } from 'date-fns' import { Q } from 'cozy-client' @@ -57,8 +61,8 @@ export const fetchExpensesForAlert = async ( let currentDate = originalCurrentDate ? new Date(originalCurrentDate) : new Date() - const start = format(startOfMonth(currentDate), 'YYYY-MM') - const end = format(addDays(endOfMonth(currentDate), 1), 'YYYY-MM') + const start = format(startOfMonth(currentDate), 'yyyy-MM') + const end = format(addDays(endOfMonth(currentDate), 1), 'yyyy-MM') const selector = { date: { $lt: end, diff --git a/src/ducks/categorization/services.js b/src/ducks/categorization/services.js index 9982dc7151..11f31b4eb0 100644 --- a/src/ducks/categorization/services.js +++ b/src/ducks/categorization/services.js @@ -5,7 +5,8 @@ import { BankTransaction } from 'cozy-doctypes' import flag from 'cozy-flags' import chunk from 'lodash/chunk' import sortBy from 'lodash/sortBy' -import { differenceInSeconds } from 'date-fns' +import differenceInSeconds from 'date-fns/differenceInSeconds' + import { getTracker } from 'ducks/tracking/node' import { TRANSACTION_DOCTYPE } from 'doctypes' diff --git a/src/ducks/chart/selectors.js b/src/ducks/chart/selectors.js index a7e252b49e..c1799ba9a8 100644 --- a/src/ducks/chart/selectors.js +++ b/src/ducks/chart/selectors.js @@ -1,17 +1,21 @@ import { isQueryLoading, hasQueryBeenLoaded } from 'cozy-client' +import startOfMonth from 'date-fns/startOfMonth' +import endOfMonth from 'date-fns/endOfMonth' +import isAfter from 'date-fns/isAfter' +import subDays from 'date-fns/subDays' +import subMonths from 'date-fns/subMonths' + import { getBalanceHistories, sumBalanceHistories, balanceHistoryToChartData } from 'ducks/balance/helpers' -import { startOfMonth, endOfMonth, isAfter, subDays, subMonths } from 'date-fns' import { getAccounts, getTransactions } from 'selectors' import { getFilteredTransactions, getTransactionsFilteredByAccount, getFilteredAccounts } from 'ducks/filters' - import { getCategoryId } from 'ducks/transactions/helpers' import { createSelector } from 'reselect' diff --git a/src/ducks/filters/index.js b/src/ducks/filters/index.js index 3df03fa830..4f6a7b2031 100644 --- a/src/ducks/filters/index.js +++ b/src/ducks/filters/index.js @@ -1,7 +1,16 @@ import { combineReducers } from 'redux' import { createSelector } from 'reselect' -import { parse, format, isWithinRange } from 'date-fns' +import find from 'lodash/find' +import keyBy from 'lodash/keyBy' +import last from 'lodash/last' +import sortBy from 'lodash/sortBy' +import parse from 'date-fns/parse' +import parseISO from 'date-fns/parseISO' +import formatISO from 'date-fns/formatISO' +import isWithinInterval from 'date-fns/isWithinInterval' +import { dehydrate } from 'cozy-client' import logger from 'cozy-logger' + import { getTransactions, getAllGroups, @@ -10,12 +19,7 @@ import { getAccountsById } from 'selectors' import { ACCOUNT_DOCTYPE, GROUP_DOCTYPE } from 'doctypes' -import find from 'lodash/find' -import keyBy from 'lodash/keyBy' -import last from 'lodash/last' -import sortBy from 'lodash/sortBy' import { DESTROY_ACCOUNT } from 'actions/accounts' -import { dehydrate } from 'cozy-client' import { getApplicationDate, getDisplayDate } from 'ducks/transactions/helpers' import { isHealthExpense } from 'ducks/categories/helpers' @@ -25,13 +29,14 @@ const log = logger.namespace('filters') const FILTER_BY_PERIOD = 'FILTER_BY_PERIOD' const FILTER_BY_DOC = 'FILTER_BY_DOC' const RESET_FILTER_BY_DOC = 'RESET_FILTER_BY_DOC' -const FILTER_YEAR_MONTH_FORMAT = 'YYYY-MM' -const FILTER_YEAR_FORMAT = 'YYYY' +const FILTER_YEAR_MONTH_FORMAT = 'yyyy-MM' +const FILTER_YEAR_FORMAT = 'yyyy' export const parsePeriod = filter => { return parse( filter, - filter.length === 4 ? FILTER_YEAR_FORMAT : FILTER_YEAR_MONTH_FORMAT + filter.length === 4 ? FILTER_YEAR_FORMAT : FILTER_YEAR_MONTH_FORMAT, + new Date() ) } @@ -61,7 +66,10 @@ export const filterByPeriod = (transactions, period, dateGetter) => { } } else if (period.length === 2 && isDate(period[0]) && isDate(period[1])) { pred = date => { - return isWithinRange(parse(date), period[0], period[1]) + return isWithinInterval(parseISO(date), { + start: period[0], + end: period[1] + }) } } else { throw new Error('Invalid period: ' + JSON.stringify(period)) @@ -239,7 +247,7 @@ export const addFilterForMostRecentTransactions = } // reducers -const getDefaultMonth = () => monthFormat(format(new Date())) +const getDefaultMonth = () => monthFormat(formatISO(new Date())) const period = (state = getDefaultMonth(), action) => { switch (action.type) { case FILTER_BY_PERIOD: diff --git a/src/ducks/future/selectors.js b/src/ducks/future/selectors.js index 195055c510..6df8d73997 100644 --- a/src/ducks/future/selectors.js +++ b/src/ducks/future/selectors.js @@ -1,8 +1,8 @@ import { createSelector } from 'reselect' -import addDays from 'date-fns/add_days' -import isAfter from 'date-fns/is_after' -import parse from 'date-fns/parse' -import differenceInDays from 'date-fns/difference_in_days' +import addDays from 'date-fns/addDays' +import isAfter from 'date-fns/isAfter' +import parseISO from 'date-fns/parseISO' +import differenceInDays from 'date-fns/differenceInDays' import get from 'lodash/get' import orderBy from 'lodash/orderBy' @@ -29,7 +29,7 @@ export const isDeprecatedBundle = recurrence => { return true } const now = Date.now() - const latestDate = parse(recurrence.latestDate) + const latestDate = parseISO(recurrence.latestDate) const deltaToNow = differenceInDays(now, latestDate) return deltaToNow >= RECURRENCE_MAX_AGE_FOR_PLANNING } diff --git a/src/ducks/notifications/DelayedDebit/index.js b/src/ducks/notifications/DelayedDebit/index.js index 09be91402c..66c2f60a2d 100644 --- a/src/ducks/notifications/DelayedDebit/index.js +++ b/src/ducks/notifications/DelayedDebit/index.js @@ -2,7 +2,10 @@ import map from 'lodash/map' import groupBy from 'lodash/groupBy' import keyBy from 'lodash/keyBy' import merge from 'lodash/merge' -import { endOfMonth, subDays, isWithinRange } from 'date-fns' +import endOfMonth from 'date-fns/endOfMonth' +import subDays from 'date-fns/subDays' +import startOfDay from 'date-fns/startOfDay' +import isWithinInterval from 'date-fns/isWithinInterval' import { toText } from 'cozy-notifications' import logger from 'cozy-logger' @@ -42,11 +45,9 @@ export const isCreditCardAccount = account => export const isWithinEndOfMonthRange = nbDaysBeforeEndOfMonth => { const today = new Date() const lastDayOfMonth = endOfMonth(today) - // We need to add one to nbDaysBeforeEndOfMonth because `isWithinRange` is - // exclusive - const limitDate = subDays(lastDayOfMonth, nbDaysBeforeEndOfMonth + 1) + const limitDate = startOfDay(subDays(lastDayOfMonth, nbDaysBeforeEndOfMonth)) - return isWithinRange(today, limitDate, lastDayOfMonth) + return isWithinInterval(today, { start: limitDate, end: lastDayOfMonth }) } const isBalanceGreater = (account1, account2) => { diff --git a/src/ducks/notifications/LateHealthReimbursement/index.js b/src/ducks/notifications/LateHealthReimbursement/index.js index 90e7a69979..4d76a138bf 100644 --- a/src/ducks/notifications/LateHealthReimbursement/index.js +++ b/src/ducks/notifications/LateHealthReimbursement/index.js @@ -1,7 +1,9 @@ import uniq from 'lodash/uniq' import keyBy from 'lodash/keyBy' import logger from 'cozy-logger' -import { subDays, subMonths, format as formatDate } from 'date-fns' +import subDays from 'date-fns/subDays' +import subMonths from 'date-fns/subMonths' +import formatDate from 'date-fns/format' import { BankTransaction, BankAccount } from 'cozy-doctypes' import { toText } from 'cozy-notifications' @@ -67,16 +69,18 @@ class LateHealthReimbursement extends NotificationView { } async fetchTransactions() { - const DATE_FORMAT = 'YYYY-MM-DD' + const DATE_FORMAT = 'yyyy-MM-dd' const today = new Date() - const lt = formatDate(subDays(today, this.interval), DATE_FORMAT) - const gt = formatDate(subMonths(lt, 6), DATE_FORMAT) + const lt = subDays(today, this.interval) + const gt = subMonths(lt, 6) + const $lt = formatDate(lt, DATE_FORMAT) + const $gt = formatDate(gt, DATE_FORMAT) - log('info', `Fetching transactions between ${gt} and ${lt}`) + log('info', `Fetching transactions between ${$gt} and ${$lt}`) const transactionsInDateRange = await BankTransaction.queryAll({ date: { - $gt: gt, - $lt: lt + $gt, + $lt } }) log( diff --git a/src/ducks/notifications/LateHealthReimbursement/index.spec.js b/src/ducks/notifications/LateHealthReimbursement/index.spec.js index 4096a6b4b4..0ab0e75a5e 100644 --- a/src/ducks/notifications/LateHealthReimbursement/index.spec.js +++ b/src/ducks/notifications/LateHealthReimbursement/index.spec.js @@ -14,7 +14,7 @@ const mockTransactions = [ { _id: 't1', amount: 20, - date: '2018-09-16T12:00', + date: '2018-09-16T12:00:00.000Z', manualCategoryId: '400610', label: '1', account: 'accountId1' @@ -24,14 +24,14 @@ const mockTransactions = [ { _id: 't2', amount: 10, - date: '2018-09-17T12:00', + date: '2018-09-17T12:00:00.000Z', label: '2', account: 'accountId2' }, { _id: 't3', amount: -5, - date: '2018-09-18T12:00', + date: '2018-09-18T12:00:00.000Z', label: '3', manualCategoryId: '400610', account: 'accountId3', @@ -55,7 +55,7 @@ const mockTransactions = [ { _id: 't5', amount: -30, - date: '2018-09-07T12:00', + date: '2018-09-07T12:00:00.000Z', manualCategoryId: '400610', label: '1', account: 'accountId1' @@ -66,7 +66,7 @@ const mockTransactions = [ { _id: 't6', amount: -20, - date: '2018-09-16T12:00', + date: '2018-09-16T12:00:00.000Z', manualCategoryId: '400610', label: '1', account: 'accountId1' diff --git a/src/ducks/notifications/TransactionGreater/index.js b/src/ducks/notifications/TransactionGreater/index.js index cbe5613b8f..bf29f724c2 100644 --- a/src/ducks/notifications/TransactionGreater/index.js +++ b/src/ducks/notifications/TransactionGreater/index.js @@ -1,4 +1,4 @@ -import { subDays } from 'date-fns' +import subDays from 'date-fns/subDays' import uniqBy from 'lodash/uniqBy' import flatten from 'lodash/flatten' import overEvery from 'lodash/overEvery' diff --git a/src/ducks/notifications/index.js b/src/ducks/notifications/index.js index 5167eddd99..42ae477ede 100644 --- a/src/ducks/notifications/index.js +++ b/src/ducks/notifications/index.js @@ -3,7 +3,8 @@ */ import Handlebars from 'handlebars' -import { parse, format } from 'date-fns' +import parse from 'date-fns/parse' +import format from 'date-fns/format' import { getCategoryId } from 'ducks/transactions/helpers' import { getAccountBalance } from 'ducks/account/helpers' @@ -53,12 +54,12 @@ ${Math.abs(amount)} € let fmtToUse = fmt if (ctxToUse === undefined) { ctxToUse = fmt - fmtToUse = 'DD/MM/YYYY' + fmtToUse = 'dd/MM/yyyy' } if (date.getDay) { return format(date, fmtToUse) } else { - const parsed = parse(date.substr(0, 10), 'YYYY-MM-DD') + const parsed = parse(date.substr(0, 10), 'yyyy-MM-dd', new Date()) return format(parsed, fmtToUse) } }, diff --git a/src/ducks/recurrence/Bundles.jsx b/src/ducks/recurrence/Bundles.jsx index 2be024a8d7..78c4df53b7 100644 --- a/src/ducks/recurrence/Bundles.jsx +++ b/src/ducks/recurrence/Bundles.jsx @@ -1,18 +1,17 @@ import React, { useMemo } from 'react' import cx from 'classnames' -import distanceInWords from 'date-fns/distance_in_words' +import intlFormatDistance from 'date-fns/intlFormatDistance' import CompositeRow from 'cozy-ui/transpiled/react/CompositeRow' import useBreakpoints from 'cozy-ui/transpiled/react/hooks/useBreakpoints' import { useI18n } from 'cozy-ui/transpiled/react/I18n' import { Bd, Img, Media } from 'cozy-ui/transpiled/react/Media' import Figure from 'cozy-ui/transpiled/react/Figure' + import CategoryIcon from 'ducks/categories/CategoryIcon' import Table, { TdSecondary } from 'components/Table' import { useHistory } from 'components/RouterContext' -import frLocale from 'date-fns/locale/fr' -import enLocale from 'date-fns/locale/en' -import esLocale from 'date-fns/locale/es' +import { fr as frLocale, en as enLocale, es as esLocale } from 'date-fns/locale' import styles from './styles.styl' import { @@ -38,8 +37,7 @@ const BundleDistance = ({ bundle }) => { const { lang } = useI18n() const d = useMemo( () => - distanceInWords(Date.now(), bundle.latestDate, { - addSuffix: true, + intlFormatDistance(Date.now(), bundle.latestDate, { locale: dateFnsLocales[lang] || dateFnsLocales.en }), [bundle, lang] diff --git a/src/ducks/recurrence/DateSlider.jsx b/src/ducks/recurrence/DateSlider.jsx index 135dbcfd67..36e55f28e8 100644 --- a/src/ducks/recurrence/DateSlider.jsx +++ b/src/ducks/recurrence/DateSlider.jsx @@ -1,5 +1,5 @@ import React, { useCallback } from 'react' -import addDays from 'date-fns/add_days' +import addDays from 'date-fns/addDays' import { ONE_DAY } from 'ducks/recurrence/constants' diff --git a/src/ducks/recurrence/service.js b/src/ducks/recurrence/service.js index 29dd2e4383..bdcc0d5811 100644 --- a/src/ducks/recurrence/service.js +++ b/src/ducks/recurrence/service.js @@ -13,7 +13,7 @@ import { import { fetchHydratedBundles, saveHydratedBundles } from 'ducks/recurrence/api' import { getLabel } from 'ducks/recurrence/utils' import tree from 'ducks/categories/tree' -import addDays from 'date-fns/add_days' +import addDays from 'date-fns/addDays' export const NB_DAYS_LOOKBACK = 100 diff --git a/src/ducks/recurrence/utils.js b/src/ducks/recurrence/utils.js index 1280ef1fa9..d0960efa93 100644 --- a/src/ducks/recurrence/utils.js +++ b/src/ducks/recurrence/utils.js @@ -2,9 +2,9 @@ import uniqBy from 'lodash/uniqBy' import startCase from 'lodash/startCase' import min from 'lodash/min' import max from 'lodash/max' -import addDays from 'date-fns/add_days' -import parse from 'date-fns/parse' -import differenceInDays from 'date-fns/difference_in_days' +import addDays from 'date-fns/addDays' +import parseISO from 'date-fns/parseISO' +import differenceInDays from 'date-fns/differenceInDays' import flag from 'cozy-flags' @@ -115,7 +115,7 @@ export const nextDate = recurrence => { deltas: { median } } } = recurrence - const latestDate = parse(rawLatestDate) + const latestDate = parseISO(rawLatestDate) const now = new Date(Date.now()) const deltaDays = differenceInDays(now, latestDate) const n = deltaDays / median @@ -133,7 +133,7 @@ export const nextDate = recurrence => { } export const isDeprecatedBundle = recurrence => { - const latestDate = parse(recurrence.latestDate) + const latestDate = parseISO(recurrence.latestDate) const now = Date.now() return differenceInDays(now, latestDate) } diff --git a/src/ducks/reimbursements/Reimbursements.jsx b/src/ducks/reimbursements/Reimbursements.jsx index ad243ab841..79776539d0 100644 --- a/src/ducks/reimbursements/Reimbursements.jsx +++ b/src/ducks/reimbursements/Reimbursements.jsx @@ -1,19 +1,18 @@ import React, { useEffect } from 'react' import { useSelector } from 'react-redux' -import { transactionsConn } from 'doctypes' import sumBy from 'lodash/sumBy' - import { isQueryLoading, hasQueryBeenLoaded, useQuery } from 'cozy-client' import { useI18n } from 'cozy-ui/transpiled/react/I18n' import Figure from 'cozy-ui/transpiled/react/Figure' import Divider from 'cozy-ui/transpiled/react/MuiCozyTheme/Divider' +import getYear from 'date-fns/getYear' +import { transactionsConn } from 'doctypes' import { TransactionList } from 'ducks/transactions/Transactions' import styles from 'ducks/reimbursements/Reimbursements.styl' import Loading from 'components/Loading' import { Section, SectionTitle } from 'components/Section' import { useFilters } from 'components/withFilters' -import { getYear } from 'date-fns' import TransactionActionsProvider from 'ducks/transactions/TransactionActionsProvider' import { useBrands } from 'ducks/brandDictionary/withBrands' import { getGroupedFilteredExpenses } from './selectors' @@ -52,6 +51,8 @@ export const DumbReimbursements = ({ const hasHealthBrands = brands.filter(brand => brand.hasTrigger && brand.health).length > 0 + // XXX: f() is an old version of date-fns/format which does not understand the + // new format string. const formattedPeriod = f( parsePeriod(currentPeriod), currentPeriod.length === 4 ? 'YYYY' : 'MMMM YYYY' diff --git a/src/ducks/reimbursements/ReimbursementsPage.jsx b/src/ducks/reimbursements/ReimbursementsPage.jsx index 3b269c7b0b..d92e6ec011 100644 --- a/src/ducks/reimbursements/ReimbursementsPage.jsx +++ b/src/ducks/reimbursements/ReimbursementsPage.jsx @@ -1,23 +1,22 @@ import React, { useMemo } from 'react' import { useI18n } from 'cozy-ui/transpiled/react/I18n' import useBreakpoints from 'cozy-ui/transpiled/react/hooks/useBreakpoints' +import cx from 'classnames' +import { GROUP_DOCTYPE } from 'doctypes' +import subMonths from 'date-fns/subMonths' +import format from 'date-fns/format' +import endOfDay from 'date-fns/endOfDay' +import differenceInCalendarMonths from 'date-fns/differenceInCalendarMonths' + import Header from 'components/Header' import Padded from 'components/Padded' import { PageTitle } from 'components/Title' -import cx from 'classnames' import BackButton from 'components/BackButton' import { ConnectedSelectDates } from 'components/SelectDates' import Reimbursements from 'ducks/reimbursements/Reimbursements' import styles from 'ducks/reimbursements/ReimbursementsPage.styl' import useFilteringDoc from 'ducks/filters/useFilteringDoc' import { getCategoryName } from 'ducks/categories/categoriesMap' -import { GROUP_DOCTYPE } from 'doctypes' -import { - subMonths, - format, - endOfDay, - differenceInCalendarMonths -} from 'date-fns' const getTitleTranslationKey = doc => { const base = 'Reimbursements.title' @@ -49,7 +48,7 @@ const getDefaultOptions = () => { const now = endOfDay(new Date()) for (let i = 0; i < differenceInCalendarMonths(now, start2016); i++) { - const month = format(subMonths(now, i), 'YYYY-MM') + const month = format(subMonths(now, i), 'yyyy-MM') options.push({ yearMonth: month }) diff --git a/src/ducks/search/EarliestTransactionDate.jsx b/src/ducks/search/EarliestTransactionDate.jsx index 7d39bb4c18..2690cf8e40 100644 --- a/src/ducks/search/EarliestTransactionDate.jsx +++ b/src/ducks/search/EarliestTransactionDate.jsx @@ -17,7 +17,11 @@ const EarliestTransactionDate = ({ if (!transaction) return null return (
- {t('Search.since', { date: f(transaction.date, 'D MMM YYYY') })} + {t('Search.since', { + // XXX: f() is an old version of date-fns/format which does not + // understand the new format string. + date: f(transaction.date, 'D MMM YYYY') + })} {transactionCol.hasMore ? ( { diff --git a/src/ducks/transactions/TransactionModal/TransactionModal.spec.jsx b/src/ducks/transactions/TransactionModal/TransactionModal.spec.jsx index 378087fc9d..6d9e50d739 100644 --- a/src/ducks/transactions/TransactionModal/TransactionModal.spec.jsx +++ b/src/ducks/transactions/TransactionModal/TransactionModal.spec.jsx @@ -1,7 +1,7 @@ import React from 'react' import { render, fireEvent, within } from '@testing-library/react' import Alerter from 'cozy-ui/transpiled/react/Alerter' -import { format } from 'date-fns' +import format from 'date-fns/format' import AppLike from 'test/AppLike' import { createClientWithData } from 'test/client' diff --git a/src/ducks/transactions/TransactionModal/TransactionModalInfoContent.jsx b/src/ducks/transactions/TransactionModal/TransactionModalInfoContent.jsx index c1448730e2..570678b256 100644 --- a/src/ducks/transactions/TransactionModal/TransactionModalInfoContent.jsx +++ b/src/ducks/transactions/TransactionModal/TransactionModalInfoContent.jsx @@ -1,6 +1,6 @@ import React, { useState } from 'react' +import parse from 'date-fns/parse' -import { TRANSACTION_DOCTYPE } from 'doctypes' import flag from 'cozy-flags' import { useClient } from 'cozy-client' import { useI18n } from 'cozy-ui/transpiled/react/I18n' @@ -13,6 +13,7 @@ import RestoreIcon from 'cozy-ui/transpiled/react/Icons/Restore' import Spinner from 'cozy-ui/transpiled/react/Spinner' import IconButton from 'cozy-ui/transpiled/react/IconButton' +import { TRANSACTION_DOCTYPE } from 'doctypes' import ListItemArrow from 'components/ListItemArrow' import iconCalendar from 'components/IconCalendar' import useDocument from 'components/useDocument' @@ -26,7 +27,8 @@ import { getCategoryId, updateApplicationDate, getDate, - getApplicationDate + getApplicationDate, + getParsedTransactionDate } from 'ducks/transactions/helpers' import TransactionActions from 'ducks/transactions/TransactionActions' import { getCategoryName } from 'ducks/categories/categoriesMap' @@ -135,7 +137,12 @@ const TransactionModalInfoContent = props => { }, { label: t('Transactions.infos.date'), - value: f(getDate(transaction), 'dddd D MMMM') + // XXX: f() is an old version of date-fns/format which does not understand the + // new format string. + value: f( + parse(getDate(transaction), 'yyyy-MM-dd', new Date()), + 'dddd D MMMM' + ) } ].filter(x => x.value)} /> @@ -170,10 +177,9 @@ const TransactionModalInfoContent = props => { {t('Transactions.infos.assignedToPeriod', { - date: f( - getApplicationDate(transaction) || getDate(transaction), - 'MMM YYYY' - ) + // XXX: f() is an old version of date-fns/format which does not + // understand the new format string. + date: f(getParsedTransactionDate(transaction), 'MMM YYYY') })} {shouldShowRestoreApplicationDateIcon && ( diff --git a/src/ducks/transactions/TransactionModal/helpers.js b/src/ducks/transactions/TransactionModal/helpers.js index 217705f542..c4322b1633 100644 --- a/src/ducks/transactions/TransactionModal/helpers.js +++ b/src/ducks/transactions/TransactionModal/helpers.js @@ -1,9 +1,9 @@ import Alerter from 'cozy-ui/transpiled/react/Alerter' -import { getDate, getApplicationDate } from 'ducks/transactions/helpers' +import { getParsedTransactionDate } from 'ducks/transactions/helpers' export const showAlertAfterApplicationDateUpdate = (transaction, t, f) => { - const date = getApplicationDate(transaction) || getDate(transaction) + const date = getParsedTransactionDate(transaction) Alerter.success( t('Transactions.infos.applicationDateChangedAlert', { applicationDate: f(date, 'MMMM') diff --git a/src/ducks/transactions/TransactionRow/TransactionDate.jsx b/src/ducks/transactions/TransactionRow/TransactionDate.jsx index d65d32200f..34d490b002 100644 --- a/src/ducks/transactions/TransactionRow/TransactionDate.jsx +++ b/src/ducks/transactions/TransactionRow/TransactionDate.jsx @@ -1,6 +1,6 @@ import React from 'react' - import { useI18n } from 'cozy-ui/transpiled/react/I18n' +import parse from 'date-fns/parse' import { getDate } from 'ducks/transactions/helpers' @@ -13,12 +13,21 @@ const TransactionDate = ({ isExtraLarge, transaction }) => { transaction.realisationDate && transaction.date !== transaction.realisationDate ? t('Transactions.will-be-debited-on', { + // XXX: f() is an old version of date-fns/format which does not + // understand the new format string. date: f(transaction.date, 'D MMMM YYYY') }) : null } > - {f(getDate(transaction), `D ${isExtraLarge ? 'MMMM' : 'MMM'} YYYY`)} + { + // XXX: f() is an old version of date-fns/format which does not + // understand the new format string. + f( + parse(getDate(transaction), 'yyyy-MM-dd', new Date()), + `D ${isExtraLarge ? 'MMMM' : 'MMM'} YYYY` + ) + } ) } diff --git a/src/ducks/transactions/TransactionSelectDates.jsx b/src/ducks/transactions/TransactionSelectDates.jsx index b730467f33..13e509abad 100644 --- a/src/ducks/transactions/TransactionSelectDates.jsx +++ b/src/ducks/transactions/TransactionSelectDates.jsx @@ -1,18 +1,15 @@ import React, { useEffect, useMemo } from 'react' import PropTypes from 'prop-types' - -import SelectDates, { monthRange } from 'components/SelectDates' import last from 'lodash/last' import uniq from 'lodash/uniq' -import { - subMonths, - format, - parse, - differenceInCalendarMonths, - isAfter -} from 'date-fns' -import { getDate } from 'ducks/transactions/helpers' +import subMonths from 'date-fns/subMonths' +import format from 'date-fns/format' +import parse from 'date-fns/parse' +import differenceInCalendarMonths from 'date-fns/differenceInCalendarMonths' +import isAfter from 'date-fns/isAfter' +import SelectDates, { monthRange } from 'components/SelectDates' +import { getDate } from 'ducks/transactions/helpers' import useTransactionExtent from 'hooks/useTransactionExtent' const rangeMonth = (startDate, endDate) => { @@ -32,13 +29,13 @@ export const getOptions = transactions => { const mAvailableMonths = new Set(availableMonths) - const start = parse(availableMonths[0], 'YYYY-MM') - const lastMonth = parse(last(availableMonths), 'YYYY-MM') + const start = parse(availableMonths[0], 'yyyy-MM', new Date()) + const lastMonth = parse(last(availableMonths), 'yyyy-MM', new Date()) const today = new Date() const end = isAfter(lastMonth, today) ? lastMonth : today return rangeMonth(start, end).map(month => { - const fmted = format(month, 'YYYY-MM') + const fmted = format(month, 'yyyy-MM') return { yearMonth: fmted, disabled: !mAvailableMonths.has(fmted) @@ -73,7 +70,7 @@ const TransactionSelectDates = ({ onExtentLoad, ...props }) => { const { date: latestDate } = latestTransaction const range = monthRange(new Date(earliestDate), new Date(latestDate)) .map(date => ({ - yearMonth: format(date, 'YYYY-MM'), + yearMonth: format(date, 'yyyy-MM'), disabled: false })) .reverse() diff --git a/src/ducks/transactions/TransactionSelectDates.spec.jsx b/src/ducks/transactions/TransactionSelectDates.spec.jsx index 3872957c3a..a8661318a7 100644 --- a/src/ducks/transactions/TransactionSelectDates.spec.jsx +++ b/src/ducks/transactions/TransactionSelectDates.spec.jsx @@ -1,15 +1,15 @@ import React from 'react' import { render } from '@testing-library/react' import fixtures from 'test/fixtures' -import addMonths from 'date-fns/add_months' -import isBefore from 'date-fns/is_before' -import isEqual from 'date-fns/is_equal' +import addMonths from 'date-fns/addMonths' +import isBefore from 'date-fns/isBefore' +import isEqual from 'date-fns/isEqual' import format from 'date-fns/format' import includes from 'lodash/includes' import MockDate from 'mockdate' +import { createMockClient } from 'cozy-client' import TransactionSelectDates, { getOptions } from './TransactionSelectDates' -import { createMockClient } from 'cozy-client' import { TRANSACTION_DOCTYPE } from 'doctypes' import AppLike from 'test/AppLike' import { findSelectDatesInput } from 'test/selectDates' @@ -24,7 +24,7 @@ const transactions = fixtures['io.cozy.bank.operations'] const enabledMonth = ['2018-06', '2018-01', '2017-08', '2017-07', '2017-06'] const generateOption = date => { - const month = format(date, 'YYYY-MM') + const month = format(date, 'yyyy-MM') return { disabled: !includes(enabledMonth, month), yearMonth: month @@ -58,7 +58,7 @@ describe('options from select dates', () => { const transactionInFuture = { _id: 'inthefuture', - date: format(addMonths(new Date(), 1), 'YYYY-MM-DD') + date: format(addMonths(new Date(), 1), 'yyyy-MM-dd') } enabledMonth.unshift(transactionInFuture.date.slice(0, 7)) diff --git a/src/ducks/transactions/Transactions.jsx b/src/ducks/transactions/Transactions.jsx index bafed70c4e..1396129ada 100644 --- a/src/ducks/transactions/Transactions.jsx +++ b/src/ducks/transactions/Transactions.jsx @@ -35,6 +35,8 @@ const groupByDate = transactions => { } export const TransactionsListContext = createContext({ + // XXX: f() is an old version of date-fns/format which does not understand the + // new format string. mobileSectionDateFormat: 'dddd D MMMM' }) diff --git a/src/ducks/transactions/helpers.js b/src/ducks/transactions/helpers.js index 50ef0497e0..d6f86a102d 100644 --- a/src/ducks/transactions/helpers.js +++ b/src/ducks/transactions/helpers.js @@ -3,10 +3,11 @@ import findLast from 'lodash/findLast' import get from 'lodash/get' import set from 'lodash/set' import sumBy from 'lodash/sumBy' +import differenceInDays from 'date-fns/differenceInDays' +import parse from 'date-fns/parse' import flag from 'cozy-flags' -import { differenceInDays, parse as parseDate } from 'date-fns' import { isHealthExpense, isProfessionalExpense @@ -40,6 +41,12 @@ const titleRx = /(?:^|\s)\S/g const titleCase = label => label.toLowerCase().replace(titleRx, a => a.toUpperCase()) +const isSameMonth = (dateStr, otherDateStr) => { + return ( + dateStr && otherDateStr && dateStr.slice(0, 7) == otherDateStr.slice(0, 7) + ) +} + export const getLabel = transaction => cleanLabel(titleCase(transaction.label)) export const getAccountType = transaction => { @@ -65,6 +72,22 @@ export const getDate = transaction => { return date.slice(0, 10) } +export const getApplicationDate = transaction => { + if (isSameMonth(transaction.applicationDate, transaction.date)) { + return null + } + return transaction.applicationDate +} + +export const getParsedTransactionDate = transaction => { + const applicationDate = getApplicationDate(transaction) + const transactionDate = getDate(transaction) + const parsedDate = applicationDate + ? parse(applicationDate, 'yyyy-MM', new Date()) + : parse(transactionDate, 'yyyy-MM-dd', new Date()) + return parsedDate +} + /** * Performs successive `find`s until one of the find functions returns * a result @@ -212,7 +235,7 @@ export const isReimbursementLate = (transaction, lateLimitInDays) => { return false } - const transactionDate = parseDate(getDate(transaction)) + const transactionDate = parse(getDate(transaction), 'yyyy-MM-dd', new Date()) const today = new Date() return differenceInDays(today, transactionDate) > lateLimitInDays @@ -271,19 +294,6 @@ export const updateTransactionRecurrence = async ( return data } -const isSameMonth = (dateStr, otherDateStr) => { - return ( - dateStr && otherDateStr && dateStr.slice(0, 7) == otherDateStr.slice(0, 7) - ) -} - -export const getApplicationDate = transaction => { - if (isSameMonth(transaction.applicationDate, transaction.date)) { - return null - } - return transaction.applicationDate -} - export const updateApplicationDate = async ( client, transaction, diff --git a/src/ducks/transactions/queries.js b/src/ducks/transactions/queries.js index 69abdf4378..eb1650ff9f 100644 --- a/src/ducks/transactions/queries.js +++ b/src/ducks/transactions/queries.js @@ -1,7 +1,7 @@ -import startOfMonth from 'date-fns/start_of_month' -import endOfMonth from 'date-fns/end_of_month' -import startOfYear from 'date-fns/start_of_year' -import endOfYear from 'date-fns/end_of_year' +import startOfMonth from 'date-fns/startOfMonth' +import endOfMonth from 'date-fns/endOfMonth' +import startOfYear from 'date-fns/startOfYear' +import endOfYear from 'date-fns/endOfYear' import format from 'date-fns/format' import merge from 'lodash/merge' @@ -178,7 +178,7 @@ export const addPeriodToConn = ({ const startDate = period.length === 7 ? startOfMonth(d) : startOfYear(d) const endDate = period.length === 7 ? endOfMonth(d) : endOfYear(d) const dateFormat = - dateAttribute === APPLICATION_DATE ? 'YYYY-MM-DD' : 'YYYY-MM-DD[T]HH:mm' + dateAttribute === APPLICATION_DATE ? 'yyyy-MM-dd' : `yyyy-MM-dd'T'HH:mm` const baseQuery = mkBaseQuery() const query = Q(baseQuery.doctype) @@ -200,8 +200,8 @@ export const addPeriodToConn = ({ .limitBy(500) const as = `${baseAs}-by-${dateAttribute}-${format( startDate, - 'YYYY-MM' - )}-${format(endDate, 'YYYY-MM')}` + 'yyyy-MM' + )}-${format(endDate, 'yyyy-MM')}` return { query, as, diff --git a/src/ducks/transfers/transfers.js b/src/ducks/transfers/transfers.js index 7b2d39c9c8..a6a8a53a63 100644 --- a/src/ducks/transfers/transfers.js +++ b/src/ducks/transfers/transfers.js @@ -50,7 +50,7 @@ export const prepareJobAccount = async (client, konnSlug, auth) => { * @param {String} options.senderAccount - io.cozy.bank.accounts id * @param {String} options.password - Password of the bank account * @param {String} options.label - Label of the operation - * @param {String} options.executionDate - Date of the operation in DD/MM/YYYY + * @param {String} options.executionDate - Date of the operation in dd/MM/yyyy * @return {Promise} */ export const createJob = async ( diff --git a/src/targets/services/konnectorAlerts/createTriggerAt.js b/src/targets/services/konnectorAlerts/createTriggerAt.js index fc3d8336b6..32c21673a4 100644 --- a/src/targets/services/konnectorAlerts/createTriggerAt.js +++ b/src/targets/services/konnectorAlerts/createTriggerAt.js @@ -1,9 +1,10 @@ +import add from 'date-fns/add' + import { TRIGGER_DOCTYPE } from 'doctypes' import { logger } from 'ducks/konnectorAlerts' import { - add, - getTriggerStates, - fetchRelatedFuturAtTriggers + fetchRelatedFuturAtTriggers, + getTriggerStates } from 'targets/services/konnectorAlerts/helpers' const createTriggerAt = async ({ client, date, konnectorTriggerId }) => { diff --git a/src/targets/services/konnectorAlerts/createTriggerAt.spec.js b/src/targets/services/konnectorAlerts/createTriggerAt.spec.js index 300a81bf93..3e2585e470 100644 --- a/src/targets/services/konnectorAlerts/createTriggerAt.spec.js +++ b/src/targets/services/konnectorAlerts/createTriggerAt.spec.js @@ -1,7 +1,8 @@ import { createMockClient } from 'cozy-client' +import sub from 'date-fns/sub' import { createScheduledTrigger, containerForTesting } from './createTriggerAt' -import { fetchRelatedFuturAtTriggers, getTriggerStates, sub } from './helpers' +import { fetchRelatedFuturAtTriggers, getTriggerStates } from './helpers' jest.mock('./helpers', () => ({ ...jest.requireActual('./helpers'), @@ -56,7 +57,11 @@ describe('createTriggerAt', () => { getTriggerStates.mockResolvedValue({ trigger01Id: { shouldNotify: { ok: true }, - last_failure: sub(Date.now(), { hours: 23, minutes: 59, seconds: 59 }) + last_failure: sub(Date.now(), { + hours: 23, + minutes: 59, + seconds: 59 + }) } }) fetchRelatedFuturAtTriggers.mockResolvedValue([]) diff --git a/src/targets/services/konnectorAlerts/helpers.js b/src/targets/services/konnectorAlerts/helpers.js index 8e6056a1ed..e4fd9c15f7 100644 --- a/src/targets/services/konnectorAlerts/helpers.js +++ b/src/targets/services/konnectorAlerts/helpers.js @@ -1,15 +1,8 @@ import memoize from 'lodash/memoize' import keyBy from 'lodash/keyBy' import get from 'lodash/get' -import addDays from 'date-fns/add_days' -import addHours from 'date-fns/add_hours' -import addMinutes from 'date-fns/add_minutes' -import addSeconds from 'date-fns/add_seconds' -import parse from 'date-fns/parse' -import subDays from 'date-fns/sub_days' -import subHours from 'date-fns/sub_hours' -import subMinutes from 'date-fns/sub_minutes' -import subSeconds from 'date-fns/sub_seconds' +import sub from 'date-fns/sub' +import toDate from 'date-fns/toDate' import { Q } from 'cozy-client' @@ -125,11 +118,5 @@ export const fetchRelatedFuturAtTriggers = async (client, id) => { return data } -export const add = (base, { days = 0, hours = 0, minutes = 0, seconds = 0 }) => - addDays(addHours(addMinutes(addSeconds(base, seconds), minutes), hours), days) - -export const sub = (base, { days = 0, hours = 0, minutes = 0, seconds = 0 }) => - subDays(subHours(subMinutes(subSeconds(base, seconds), minutes), hours), days) - export const isOlderThan = (referenceDate, { days, hours, minutes, seconds }) => - parse(referenceDate) < sub(Date.now(), { days, hours, minutes, seconds }) + toDate(referenceDate) < sub(Date.now(), { days, hours, minutes, seconds }) diff --git a/src/targets/services/konnectorAlerts/helpers.spec.js b/src/targets/services/konnectorAlerts/helpers.spec.js index 4730192584..d35e82f9f3 100644 --- a/src/targets/services/konnectorAlerts/helpers.spec.js +++ b/src/targets/services/konnectorAlerts/helpers.spec.js @@ -1,7 +1,8 @@ import { createMockClient } from 'cozy-client' import MockDate from 'mockdate' +import parseISO from 'date-fns/parseISO' -import { add, storeTriggerStates, isOlderThan, sub } from './helpers' +import { isOlderThan, storeTriggerStates } from './helpers' const triggerStatesWithNotifsInfo = [ { @@ -58,67 +59,6 @@ describe('storeTriggerStates', () => { }) }) -describe('sub', () => { - it('returns a Date object', () => { - expect( - sub(Date.now(), { days: 1, hours: 2, minutes: 3, seconds: 4 }) - ).toBeInstanceOf(Date) - expect( - sub(new Date(), { days: 1, hours: 2, minutes: 3, seconds: 4 }) - ).toBeInstanceOf(Date) - }) - - it('returns the expected past date', () => { - const base = Date.parse('28 Sep 2022 11:14:37 GMT') - - const past = sub(base, { days: 1, hours: 2, minutes: 3, seconds: 4 }) - expect(past.getUTCFullYear()).toBe(2022) - expect(past.getUTCMonth()).toBe(8) // Months are 0 indexed - expect(past.getUTCDate()).toBe(27) - expect(past.getUTCHours()).toBe(9) - expect(past.getUTCMinutes()).toBe(11) - expect(past.getUTCSeconds()).toBe(33) - }) -}) - -describe('add', () => { - it('returns a Date object', () => { - expect( - add(Date.now(), { - days: 1, - hours: 2, - minutes: 3, - seconds: 4 - }) - ).toBeInstanceOf(Date) - expect( - add(new Date(), { - days: 1, - hours: 2, - minutes: 3, - seconds: 4 - }) - ).toBeInstanceOf(Date) - }) - - it('returns the expected future date', () => { - const base = Date.parse('28 Sep 2022 11:14:37 GMT') - - const future = add(base, { - days: 1, - hours: 2, - minutes: 3, - seconds: 4 - }) - expect(future.getUTCFullYear()).toBe(2022) - expect(future.getUTCMonth()).toBe(8) // Months are 0 indexed - expect(future.getUTCDate()).toBe(29) - expect(future.getUTCHours()).toBe(13) - expect(future.getUTCMinutes()).toBe(17) - expect(future.getUTCSeconds()).toBe(41) - }) -}) - describe('isOlderThan', () => { afterEach(() => { MockDate.reset() @@ -127,12 +67,16 @@ describe('isOlderThan', () => { it('returns true if given date is older than given time parameters', () => { MockDate.set(Date.parse('28 Sep 2022 11:14:37 GMT')) - expect(isOlderThan('2022-09-28T11:14:33Z', { seconds: 3 })).toBe(true) + expect(isOlderThan(parseISO('2022-09-28T11:14:33Z'), { seconds: 3 })).toBe( + true + ) }) it('returns false if given date is not older than given time parameters', () => { MockDate.set(Date.parse('28 Sep 2022 11:14:37 GMT')) - expect(isOlderThan('2022-09-28T11:14:33Z', { seconds: 4 })).toBe(false) + expect(isOlderThan(parseISO('2022-09-28T11:14:33Z'), { seconds: 4 })).toBe( + false + ) }) }) diff --git a/src/targets/services/konnectorAlerts/shouldNotify.js b/src/targets/services/konnectorAlerts/shouldNotify.js index 2700b88bf3..15049ec494 100644 --- a/src/targets/services/konnectorAlerts/shouldNotify.js +++ b/src/targets/services/konnectorAlerts/shouldNotify.js @@ -1,4 +1,5 @@ import get from 'lodash/get' +import parseISO from 'date-fns/parseISO' import { Q } from 'cozy-client' @@ -44,7 +45,10 @@ export const shouldNotify = async ({ client, trigger, previousStates }) => { // minutes, with a maximum of 15 minutes, so we prevent notifications to be // sent if we're past that delay. if ( - isOlderThan(trigger.current_state.last_failure, { days: 7, minutes: 15 }) + isOlderThan(parseISO(trigger.current_state.last_failure), { + days: 7, + minutes: 15 + }) ) { return { ok: false, reason: 'last-failure-too-old' } } diff --git a/src/targets/services/konnectorAlerts/shouldNotify.spec.js b/src/targets/services/konnectorAlerts/shouldNotify.spec.js index 09729a5a61..fa7c54b1a5 100644 --- a/src/targets/services/konnectorAlerts/shouldNotify.spec.js +++ b/src/targets/services/konnectorAlerts/shouldNotify.spec.js @@ -1,8 +1,8 @@ import { createMockClient } from 'cozy-client' import MockDate from 'mockdate' +import sub from 'date-fns/sub' import { shouldNotify } from './shouldNotify' -import { sub } from './helpers' describe('shouldNotify', () => { const setup = ({ last_failure } = {}) => { diff --git a/src/utils/token.js b/src/utils/token.js index 3a77308703..ebb33f806a 100644 --- a/src/utils/token.js +++ b/src/utils/token.js @@ -1,4 +1,6 @@ -import { isBefore, subDays, isValid } from 'date-fns' +import isBefore from 'date-fns/isBefore' +import subDays from 'date-fns/subDays' +import isValid from 'date-fns/isValid' /** * This check will be removed when we will be able to inject a cozy-client diff --git a/test/fixtures/helpers/freshDate.js b/test/fixtures/helpers/freshDate.js index 8e0953dc3c..a13420017d 100644 --- a/test/fixtures/helpers/freshDate.js +++ b/test/fixtures/helpers/freshDate.js @@ -1,7 +1,7 @@ const demoFixtures = require('../demo.json') const last = require('lodash/last') -const differenceInDays = require('date-fns/difference_in_days') -const addDays = require('date-fns/add_days') +const differenceInDays = require('date-fns/differenceInDays') +const addDays = require('date-fns/addDays') const getMostRecentDate = dates => { const sorted = dates.sort() diff --git a/yarn.lock b/yarn.lock index 8e36ad00eb..b261be6cbf 100644 --- a/yarn.lock +++ b/yarn.lock @@ -6281,7 +6281,12 @@ datauri@^2.0.0: image-size "^0.7.3" mimer "^1.0.0" -date-fns@1.30.1, date-fns@^1.27.2, date-fns@^1.28.5, date-fns@^1.30.1: +date-fns@2.29.3: + version "2.29.3" + resolved "https://registry.yarnpkg.com/date-fns/-/date-fns-2.29.3.tgz#27402d2fc67eb442b511b70bbdf98e6411cd68a8" + integrity sha512-dDCnyH2WnnKusqvZZ6+jA1O51Ibt8ZMRNkDZdyAyK4YfbDwa/cEmuztzG5pk6hqlp9aSBPYcjOlktquahGwGeA== + +date-fns@^1.27.2, date-fns@^1.28.5, date-fns@^1.30.1: version "1.30.1" resolved "https://registry.yarnpkg.com/date-fns/-/date-fns-1.30.1.tgz#2e71bf0b119153dbb4cc4e88d9ea5acfb50dc05c" integrity sha512-hBSVCvSmWC+QypYObzwGOd9wqdDpOt+0wl0KbU+R+uuZBS1jN8VsD1ss3irQDknRj5NvxiTF6oj/nDRnN/UQNw==