From fbec58a50bf91cf1d80731173be470dc840c9c2b Mon Sep 17 00:00:00 2001 From: Finn Weigand <52424812+Hudint@users.noreply.github.com> Date: Fri, 9 May 2025 15:08:17 +0200 Subject: [PATCH] feat: allow to write date via Quick Add Magic in DMY format with dots (#744) Co-authored-by: Hudint Finn Weigand --- .../tasks/partials/QuickAddMagic.vue | 4 +- frontend/src/helpers/time/parseDate.ts | 70 ++++++++++--------- frontend/src/modules/parseTaskText.test.ts | 5 +- 3 files changed, 44 insertions(+), 35 deletions(-) diff --git a/frontend/src/components/tasks/partials/QuickAddMagic.vue b/frontend/src/components/tasks/partials/QuickAddMagic.vue index 880f05c48..5583a954e 100644 --- a/frontend/src/components/tasks/partials/QuickAddMagic.vue +++ b/frontend/src/components/tasks/partials/QuickAddMagic.vue @@ -73,7 +73,9 @@
  • End of month
  • In 5 days [hours/weeks/months]
  • Tuesday ({{ $t('task.quickAddMagic.dateWeekday') }})
  • -
  • 17/02/2021
  • +
  • 02/17/2021
  • +
  • 2021-02-17
  • +
  • 17.02.2021
  • Feb 17 ({{ $t('task.quickAddMagic.dateCurrentYear') }})
  • 17th ({{ $t('task.quickAddMagic.dateNth', {day: '17'}) }})
  • diff --git a/frontend/src/helpers/time/parseDate.ts b/frontend/src/helpers/time/parseDate.ts index cd27c074d..9d04338bf 100644 --- a/frontend/src/helpers/time/parseDate.ts +++ b/frontend/src/helpers/time/parseDate.ts @@ -85,11 +85,11 @@ export const parseDate = (text: string, now: Date = new Date()): dateParseResult if (parsed.date === null) { const time = addTimeToDate(text, new Date(now), parsed.foundText) - + if (time.date !== null && +now !== +time.date) { return time } - + return { newText: replaceAll(text, parsed.foundText, ''), date: parsed.date, @@ -138,46 +138,50 @@ const addTimeToDate = (text: string, date: Date, previousMatch: string | null): } export const getDateFromText = (text: string, now: Date = new Date()) => { - const fullDateRegex = /(^| )([0-9][0-9]?\/[0-9][0-9]?\/[0-9][0-9]([0-9][0-9])?|[0-9][0-9][0-9][0-9]\/[0-9][0-9]?\/[0-9][0-9]?|[0-9][0-9][0-9][0-9]-[0-9][0-9]?-[0-9][0-9]?)/ig + const dateRegexes: RegExp[] = [ + /(^| )(?(?[0-9][0-9]?)\/(?[0-9][0-9]?)(\/(?[0-9][0-9]([0-9][0-9])?))?)($| )/gi, + /(^| )(?(?[0-9][0-9][0-9][0-9]?)\/(?[0-9][0-9]?)\/(?[0-9][0-9]))($| )/gi, + /(^| )(?(?[0-9][0-9][0-9][0-9]?)-(?[0-9][0-9]?)-(?[0-9][0-9]))($| )/gi, + /(^| )(?(?[0-9][0-9]?)\.(?[0-9][0-9]?)(\.(?[0-9][0-9]([0-9][0-9])?))?)($| )/gi, + ] - // 1. Try parsing the text as a "usual" date, like 2021-06-24 or 06/24/2021 - let results: string[] | null = fullDateRegex.exec(text) - let result: string | null = results === null ? null : results[0] - let foundText: string | null = result + let result: string | null = null + let results: RegExpExecArray | null = null + let foundText: string | null = '' let containsYear = true + + // 1. Try parsing the text as a "usual" date, like 2021-06-24 or "06/24/2021" or "27/01" or "01/27" + for (const dateRegex of dateRegexes) { + results = dateRegex.exec(text) + if (results !== null) { + const {day, month, year, found} = {...results.groups} + let tmp_year = year + + if (tmp_year === undefined) { + tmp_year = year ?? now.getFullYear() + containsYear = false + } + + result = `${month}/${day}/${tmp_year}` + result = !isNaN(new Date(result).getTime()) ? result : `${day}/${month}/${tmp_year}` + result = !isNaN(new Date(result).getTime()) ? result : null + + if(result !== null){ + foundText = found + break + } + } + } + + // 2. Try parsing the date as something like "jan 21" or "21 jan" if (result === null) { - // 2. Try parsing the date as something like "jan 21" or "21 jan" const monthRegex = new RegExp(`(^| )(${monthsRegexGroup} [0-9][0-9]?|[0-9][0-9]? ${monthsRegexGroup})`, 'ig') results = monthRegex.exec(text) result = results === null ? null : `${results[0]} ${now.getFullYear()}`.trim() foundText = results === null ? '' : results[0].trim() containsYear = false - - if (result === null) { - // 3. Try parsing the date as "27/01" or "01/27" - const monthNumericRegex = /(^| )([0-9][0-9]?\/[0-9][0-9]?)/ig - results = monthNumericRegex.exec(text) - - // Put the year before or after the date, depending on what works - result = results === null ? null : `${now.getFullYear()}/${results[0]}` - if (result === null) { - return { - foundText, - date: null, - } - } - - foundText = results === null ? '' : results[0] - if (result === null || isNaN(new Date(result).getTime())) { - result = results === null ? null : `${results[0]}/${now.getFullYear()}` - } - if (result === null || (isNaN(new Date(result).getTime()) && foundText !== '')) { - const parts = foundText.split('/') - result = `${parts[1]}/${parts[0]}/${now.getFullYear()}` - } - } } - + if (result === null) { return { foundText, diff --git a/frontend/src/modules/parseTaskText.test.ts b/frontend/src/modules/parseTaskText.test.ts index 68baf8680..2d8e19e6b 100644 --- a/frontend/src/modules/parseTaskText.test.ts +++ b/frontend/src/modules/parseTaskText.test.ts @@ -515,7 +515,10 @@ describe('Parse Task Text', () => { 'dec 21': '2021-12-21', 'Dec 21': '2021-12-21', 'december 21': '2021-12-21', - 'December 21': '2021-12-21', + '01.02.2021': '2021-2-1', + '01.02': '2022-2-1', + '01.10': '2021-10-1', + '01.02.25': '2025-2-1', } as Record for (const c in cases) {