@alveole/core 0.34.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +3 -0
- package/dist/date/addTimes.d.ts +10 -0
- package/dist/date/addTimes.d.ts.map +1 -0
- package/dist/date/addTimes.js +25 -0
- package/dist/date/dateFormat.d.ts +22 -0
- package/dist/date/dateFormat.d.ts.map +1 -0
- package/dist/date/dateFormat.js +20 -0
- package/dist/date/displayDate.d.ts +23 -0
- package/dist/date/displayDate.d.ts.map +1 -0
- package/dist/date/displayDate.js +37 -0
- package/dist/date/displayDate.test.d.ts +2 -0
- package/dist/date/displayDate.test.d.ts.map +1 -0
- package/dist/date/displayDate.test.js +34 -0
- package/dist/date/formatDateRangeLabel.d.ts +8 -0
- package/dist/date/formatDateRangeLabel.d.ts.map +1 -0
- package/dist/date/formatDateRangeLabel.js +21 -0
- package/dist/date/formatMinutes.d.ts +2 -0
- package/dist/date/formatMinutes.d.ts.map +1 -0
- package/dist/date/formatMinutes.js +10 -0
- package/dist/date/formatMs.d.ts +2 -0
- package/dist/date/formatMs.d.ts.map +1 -0
- package/dist/date/formatMs.js +7 -0
- package/dist/date/formatMs.test.d.ts +2 -0
- package/dist/date/formatMs.test.d.ts.map +1 -0
- package/dist/date/formatMs.test.js +24 -0
- package/dist/date/formatSec.d.ts +2 -0
- package/dist/date/formatSec.d.ts.map +1 -0
- package/dist/date/formatSec.js +5 -0
- package/dist/date/getDurationBetweenTimes.d.ts +11 -0
- package/dist/date/getDurationBetweenTimes.d.ts.map +1 -0
- package/dist/date/getDurationBetweenTimes.js +21 -0
- package/dist/date/getDurationBetweenTimes.test.d.ts +2 -0
- package/dist/date/getDurationBetweenTimes.test.d.ts.map +1 -0
- package/dist/date/getDurationBetweenTimes.test.js +24 -0
- package/dist/date/index.d.ts +8 -0
- package/dist/date/index.d.ts.map +1 -0
- package/dist/date/index.js +7 -0
- package/dist/date/isAfterDate.d.ts +5 -0
- package/dist/date/isAfterDate.d.ts.map +1 -0
- package/dist/date/isAfterDate.js +7 -0
- package/dist/date/isAfterDate.test.d.ts +2 -0
- package/dist/date/isAfterDate.test.d.ts.map +1 -0
- package/dist/date/isAfterDate.test.js +9 -0
- package/dist/date/isBeforeDate.d.ts +5 -0
- package/dist/date/isBeforeDate.d.ts.map +1 -0
- package/dist/date/isBeforeDate.js +7 -0
- package/dist/date/isBeforeDate.test.d.ts +2 -0
- package/dist/date/isBeforeDate.test.d.ts.map +1 -0
- package/dist/date/isBeforeDate.test.js +20 -0
- package/dist/date/isValidDate.d.ts +5 -0
- package/dist/date/isValidDate.d.ts.map +1 -0
- package/dist/date/isValidDate.js +35 -0
- package/dist/date/isValidDate.test.d.ts +2 -0
- package/dist/date/isValidDate.test.d.ts.map +1 -0
- package/dist/date/isValidDate.test.js +22 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +1 -0
- package/package.json +31 -0
package/README.md
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Additionne deux durées au format time
|
|
3
|
+
* @param a Format time (ex : "01:30")
|
|
4
|
+
* @param b Format time (ex : "02:45")
|
|
5
|
+
* @returns Format time (ex : "04:15")
|
|
6
|
+
*/
|
|
7
|
+
export declare const addTimes: (a?: string | null, b?: string | null, options?: {
|
|
8
|
+
defaultValue?: string;
|
|
9
|
+
}) => string;
|
|
10
|
+
//# sourceMappingURL=addTimes.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"addTimes.d.ts","sourceRoot":"","sources":["../../src/date/addTimes.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,eAAO,MAAM,QAAQ,GAAI,IAAI,MAAM,GAAG,IAAI,EAAE,IAAI,MAAM,GAAG,IAAI,EAAE,UAAU;IAAE,YAAY,CAAC,EAAE,MAAM,CAAA;CAAE,KAAG,MAqBpG,CAAC"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Additionne deux durées au format time
|
|
3
|
+
* @param a Format time (ex : "01:30")
|
|
4
|
+
* @param b Format time (ex : "02:45")
|
|
5
|
+
* @returns Format time (ex : "04:15")
|
|
6
|
+
*/
|
|
7
|
+
export const addTimes = (a, b, options) => {
|
|
8
|
+
const { defaultValue } = options || {};
|
|
9
|
+
if (a == null && b != null)
|
|
10
|
+
return b;
|
|
11
|
+
if (b == null && a != null)
|
|
12
|
+
return a;
|
|
13
|
+
if (a == null || b == null)
|
|
14
|
+
return defaultValue ?? '00:00';
|
|
15
|
+
const toMinutes = (timeStr) => {
|
|
16
|
+
const [h, m] = timeStr.split(':').map(Number);
|
|
17
|
+
return h * 60 + m;
|
|
18
|
+
};
|
|
19
|
+
const totalMinutes = toMinutes(a) + toMinutes(b);
|
|
20
|
+
const hours = Math.floor(totalMinutes / 60);
|
|
21
|
+
const minutes = totalMinutes % 60;
|
|
22
|
+
const hoursStr = String(hours).padStart(2, '0');
|
|
23
|
+
const minutesStr = String(minutes).padStart(2, '0');
|
|
24
|
+
return `${hoursStr}:${minutesStr}`;
|
|
25
|
+
};
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
export declare const DateFormats: {
|
|
2
|
+
readonly DatetimeFull: "iiii d MMMM yyyy à HH:mm";
|
|
3
|
+
readonly Datetime: "d MMMM yyyy à HH:mm";
|
|
4
|
+
readonly DatetimeShort: "d MMMM à HH:mm";
|
|
5
|
+
readonly Date: "d MMMM yyyy";
|
|
6
|
+
readonly DaySlashShort: "eeee dd/MM/yy";
|
|
7
|
+
readonly DateSlash: "dd/MM/yyyy";
|
|
8
|
+
readonly DateString: "yyyy-MM-dd";
|
|
9
|
+
readonly DateFull: "iiii d MMMM yyyy";
|
|
10
|
+
readonly DateFullAlt: "iii d MMM yyyy";
|
|
11
|
+
readonly DateTimeString: "yyyy-MM-dd'T'HH:mm";
|
|
12
|
+
readonly Time: "HH:mm";
|
|
13
|
+
readonly MonthString: "yyyy-MM";
|
|
14
|
+
readonly MonthAndYear: "MMMM yy";
|
|
15
|
+
readonly MonthAndYearFull: "MMMM yyyy";
|
|
16
|
+
readonly Month: "MMMM";
|
|
17
|
+
readonly DateTimeFR: "d MMMM yyyy à HH:mm";
|
|
18
|
+
readonly DateTimeEN: "d MMMM yyyy at HH:mm";
|
|
19
|
+
};
|
|
20
|
+
export type DateFormat = (typeof DateFormats)[keyof typeof DateFormats];
|
|
21
|
+
export declare const isDateFormat: (value: unknown) => value is DateFormat;
|
|
22
|
+
//# sourceMappingURL=dateFormat.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dateFormat.d.ts","sourceRoot":"","sources":["../../src/date/dateFormat.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,WAAW;;;;;;;;;;;;;;;;;;CAkBd,CAAC;AAEX,MAAM,MAAM,UAAU,GAAG,CAAC,OAAO,WAAW,CAAC,CAAC,MAAM,OAAO,WAAW,CAAC,CAAC;AAExE,eAAO,MAAM,YAAY,GAAI,OAAO,OAAO,KAAG,KAAK,IAAI,UACa,CAAC"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
export const DateFormats = {
|
|
2
|
+
DatetimeFull: 'iiii d MMMM yyyy à HH:mm',
|
|
3
|
+
Datetime: 'd MMMM yyyy à HH:mm',
|
|
4
|
+
DatetimeShort: 'd MMMM à HH:mm',
|
|
5
|
+
Date: 'd MMMM yyyy',
|
|
6
|
+
DaySlashShort: 'eeee dd/MM/yy',
|
|
7
|
+
DateSlash: 'dd/MM/yyyy',
|
|
8
|
+
DateString: 'yyyy-MM-dd',
|
|
9
|
+
DateFull: 'iiii d MMMM yyyy',
|
|
10
|
+
DateFullAlt: 'iii d MMM yyyy',
|
|
11
|
+
DateTimeString: "yyyy-MM-dd'T'HH:mm",
|
|
12
|
+
Time: 'HH:mm',
|
|
13
|
+
MonthString: 'yyyy-MM',
|
|
14
|
+
MonthAndYear: 'MMMM yy',
|
|
15
|
+
MonthAndYearFull: 'MMMM yyyy',
|
|
16
|
+
Month: 'MMMM',
|
|
17
|
+
DateTimeFR: 'd MMMM yyyy à HH:mm',
|
|
18
|
+
DateTimeEN: 'd MMMM yyyy at HH:mm',
|
|
19
|
+
};
|
|
20
|
+
export const isDateFormat = (value) => value != null && Object.values(DateFormats).includes(value);
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { Locale } from 'date-fns';
|
|
2
|
+
import { type DateFormat } from './dateFormat';
|
|
3
|
+
/**
|
|
4
|
+
* Retourne la locale date-fns à partir du code langue (ex: 'en', 'fr').
|
|
5
|
+
* Défaut: enGB.
|
|
6
|
+
*/
|
|
7
|
+
export declare function getDateFnsLocale(localeCode?: string): Locale;
|
|
8
|
+
/**
|
|
9
|
+
* Affiche une date au format français (ex: 22 juillet 2025).
|
|
10
|
+
*/
|
|
11
|
+
export declare function displayDate(date: string | Date | undefined, options?: {
|
|
12
|
+
fallback?: string;
|
|
13
|
+
format?: DateFormat;
|
|
14
|
+
capitalize?: boolean;
|
|
15
|
+
locale?: Locale;
|
|
16
|
+
}): string;
|
|
17
|
+
/**
|
|
18
|
+
* Affiche une date au format français (ex: 22 juillet 2025).
|
|
19
|
+
*/
|
|
20
|
+
export declare function displayDatetime(date: string | Date, options?: {
|
|
21
|
+
fallback?: string;
|
|
22
|
+
}): string;
|
|
23
|
+
//# sourceMappingURL=displayDate.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"displayDate.d.ts","sourceRoot":"","sources":["../../src/date/displayDate.ts"],"names":[],"mappings":"AAAA,OAAO,EAAmB,MAAM,EAAY,MAAM,UAAU,CAAC;AAE7D,OAAO,EAAe,KAAK,UAAU,EAAE,MAAM,cAAc,CAAC;AAE5D;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,UAAU,CAAC,EAAE,MAAM,GAAG,MAAM,CAG5D;AAED;;GAEG;AACH,wBAAgB,WAAW,CACzB,IAAI,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,EAC/B,OAAO,CAAC,EAAE;IAAE,QAAQ,CAAC,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,UAAU,CAAC;IAAC,UAAU,CAAC,EAAE,OAAO,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAA;CAAE,GAC1F,MAAM,CAaR;AAED;;GAEG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,EAAE,OAAO,CAAC,EAAE;IAAE,QAAQ,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG,MAAM,CAO5F"}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { format, isValid, parseISO } from 'date-fns';
|
|
2
|
+
import { enGB, fr } from 'date-fns/locale';
|
|
3
|
+
import { DateFormats } from './dateFormat';
|
|
4
|
+
/**
|
|
5
|
+
* Retourne la locale date-fns à partir du code langue (ex: 'en', 'fr').
|
|
6
|
+
* Défaut: enGB.
|
|
7
|
+
*/
|
|
8
|
+
export function getDateFnsLocale(localeCode) {
|
|
9
|
+
if (localeCode?.startsWith('fr'))
|
|
10
|
+
return fr;
|
|
11
|
+
return enGB;
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Affiche une date au format français (ex: 22 juillet 2025).
|
|
15
|
+
*/
|
|
16
|
+
export function displayDate(date, options) {
|
|
17
|
+
const defaultFormat = DateFormats.Date;
|
|
18
|
+
const defaultLocale = enGB;
|
|
19
|
+
const locale = options?.locale ?? defaultLocale;
|
|
20
|
+
const d = typeof date === 'string' ? parseISO(date) : date;
|
|
21
|
+
if (!d || !isValid(d))
|
|
22
|
+
return options?.fallback ?? '';
|
|
23
|
+
let response = format(d, options?.format ?? defaultFormat, { locale: locale });
|
|
24
|
+
if (options?.capitalize)
|
|
25
|
+
response = response.charAt(0).toUpperCase() + response.slice(1);
|
|
26
|
+
return response;
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Affiche une date au format français (ex: 22 juillet 2025).
|
|
30
|
+
*/
|
|
31
|
+
export function displayDatetime(date, options) {
|
|
32
|
+
const defaultFormat = DateFormats.Datetime;
|
|
33
|
+
const d = typeof date === 'string' ? parseISO(date) : date;
|
|
34
|
+
if (!isValid(d))
|
|
35
|
+
return options?.fallback ?? '';
|
|
36
|
+
return format(d, defaultFormat, { locale: enGB });
|
|
37
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"displayDate.test.d.ts","sourceRoot":"","sources":["../../src/date/displayDate.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { displayDate, displayDatetime } from './displayDate';
|
|
2
|
+
describe('displayDate', () => {
|
|
3
|
+
it('formate une date string ISO correctement', () => {
|
|
4
|
+
const result = displayDate('2025-07-22');
|
|
5
|
+
expect(result).toBe('22 July 2025');
|
|
6
|
+
});
|
|
7
|
+
it('formate une date Date correctement', () => {
|
|
8
|
+
const result = displayDate(new Date('2025-07-22T00:00:00Z'));
|
|
9
|
+
expect(result).toBe('22 July 2025');
|
|
10
|
+
});
|
|
11
|
+
it('retourne le fallback si la date est invalide', () => {
|
|
12
|
+
const result = displayDate('invalid-date', { fallback: 'Date inconnue' });
|
|
13
|
+
expect(result).toBe('Date inconnue');
|
|
14
|
+
});
|
|
15
|
+
it('utilise le format personnalisé si fourni', () => {
|
|
16
|
+
const result = displayDate('2025-07-22', { format: 'd MMMM yyyy' });
|
|
17
|
+
expect(result).toBe('22 July 2025');
|
|
18
|
+
});
|
|
19
|
+
});
|
|
20
|
+
describe('displayDatetime', () => {
|
|
21
|
+
it('formate une date string ISO avec heure', () => {
|
|
22
|
+
const result = displayDatetime('2025-07-22T15:30:00');
|
|
23
|
+
expect(result).toBe('22 July 2025 à 15:30');
|
|
24
|
+
});
|
|
25
|
+
it('retourne le fallback si la date est invalide', () => {
|
|
26
|
+
const result = displayDatetime('invalid-date', { fallback: 'Date/heure inconnue' });
|
|
27
|
+
expect(result).toBe('Date/heure inconnue');
|
|
28
|
+
});
|
|
29
|
+
it('fonctionne avec un objet Date', () => {
|
|
30
|
+
const date = new Date('2025-07-22T10:45:00');
|
|
31
|
+
const result = displayDatetime(date);
|
|
32
|
+
expect(result).toBe('22 July 2025 à 10:45');
|
|
33
|
+
});
|
|
34
|
+
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"formatDateRangeLabel.d.ts","sourceRoot":"","sources":["../../src/date/formatDateRangeLabel.ts"],"names":[],"mappings":"AAGA,wBAAgB,oBAAoB,CAAC,MAAM,EAAE;IAC3C,SAAS,EAAE,IAAI,CAAC;IAChB,OAAO,EAAE,IAAI,CAAC;IACd,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;CACjB,GAAG,MAAM,CAgCT"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { format, isValid } from 'date-fns';
|
|
2
|
+
import { getDateFnsLocale } from './displayDate';
|
|
3
|
+
export function formatDateRangeLabel(params) {
|
|
4
|
+
const { startDate, endDate, localeCode, fromLabel, toLabel } = params;
|
|
5
|
+
if (!isValid(startDate) || !isValid(endDate))
|
|
6
|
+
return '';
|
|
7
|
+
const sameMonthYear = startDate.getMonth() === endDate.getMonth() && startDate.getFullYear() === endDate.getFullYear();
|
|
8
|
+
const sameYear = startDate.getFullYear() === endDate.getFullYear();
|
|
9
|
+
const dateFnsLocale = getDateFnsLocale(localeCode);
|
|
10
|
+
if (sameMonthYear) {
|
|
11
|
+
return `${fromLabel} ${format(startDate, 'dd', { locale: dateFnsLocale })} ${toLabel} ${format(endDate, 'dd', {
|
|
12
|
+
locale: dateFnsLocale,
|
|
13
|
+
})} ${format(startDate, 'MMMM', { locale: dateFnsLocale })} ${format(startDate, 'yyyy', {
|
|
14
|
+
locale: dateFnsLocale,
|
|
15
|
+
})}`;
|
|
16
|
+
}
|
|
17
|
+
if (sameYear) {
|
|
18
|
+
return `${fromLabel} ${format(startDate, 'dd MMM', { locale: dateFnsLocale })} ${toLabel} ${format(endDate, 'dd MMM', { locale: dateFnsLocale })} ${format(startDate, 'yyyy', { locale: dateFnsLocale })}`;
|
|
19
|
+
}
|
|
20
|
+
return `${fromLabel} ${format(startDate, 'dd MMM yyyy', { locale: dateFnsLocale })} ${toLabel} ${format(endDate, 'dd MMM yyyy', { locale: dateFnsLocale })}`;
|
|
21
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"formatMinutes.d.ts","sourceRoot":"","sources":["../../src/date/formatMinutes.ts"],"names":[],"mappings":"AAAA,wBAAgB,aAAa,CAAC,GAAG,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,MAAM,UAS3D"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export function formatMinutes(min, fallback) {
|
|
2
|
+
const heures = Math.floor(min / 60);
|
|
3
|
+
const minutes = min % 60;
|
|
4
|
+
if (minutes <= 0 && heures <= 0)
|
|
5
|
+
return fallback ?? `Vide`;
|
|
6
|
+
const heuresText = heures > 0 ? `${heures} heure${heures > 1 ? 's' : ''}` : undefined;
|
|
7
|
+
const minutesText = minutes > 0 ? `${minutes} minute${minutes > 1 ? 's' : ''}` : undefined;
|
|
8
|
+
const fullText = `${heuresText ?? ''}${minutesText && heuresText ? ' et ' : ''}${minutesText ?? ''}`;
|
|
9
|
+
return `${fullText}`;
|
|
10
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"formatMs.d.ts","sourceRoot":"","sources":["../../src/date/formatMs.ts"],"names":[],"mappings":"AAAA,wBAAgB,QAAQ,CAAC,EAAE,EAAE,MAAM,UAMlC"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export function formatMs(ms) {
|
|
2
|
+
const totalSeconds = Math.floor(ms / 1000);
|
|
3
|
+
const minutes = Math.floor(totalSeconds / 60);
|
|
4
|
+
const seconds = totalSeconds % 60;
|
|
5
|
+
const centiseconds = Math.floor((ms % 1000) / 10);
|
|
6
|
+
return `${String(minutes).padStart(2, '0')}:${String(seconds).padStart(2, '0')},${String(centiseconds).padStart(2, '0')}`;
|
|
7
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"formatMs.test.d.ts","sourceRoot":"","sources":["../../src/date/formatMs.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { formatMs } from './formatMs';
|
|
2
|
+
describe('formatMs', () => {
|
|
3
|
+
it('formate 0 ms', () => {
|
|
4
|
+
expect(formatMs(0)).toBe('00:00,00');
|
|
5
|
+
});
|
|
6
|
+
it('formate un petit nombre de ms (< 1s)', () => {
|
|
7
|
+
expect(formatMs(90)).toBe('00:00,09');
|
|
8
|
+
expect(formatMs(999)).toBe('00:00,99');
|
|
9
|
+
});
|
|
10
|
+
it('passe correctement la seconde entière', () => {
|
|
11
|
+
expect(formatMs(1000)).toBe('00:01,00');
|
|
12
|
+
expect(formatMs(1599)).toBe('00:01,59');
|
|
13
|
+
});
|
|
14
|
+
it('formate avec padding sur 2 chiffres', () => {
|
|
15
|
+
expect(formatMs(5560)).toBe('00:05,56');
|
|
16
|
+
});
|
|
17
|
+
it('gère les minutes et seconds correctement', () => {
|
|
18
|
+
expect(formatMs(61090)).toBe('01:01,09');
|
|
19
|
+
expect(formatMs(123456)).toBe('02:03,45');
|
|
20
|
+
});
|
|
21
|
+
it('gère des durées plus longues', () => {
|
|
22
|
+
expect(formatMs(10 * 60000 + 1000 + 90)).toBe('10:01,09');
|
|
23
|
+
});
|
|
24
|
+
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"formatSec.d.ts","sourceRoot":"","sources":["../../src/date/formatSec.ts"],"names":[],"mappings":"AAAA,wBAAgB,SAAS,CAAC,GAAG,EAAE,MAAM,UAKpC"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Déduit la durée d'une période en heures au format time
|
|
3
|
+
* @param start Format time (ex : "00:00")
|
|
4
|
+
* @param end Format time (ex : "00:00")
|
|
5
|
+
* @returns Format time (ex : "00:00")
|
|
6
|
+
*/
|
|
7
|
+
export declare const getDurationBetweenTimes: (start?: string | null, end?: string | null, options?: {
|
|
8
|
+
defaultValue?: string;
|
|
9
|
+
allowNull?: boolean;
|
|
10
|
+
}) => string | undefined;
|
|
11
|
+
//# sourceMappingURL=getDurationBetweenTimes.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"getDurationBetweenTimes.d.ts","sourceRoot":"","sources":["../../src/date/getDurationBetweenTimes.ts"],"names":[],"mappings":"AAIA;;;;;GAKG;AACH,eAAO,MAAM,uBAAuB,GAClC,QAAQ,MAAM,GAAG,IAAI,EACrB,MAAM,MAAM,GAAG,IAAI,EACnB,UAAU;IAAE,YAAY,CAAC,EAAE,MAAM,CAAC;IAAC,SAAS,CAAC,EAAE,OAAO,CAAA;CAAE,KACvD,MAAM,GAAG,SAcX,CAAC"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { differenceInMinutes, parse } from 'date-fns';
|
|
2
|
+
const parseTime = (time) => parse(time, 'HH:mm', new Date(0));
|
|
3
|
+
/**
|
|
4
|
+
* Déduit la durée d'une période en heures au format time
|
|
5
|
+
* @param start Format time (ex : "00:00")
|
|
6
|
+
* @param end Format time (ex : "00:00")
|
|
7
|
+
* @returns Format time (ex : "00:00")
|
|
8
|
+
*/
|
|
9
|
+
export const getDurationBetweenTimes = (start, end, options) => {
|
|
10
|
+
const { defaultValue, allowNull } = options || { allowNull: true };
|
|
11
|
+
if (start == null || end == null)
|
|
12
|
+
return allowNull ? (defaultValue ?? '00:00') : undefined;
|
|
13
|
+
const minutes = differenceInMinutes(parseTime(end), parseTime(start));
|
|
14
|
+
if (minutes <= 0)
|
|
15
|
+
return defaultValue ?? '00:00';
|
|
16
|
+
const hours = Math.floor(minutes / 60);
|
|
17
|
+
const remainingMinutes = minutes % 60;
|
|
18
|
+
const hoursStr = String(hours).padStart(2, '0');
|
|
19
|
+
const minutesStr = String(remainingMinutes).padStart(2, '0');
|
|
20
|
+
return `${hoursStr}:${minutesStr}`;
|
|
21
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"getDurationBetweenTimes.test.d.ts","sourceRoot":"","sources":["../../src/date/getDurationBetweenTimes.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { getDurationBetweenTimes } from './getDurationBetweenTimes';
|
|
2
|
+
describe('getDurationBetweenTimes', () => {
|
|
3
|
+
it('retourne la durée entre deux heures', () => {
|
|
4
|
+
expect(getDurationBetweenTimes('07:00', '12:00')).toBe('05:00');
|
|
5
|
+
});
|
|
6
|
+
it('retourne la durée avec des minutes', () => {
|
|
7
|
+
expect(getDurationBetweenTimes('01:00', '02:30')).toBe('01:30');
|
|
8
|
+
});
|
|
9
|
+
it('retourne 00:00 si la durée est nulle', () => {
|
|
10
|
+
expect(getDurationBetweenTimes('08:00', '08:00')).toBe('00:00');
|
|
11
|
+
});
|
|
12
|
+
it('retourne 00:00 si end est avant start', () => {
|
|
13
|
+
expect(getDurationBetweenTimes('10:00', '09:00')).toBe('00:00');
|
|
14
|
+
});
|
|
15
|
+
it('retourne la defaultValue si la durée est nulle', () => {
|
|
16
|
+
expect(getDurationBetweenTimes('08:00', '08:00', { defaultValue: '—' })).toBe('—');
|
|
17
|
+
});
|
|
18
|
+
it('retourne la defaultValue si end est avant start', () => {
|
|
19
|
+
expect(getDurationBetweenTimes('10:00', '09:00', { defaultValue: '—' })).toBe('—');
|
|
20
|
+
});
|
|
21
|
+
it('retourne 00:00 si la durée est négative même sans options', () => {
|
|
22
|
+
expect(getDurationBetweenTimes('23:59', '00:00')).toBe('00:00');
|
|
23
|
+
});
|
|
24
|
+
});
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
export * from './addTimes';
|
|
2
|
+
export * from './dateFormat';
|
|
3
|
+
export * from './displayDate';
|
|
4
|
+
export * from './formatMinutes';
|
|
5
|
+
export * from './getDurationBetweenTimes';
|
|
6
|
+
export * from './isAfterDate';
|
|
7
|
+
export * from './isValidDate';
|
|
8
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/date/index.ts"],"names":[],"mappings":"AAAA,cAAc,YAAY,CAAC;AAC3B,cAAc,cAAc,CAAC;AAC7B,cAAc,eAAe,CAAC;AAC9B,cAAc,iBAAiB,CAAC;AAChC,cAAc,2BAA2B,CAAC;AAC1C,cAAc,eAAe,CAAC;AAC9B,cAAc,eAAe,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"isAfterDate.d.ts","sourceRoot":"","sources":["../../src/date/isAfterDate.ts"],"names":[],"mappings":"AAEA;;GAEG;AACH,wBAAgB,WAAW,CAAC,KAAK,EAAE,MAAM,EAAE,cAAc,EAAE,MAAM,GAAG,OAAO,CAE1E"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"isAfterDate.test.d.ts","sourceRoot":"","sources":["../../src/date/isAfterDate.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { isAfterDate } from './isAfterDate';
|
|
2
|
+
describe('isAfterDate', () => {
|
|
3
|
+
it('retourne true pour une date après une date de référence', () => {
|
|
4
|
+
expect(isAfterDate('2025-07-22', '2025-07-21')).toBe(true);
|
|
5
|
+
});
|
|
6
|
+
it('retourne false pour une date avant une date de référence', () => {
|
|
7
|
+
expect(isAfterDate('2025-07-21', '2025-07-22')).toBe(false);
|
|
8
|
+
});
|
|
9
|
+
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"isBeforeDate.d.ts","sourceRoot":"","sources":["../../src/date/isBeforeDate.ts"],"names":[],"mappings":"AAEA;;GAEG;AACH,wBAAgB,YAAY,CAAC,KAAK,EAAE,MAAM,EAAE,cAAc,EAAE,MAAM,GAAG,OAAO,CAE3E"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"isBeforeDate.test.d.ts","sourceRoot":"","sources":["../../src/date/isBeforeDate.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { isBeforeDate } from './isBeforeDate';
|
|
2
|
+
describe('isBeforeDate', () => {
|
|
3
|
+
it('retourne true si la première date est avant la seconde', () => {
|
|
4
|
+
expect(isBeforeDate('2025-07-21', '2025-07-22')).toBe(true);
|
|
5
|
+
});
|
|
6
|
+
it('retourne false si la première date est égale à la seconde', () => {
|
|
7
|
+
expect(isBeforeDate('2025-07-22', '2025-07-22')).toBe(false);
|
|
8
|
+
});
|
|
9
|
+
it('retourne false si la première date est après la seconde', () => {
|
|
10
|
+
expect(isBeforeDate('2025-07-23', '2025-07-22')).toBe(false);
|
|
11
|
+
});
|
|
12
|
+
it('gère les dates avec heures correctement', () => {
|
|
13
|
+
expect(isBeforeDate('2025-07-22T10:00:00Z', '2025-07-22T12:00:00Z')).toBe(true);
|
|
14
|
+
expect(isBeforeDate('2025-07-22T14:00:00Z', '2025-07-22T12:00:00Z')).toBe(false);
|
|
15
|
+
});
|
|
16
|
+
it('retourne false si une date est invalide', () => {
|
|
17
|
+
expect(isBeforeDate('invalid-date', '2025-07-22')).toBe(false);
|
|
18
|
+
expect(isBeforeDate('2025-07-22', 'invalid-date')).toBe(false);
|
|
19
|
+
});
|
|
20
|
+
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"isValidDate.d.ts","sourceRoot":"","sources":["../../src/date/isValidDate.ts"],"names":[],"mappings":"AAEA;;GAEG;AACH,wBAAgB,WAAW,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,MAAM,GAAG,IAAI,CAoClE"}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { isValid, parseISO } from 'date-fns';
|
|
2
|
+
/**
|
|
3
|
+
* Vérifie si une valeur est une date valide (string ISO ou Date).
|
|
4
|
+
*/
|
|
5
|
+
export function isValidDate(value) {
|
|
6
|
+
if (typeof value === 'string') {
|
|
7
|
+
const trimmedValue = value.trim();
|
|
8
|
+
if (!trimmedValue)
|
|
9
|
+
return false; // Vérifie les chaînes vides
|
|
10
|
+
// Vérification avec regex pour le format ISO 8601
|
|
11
|
+
const isoFormat = /^\d{4}-\d{2}-\d{2}(T\d{2}:\d{2}:\d{2}(?:\.\d{1,3})?([+-]\d{2}:\d{2}|Z)?)?$/; // Format ISO complet
|
|
12
|
+
const partialIsoFormat = /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}$/; // Format ISO partiel
|
|
13
|
+
const standardDateFormat = /^\d{4}-\d{2}-\d{2}$/; // Format YYYY-MM-DD
|
|
14
|
+
// Validation pour un format ISO complet
|
|
15
|
+
if (isoFormat.test(trimmedValue)) {
|
|
16
|
+
const parsedIsoDate = parseISO(trimmedValue);
|
|
17
|
+
return isValid(parsedIsoDate); // Vérifie si la date est valide après parsing
|
|
18
|
+
}
|
|
19
|
+
// Validation pour format ISO partiel
|
|
20
|
+
if (partialIsoFormat.test(trimmedValue)) {
|
|
21
|
+
const parsedPartialDate = new Date(trimmedValue);
|
|
22
|
+
return isValid(parsedPartialDate); // Vérifie si le format partiel est une date valide
|
|
23
|
+
}
|
|
24
|
+
// Validation pour format YYYY-MM-DD
|
|
25
|
+
if (standardDateFormat.test(trimmedValue)) {
|
|
26
|
+
const parsedStandardDate = new Date(trimmedValue);
|
|
27
|
+
return isValid(parsedStandardDate); // Vérifie si le format YYYY-MM-DD est une date valide
|
|
28
|
+
}
|
|
29
|
+
return false; // La chaîne n'est pas un format valide
|
|
30
|
+
}
|
|
31
|
+
if (value instanceof Date) {
|
|
32
|
+
return isValid(value); // Vérifie si l'objet Date est valide
|
|
33
|
+
}
|
|
34
|
+
return false; // Cadre de type non valide
|
|
35
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"isValidDate.test.d.ts","sourceRoot":"","sources":["../../src/date/isValidDate.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { isValidDate } from './isValidDate';
|
|
2
|
+
describe('isValidDate', () => {
|
|
3
|
+
it('retourne true pour une string ISO valide', () => {
|
|
4
|
+
expect(isValidDate('2025-07-22')).toBe(true);
|
|
5
|
+
});
|
|
6
|
+
it('retourne true pour un objet Date valide', () => {
|
|
7
|
+
expect(isValidDate(new Date('2025-07-22T10:00:00Z'))).toBe(true);
|
|
8
|
+
expect(isValidDate('2025-07-22T10:00:00Z')).toBe(true);
|
|
9
|
+
expect(isValidDate('2025-10-16T14:07:54.137+02:00')).toBe(true);
|
|
10
|
+
expect(isValidDate('2025-10-22T12:20')).toBe(true);
|
|
11
|
+
});
|
|
12
|
+
it('retourne false pour un objet Date invalide', () => {
|
|
13
|
+
expect(isValidDate(new Date('invalid-date'))).toBe(false);
|
|
14
|
+
});
|
|
15
|
+
it('retourne false pour une valeur qui n’est ni string ni Date', () => {
|
|
16
|
+
expect(isValidDate(123)).toBe(false);
|
|
17
|
+
expect(isValidDate(null)).toBe(false);
|
|
18
|
+
expect(isValidDate(undefined)).toBe(false);
|
|
19
|
+
expect(isValidDate({})).toBe(false);
|
|
20
|
+
expect(isValidDate('75')).toBe(false);
|
|
21
|
+
});
|
|
22
|
+
});
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,QAAQ,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './date';
|
package/package.json
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@alveole/core",
|
|
3
|
+
"version": "0.34.6",
|
|
4
|
+
"description": "Core for Alveole.",
|
|
5
|
+
"main": "dist/index.js",
|
|
6
|
+
"types": "dist/index.d.ts",
|
|
7
|
+
"exports": {
|
|
8
|
+
".": {
|
|
9
|
+
"types": "./dist/index.d.ts",
|
|
10
|
+
"default": "./dist/index.js"
|
|
11
|
+
},
|
|
12
|
+
"./package.json": "./package.json"
|
|
13
|
+
},
|
|
14
|
+
"files": [
|
|
15
|
+
"dist",
|
|
16
|
+
"README.md"
|
|
17
|
+
],
|
|
18
|
+
"sideEffects": false,
|
|
19
|
+
"scripts": {
|
|
20
|
+
"build": "tsc -p tsconfig.build.json",
|
|
21
|
+
"lint": "eslint .",
|
|
22
|
+
"typecheck": "tsc -p tsconfig.typecheck.json --noEmit"
|
|
23
|
+
},
|
|
24
|
+
"devDependencies": {
|
|
25
|
+
"@alveole/eslint-config": "file:../eslint-config",
|
|
26
|
+
"eslint": "^9.39.2"
|
|
27
|
+
},
|
|
28
|
+
"peerDependencies": {
|
|
29
|
+
"date-fns": "*"
|
|
30
|
+
}
|
|
31
|
+
}
|