@accounter/server
Version:
185 lines (169 loc) • 5.02 kB
text/typescript
import type { TimelessDateString } from '@shared/types';
function parseIntRound(v: number) {
return Math.trunc(v + Math.sign(v) / 2);
}
export function stringNumberRounded(number: string): number {
return parseIntRound((parseFloat(number) + Number.EPSILON) * 100) / 100;
}
export function numberRounded(number: number): number {
return parseIntRound((number + Number.EPSILON) * 100) / 100;
}
export function isTimelessDateString(date: string): date is TimelessDateString {
const parts = date.split('-');
if (parts.length !== 3) {
return false;
}
const [year, month, day] = parts;
//year
const yearNum = Number(year);
if (Number.isNaN(yearNum) || yearNum < 2000 || yearNum > 2049) {
return false;
}
// month
const monthNum = Number(month);
if (Number.isNaN(monthNum) || monthNum < 1 || monthNum > 12) {
return false;
}
// day
const dayNum = Number(day);
if (Number.isNaN(dayNum) || dayNum < 1 || dayNum > 31) {
return false;
}
return true;
}
export function isUUID(raw: string) {
const regexExp =
/^[0-9a-fA-F]{8}\b-[0-9a-fA-F]{4}\b-[0-9a-fA-F]{4}\b-[0-9a-fA-F]{4}\b-[0-9a-fA-F]{12}$/gi;
return regexExp.test(raw);
}
function convertMonthNameToNumber(monthName: string): string | null {
const lowerCasedName = monthName.toLocaleLowerCase();
let month: string | null = null;
switch (lowerCasedName) {
case 'january':
case 'jan':
month = '01';
break;
case 'february':
case 'feb':
month = '02';
break;
case 'march':
case 'mar':
month = '03';
break;
case 'april':
case 'apr':
month = '04';
break;
case 'may':
month = '05';
break;
case 'june':
case 'jun':
month = '06';
break;
case 'july':
case 'jul':
month = '07';
break;
case 'august':
case 'aug':
month = '08';
break;
case 'september':
case 'sep':
month = '09';
break;
case 'october':
case 'oct':
month = '10';
break;
case 'november':
case 'nov':
month = '11';
break;
case 'december':
case 'dec':
month = '12';
break;
default:
break;
}
return month;
}
/**
* @description
* Extract month from description
* @param rawDescription string - description to extract month from
* @param eventDate Date - optional, if provided, will use it to determine year
* @returns month in format yyyy-mm, else null
*/
export function getMonthFromDescription(rawDescription: string, eventDate?: Date): string | null {
if (!rawDescription.length) {
return null;
}
const description = rawDescription?.toLocaleLowerCase();
// search for "yyyy-mm" in description
const dateRegex = /\b(\d{4})-(\d{2})\b/;
const matches = description.match(dateRegex);
if (matches?.length) {
const month = matches[0];
return month;
}
// search for "mm-yyyy" in description
const dateRegex2 = /\b(\d{2})-(\d{4})\b/;
const matches2 = description.match(dateRegex2);
if (matches2?.length) {
const month = matches2[0];
const adjustedMonth = month.split('-').reverse().join('-');
return adjustedMonth;
}
// search for "mm/yyyy" in description
const dateRegex3 = /\b(\d{2})\/(\d{4})\b/;
const matches3 = description.match(dateRegex3);
if (matches3?.length) {
const month = matches3[0];
const adjustedMonth = month.split('/').reverse().join('-');
return adjustedMonth;
}
// search for "mm/yy" in description
const dateRegex4 = /\b(\d{2})\/(\d{2})\b/;
const matches4 = description.match(dateRegex4);
if (matches4?.length) {
const month = matches4[0];
const adjustedMonth = '20' + month.split('/').reverse().join('-');
return adjustedMonth;
}
// search for month name in description
const dateRegex5 =
/\b(?:jan(?:uary)?|feb(?:ruary)?|mar(?:ch)?|apr(?:il)?|may|jun(?:e)?|jul(?:y)?|aug(?:ust)?|sep(?:tember)?|oct(?:ober)?|(nov|dec)(?:ember)?)\b/;
const matches5 = description.match(dateRegex5);
if (matches5?.length) {
const monthName = matches5[0];
const month = convertMonthNameToNumber(monthName);
if (month) {
// try to search for year in description
const dateRegex5 =
/\b(?:jan(?:uary)?|feb(?:ruary)?|mar(?:ch)?|apr(?:il)?|may|jun(?:e)?|jul(?:y)?|aug(?:ust)?|sep(?:tember)?|oct(?:ober)?|(nov|dec)(?:ember)?) (?:19[7-9]\d|2\d{3})\b/;
const matches5 = description.match(dateRegex5);
if (matches5?.length) {
const year = matches5[0].split(' ')[1];
if (year) {
const adjustedMonth = `${year}-${month}`;
return adjustedMonth;
}
}
if (eventDate) {
let year = eventDate.getFullYear();
// case date is in Jan/Feb and salary month is Nov/Dec, use date's prev year
if (eventDate.getMonth() < 2 && month > '10') {
year--;
}
const adjustedMonth = `${year}-${month}`;
return adjustedMonth;
}
}
}
return null;
}