From eb63802d013a1fa6543e76de5b2b3643fba78bbd Mon Sep 17 00:00:00 2001 From: Frane Caleta Date: Sat, 23 Sep 2023 16:14:54 +0200 Subject: [PATCH] Feature/extend supported date formats in activities import (#2362) * Extend supported date formats in activities import * Update changelog --- CHANGELOG.md | 1 + .../app/services/import-activities.service.ts | 27 ++----------- libs/common/src/lib/helper.ts | 40 +++++++++++++++++-- test/import/ok.csv | 6 +-- 4 files changed, 45 insertions(+), 29 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 71cd5ef90..6777197b6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Added +- Added support for dates in `DD.MM.YYYY` format in the activities import - Set up the language localization for Türkçe (`tr`) ## 2.4.0 - 2023-09-19 diff --git a/apps/client/src/app/services/import-activities.service.ts b/apps/client/src/app/services/import-activities.service.ts index 02eeb7e03..808081bea 100644 --- a/apps/client/src/app/services/import-activities.service.ts +++ b/apps/client/src/app/services/import-activities.service.ts @@ -3,8 +3,8 @@ import { Injectable } from '@angular/core'; import { CreateAccountDto } from '@ghostfolio/api/app/account/create-account.dto'; import { CreateOrderDto } from '@ghostfolio/api/app/order/create-order.dto'; import { Activity } from '@ghostfolio/api/app/order/interfaces/activities.interface'; +import { parseDate as parseDateHelper } from '@ghostfolio/common/helper'; import { Account, DataSource, Type } from '@prisma/client'; -import { isMatch, parse, parseISO } from 'date-fns'; import { isFinite } from 'lodash'; import { parse as csvToJson } from 'papaparse'; import { EMPTY } from 'rxjs'; @@ -219,31 +219,12 @@ export class ImportActivitiesService { item: any; }) { item = this.lowercaseKeys(item); - let date: string; for (const key of ImportActivitiesService.DATE_KEYS) { if (item[key]) { - if (isMatch(item[key], 'dd-MM-yyyy') && item[key].length === 10) { - // Check length to only match yyyy (and not yy) - date = parse(item[key], 'dd-MM-yyyy', new Date()).toISOString(); - } else if ( - isMatch(item[key], 'dd/MM/yyyy') && - item[key].length === 10 - ) { - // Check length to only match yyyy (and not yy) - date = parse(item[key], 'dd/MM/yyyy', new Date()).toISOString(); - } else if (isMatch(item[key], 'yyyyMMdd') && item[key].length === 8) { - // Check length to only match yyyy (and not yy) - date = parse(item[key], 'yyyyMMdd', new Date()).toISOString(); - } else { - try { - date = parseISO(item[key]).toISOString(); - } catch {} - } - - if (date) { - return date; - } + try { + return parseDateHelper(item[key].toString()).toISOString(); + } catch {} } } diff --git a/libs/common/src/lib/helper.ts b/libs/common/src/lib/helper.ts index 43cc6d9f0..54c58c4cb 100644 --- a/libs/common/src/lib/helper.ts +++ b/libs/common/src/lib/helper.ts @@ -1,7 +1,15 @@ import * as currencies from '@dinero.js/currencies'; import { DataSource } from '@prisma/client'; import Big from 'big.js'; -import { getDate, getMonth, getYear, parse, subDays } from 'date-fns'; +import { + getDate, + getMonth, + getYear, + isMatch, + parse, + parseISO, + subDays +} from 'date-fns'; import { de, es, fr, it, nl, pt, tr } from 'date-fns/locale'; import { ghostfolioScraperApiSymbolPrefix, locale } from './config'; @@ -284,8 +292,34 @@ export const DATE_FORMAT = 'yyyy-MM-dd'; export const DATE_FORMAT_MONTHLY = 'MMMM yyyy'; export const DATE_FORMAT_YEARLY = 'yyyy'; -export function parseDate(date: string) { - return parse(date, DATE_FORMAT, new Date()); +export function parseDate(date: string): Date | null { + // Transform 'yyyyMMdd' format to supported format by parse function + if (date.length === 8) { + const match = date.match(/^(\d{4})(\d{2})(\d{2})$/); + + if (match) { + const [, year, month, day] = match; + date = `${year}-${month}-${day}`; + } + } + + const dateFormat = [ + 'dd-MM-yyyy', + 'dd/MM/yyyy', + 'dd.MM.yyyy', + 'yyyy-MM-dd', + 'yyyy/MM/dd', + 'yyyy.MM.dd', + 'yyyyMMdd' + ].find((format) => { + return isMatch(date, format) && format.length === date.length; + }); + + if (dateFormat) { + return parse(date, dateFormat, new Date()); + } + + return parseISO(date); } export function prettifySymbol(aSymbol: string): string { diff --git a/test/import/ok.csv b/test/import/ok.csv index 2d27422ab..732ab4699 100644 --- a/test/import/ok.csv +++ b/test/import/ok.csv @@ -1,5 +1,5 @@ Date,Code,Currency,Price,Quantity,Action,Fee +16-09-2021,MSFT,USD,298.580,5,buy,19.00 17/11/2021,MSFT,USD,0.62,5,dividend,0.00 -16/09/2021,MSFT,USD,298.580,5,buy,19.00 -01/01/2022,Penthouse Apartment,USD,500000.0,1,item,0.00 -06/06/2050,MSFT,USD,0.00,0,buy,0.00 +01.01.2022,Penthouse Apartment,USD,500000.0,1,item,0.00 +20500606,MSFT,USD,0.00,0,buy,0.00