Merge pull request #152 from SebastianMC/151-sort-notes-in-dd-mmm-yyyy-format

151 sort notes in dd mmm yyyy format
This commit is contained in:
SebastianMC 2024-07-10 12:07:48 +02:00 committed by GitHub
commit fa6aafa3bd
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 79 additions and 10 deletions

View File

@ -1,3 +1,5 @@
import {toString} from "builtin-modules";
export const RomanNumberRegexStr: string = ' *([MDCLXVI]+)'; // Roman number
export const CompoundRomanNumberDotRegexStr: string = ' *([MDCLXVI]+(?:\\.[MDCLXVI]+)*)';// Compound Roman number with dot as separator
export const CompoundRomanNumberDashRegexStr: string = ' *([MDCLXVI]+(?:-[MDCLXVI]+)*)'; // Compound Roman number with dash as separator
@ -6,6 +8,8 @@ export const NumberRegexStr: string = ' *(\\d+)'; // Plain number
export const CompoundNumberDotRegexStr: string = ' *(\\d+(?:\\.\\d+)*)'; // Compound number with dot as separator
export const CompoundNumberDashRegexStr: string = ' *(\\d+(?:-\\d+)*)'; // Compound number with dash as separator
export const Date_dd_Mmm_yyyy_RegexStr: string = ' *([0-3]*[0-9]-(?:Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec)-\\d{4})'; // Date like 01-Jan-2020
export const DOT_SEPARATOR = '.'
export const DASH_SEPARATOR = '-'
@ -23,12 +27,16 @@ export const WordInAnyLanguageRegexStr = '(\\p{Letter}+)' // remember about th
export const WordInASCIIRegexStr = '([a-zA-Z]+)'
export function prependWithZeros(s: string, minLength: number) {
if (s.length < minLength) {
const delta: number = minLength - s.length;
return '000000000000000000000000000'.substring(0, delta) + s;
export function prependWithZeros(s: string|undefined, minLength: number): string {
if ('string' === typeof s) {
if (s.length < minLength) {
const delta: number = minLength - s.length;
return '000000000000000000000000000'.substring(0, delta) + s;
} else {
return s;
}
} else {
return s;
return prependWithZeros((s ?? '').toString(), minLength)
}
}
@ -95,3 +103,18 @@ export function getNormalizedRomanNumber(s: string, separator?: string, places?:
return `${prependWithZeros(romanToIntStr(s), places ?? DEFAULT_NORMALIZATION_PLACES)}//`
}
}
const DAY_POSITIONS = '00'.length
const MONTH_POSITIONS = '00'.length
const YEAR_POSITIONS = '0000'.length
const MONTHS = ['Jan','Feb','Mar','Apr','May','Jun','Jul','Aug','Sep','Oct','Nov','Dec']
export function getNormalizedDate_dd_Mmm_yyyy_NormalizerFn(s: string): string | null {
// Assumption - the regex date matched against input s, no extensive defensive coding needed
const components = s.split('-')
const day = prependWithZeros(components[0], DAY_POSITIONS)
const month = prependWithZeros( `${1 + MONTHS.indexOf(components[1])}`, MONTH_POSITIONS)
const year = prependWithZeros(components[2], YEAR_POSITIONS)
return `${year}-${month}-${day}//`
}

View File

@ -16,7 +16,9 @@ import {
CompoundRomanNumberDashRegexStr,
CompoundRomanNumberDotRegexStr,
DASH_SEPARATOR,
Date_dd_Mmm_yyyy_RegexStr,
DOT_SEPARATOR,
getNormalizedDate_dd_Mmm_yyyy_NormalizerFn,
getNormalizedNumber,
getNormalizedRomanNumber,
NumberRegexStr,
@ -348,6 +350,8 @@ const InlineRegexSymbol_Digit1: string = '\\d'
const InlineRegexSymbol_Digit2: string = '\\[0-9]'
const InlineRegexSymbol_0_to_3: string = '\\[0-3]'
const Date_dd_Mmm_yyyy_RegexSymbol: string = '\\[dd-Mmm-yyyy]'
const InlineRegexSymbol_CapitalLetter: string = '\\C'
const InlineRegexSymbol_LowercaseLetter: string = '\\l'
@ -365,7 +369,8 @@ const sortingSymbolsArr: Array<string> = [
escapeRegexUnsafeCharacters(CompoundRomanNumberDotRegexSymbol),
escapeRegexUnsafeCharacters(CompoundRomanNumberDashRegexSymbol),
escapeRegexUnsafeCharacters(WordInASCIIRegexSymbol),
escapeRegexUnsafeCharacters(WordInAnyLanguageRegexSymbol)
escapeRegexUnsafeCharacters(WordInAnyLanguageRegexSymbol),
escapeRegexUnsafeCharacters(Date_dd_Mmm_yyyy_RegexSymbol)
]
const sortingSymbolsRegex = new RegExp(sortingSymbolsArr.join('|'), 'gi')
@ -433,6 +438,7 @@ export const CompoundDashRomanNumberNormalizerFn: NormalizerFn = (s: string) =>
export const NumberNormalizerFn: NormalizerFn = (s: string) => getNormalizedNumber(s)
export const CompoundDotNumberNormalizerFn: NormalizerFn = (s: string) => getNormalizedNumber(s, DOT_SEPARATOR)
export const CompoundDashNumberNormalizerFn: NormalizerFn = (s: string) => getNormalizedNumber(s, DASH_SEPARATOR)
export const Date_dd_Mmm_yyyy_NormalizerFn: NormalizerFn = (s: string) => getNormalizedDate_dd_Mmm_yyyy_NormalizerFn(s)
export enum AdvancedRegexType {
None, // to allow if (advancedRegex)
@ -443,7 +449,8 @@ export enum AdvancedRegexType {
CompoundDotRomanNumber,
CompoundDashRomanNumber,
WordInASCII,
WordInAnyLanguage
WordInAnyLanguage,
Date_dd_Mmm_yyyy
}
const sortingSymbolToRegexpStr: { [key: string]: RegExpSpecStr } = {
@ -487,6 +494,11 @@ const sortingSymbolToRegexpStr: { [key: string]: RegExpSpecStr } = {
normalizerFn: IdentityNormalizerFn,
advancedRegexType: AdvancedRegexType.WordInAnyLanguage,
unicodeRegex: true
},
[Date_dd_Mmm_yyyy_RegexSymbol]: { // Intentionally retain character case
regexpStr: Date_dd_Mmm_yyyy_RegexStr,
normalizerFn: Date_dd_Mmm_yyyy_NormalizerFn,
advancedRegexType: AdvancedRegexType.Date_dd_Mmm_yyyy
}
}

View File

@ -10,7 +10,7 @@ import {
CompoundRomanNumberDotRegexStr,
CompoundRomanNumberDashRegexStr,
WordInASCIIRegexStr,
WordInAnyLanguageRegexStr
WordInAnyLanguageRegexStr, getNormalizedDate_dd_Mmm_yyyy_NormalizerFn
} from "../../custom-sort/matchers";
describe('Plain numbers regexp', () => {
@ -405,3 +405,29 @@ describe('getNormalizedRomanNumber', () => {
expect(getNormalizedRomanNumber(s, separator, LEN)).toBe(out)
})
})
describe('getNormalizedDate_dd_Mmm_yyyy_NormalizerFn', () => {
const params = [
['13-Jan-2012', '2012-01-13//'],
['3-Feb-2', '0002-02-03//'],
['1-Mar-1900', '1900-03-01//'],
['42-Apr-9999', '9999-04-42//'],
['0-May-0', '0000-05-00//'],
['21-Jun-2024', '2024-06-21//'],
['7-Jul-1872', '1872-07-07//'],
['15-Aug-1234', '1234-08-15//'],
['1234-Sep-7777', '7777-09-1234//'],
['3-Oct-2023', '2023-10-03//'],
['8-Nov-2022', '2022-11-08//'],
['18-Dec-2021', '2021-12-18//'],
['88-Dec-2012', '2012-12-88//'], // Invalid case, Regexp on matcher in the caller should guard against this
['13-JANUARY-2012', '2012-00-13//'], // Invalid case, Regexp on matcher in the caller should guard against this
['1 .1', '0000-00-1 .1//'], // Invalid case, Regexp on matcher in the caller should guard against this
['', '0000-00-00//'], // Invalid case, Regexp on matcher in the caller should guard against this
['abc', '0000-00-abc//'], // Invalid case, Regexp on matcher in the caller should guard against this
['def-abc', '0000-00-def//'], // Invalid case, Regexp on matcher in the caller should guard against this
];
it.each(params)('>%s< should become %s', (s: string, out: string) => {
expect(getNormalizedDate_dd_Mmm_yyyy_NormalizerFn(s)).toBe(out)
})
})

View File

@ -4,7 +4,7 @@ import {
CompoundDotNumberNormalizerFn,
ConsumedFolderMatchingRegexp,
consumeFolderByRegexpExpression,
convertPlainStringToRegex,
convertPlainStringToRegex, Date_dd_Mmm_yyyy_NormalizerFn,
detectSortingSymbols,
escapeRegexUnsafeCharacters,
extractSortingSymbol,
@ -404,11 +404,17 @@ const expectedSortSpecsExampleSortingSymbols: { [key: string]: CustomSortSpec }
regex: /^(\p{Letter}+)\. is for any modern language word$/iu,
normalizerFn: IdentityNormalizerFn
}
}, {
type: CustomSortGroupType.ExactName,
regexPrefix: {
regex: /^ *([0-3]*[0-9]-(?:Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec)-\d{4}) for the specific date format of 12\-Apr\-2024$/i,
normalizerFn: Date_dd_Mmm_yyyy_NormalizerFn
}
}, {
type: CustomSortGroupType.Outsiders
}],
targetFoldersPaths: ['mock-folder'],
outsidersGroupIdx: 7
outsidersGroupIdx: 8
}
}
@ -420,6 +426,7 @@ Plain syntax\\R+ ... works?
And this kind of... \\D+plain syntax???
Here goes ASCII word \\a+
\\A+. is for any modern language word
\\[dd-Mmm-yyyy] for the specific date format of 12-Apr-2024
`
describe('SortingSpecProcessor', () => {
@ -3141,6 +3148,7 @@ describe('hasMoreThanOneSortingSymbol', () => {
['\\-r+', false], ['--\\-r+--\\-D+++', true],
['\\d+abcd\\d+efgh', true],
['\\R+abcd\\.R+efgh', true],
['\\R+abcd\\[dd-Mmm-yyyy]', true],
['\\d+\\.D+\\-d+\\R+\\.r+\\-R+ \\d+', true]
])('should correctly detect in >%s< (%s) sorting regex symbols', (s: string, b: boolean) => {
const result = hasMoreThanOneSortingSymbol(s)