mirror of
https://github.com/LaCasemate/fab-manager.git
synced 2025-02-20 14:54:15 +01:00
(bug) invalid event date in negative TZ
This commit is contained in:
parent
f2a21e444f
commit
921b5eab2f
@ -3,6 +3,7 @@
|
||||
- Add more context data to sentry reports
|
||||
- Improved SSO testing
|
||||
- Fix a bug: unable to run task fix_invoice_item when some invoice items are associated with errors
|
||||
- Fix a bug: invalid event date reported when the timezone in before UTC
|
||||
- [TODO DEPLOY] `rails fablab:fix:invoice_items_in_error` THEN `rails fablab:fix_invoice_items` THEN `rails db:migrate`
|
||||
|
||||
## v5.6.5 2023 January 9
|
||||
|
@ -1,6 +1,6 @@
|
||||
import moment, { unitOfTime } from 'moment';
|
||||
import { IFablab } from '../models/fablab';
|
||||
import { TDateISO, TDateISODate, THours, TMinutes } from '../typings/date-iso';
|
||||
import { TDateISO, TDateISODate, TDateISOShortTime } from '../typings/date-iso';
|
||||
|
||||
declare let Fablab: IFablab;
|
||||
|
||||
@ -17,7 +17,15 @@ export default class FormatLib {
|
||||
*/
|
||||
static isDateISO = (value: string): boolean => {
|
||||
if (typeof value !== 'string') return false;
|
||||
return !!value?.match(/^\d\d\d\d-\d\d-\d\dT\d\d:\d\d:\d\d.\d\d\d/);
|
||||
return !!value?.match(/^\d\d\d\d-\d\d-\d\dT\d\d:\d\d:\d\d/);
|
||||
};
|
||||
|
||||
/**
|
||||
* Check if the provided variable is string representing a short date, according to ISO 8601 (e.g. 2023-01-12)
|
||||
*/
|
||||
static isShortDateISO = (value: string): boolean => {
|
||||
if (typeof value !== 'string') return false;
|
||||
return !!value.match(/^\d\d\d\d-\d\d-\d\d$/);
|
||||
};
|
||||
|
||||
/**
|
||||
@ -32,7 +40,36 @@ export default class FormatLib {
|
||||
* Return the formatted localized date for the given date
|
||||
*/
|
||||
static date = (date: Date|TDateISO|TDateISODate): string => {
|
||||
return Intl.DateTimeFormat().format(moment(date).toDate());
|
||||
let tempDate: Date;
|
||||
if (FormatLib.isShortDateISO(date as string) || FormatLib.isDateISO(date as string)) {
|
||||
tempDate = FormatLib.parseISOdate(date as TDateISO);
|
||||
} else {
|
||||
tempDate = moment(date).toDate();
|
||||
}
|
||||
return Intl.DateTimeFormat(Fablab.intl_locale).format(tempDate);
|
||||
};
|
||||
|
||||
/**
|
||||
* Parse the provided datetime or date string (as ISO8601 format) and return the equivalent Date object
|
||||
*/
|
||||
private static parseISOdate = (date: TDateISO|TDateISODate, res: Date = new Date()): Date => {
|
||||
const isoDateMatch = (date as string)?.match(/^(\d\d\d\d)-(\d\d)-(\d\d)/);
|
||||
res.setFullYear(parseInt(isoDateMatch[1], 10));
|
||||
res.setMonth(parseInt(isoDateMatch[2], 10) - 1);
|
||||
res.setDate(parseInt(isoDateMatch[3], 10));
|
||||
|
||||
return res;
|
||||
};
|
||||
|
||||
/**
|
||||
* Parse the provided datetime or time string (as ISO8601 format) and return the equivalent Date object
|
||||
*/
|
||||
private static parseISOtime = (date: TDateISO|TDateISOShortTime, res: Date = new Date()): Date => {
|
||||
const isoTimeMatch = (date as string)?.match(/(^|T)(\d\d):(\d\d)/);
|
||||
res.setHours(parseInt(isoTimeMatch[2], 10));
|
||||
res.setMinutes(parseInt(isoTimeMatch[3], 10));
|
||||
|
||||
return res;
|
||||
};
|
||||
|
||||
/**
|
||||
@ -45,13 +82,10 @@ export default class FormatLib {
|
||||
/**
|
||||
* Return the formatted localized time for the given date
|
||||
*/
|
||||
static time = (date: Date|TDateISO|`${THours}:${TMinutes}`): string => {
|
||||
static time = (date: Date|TDateISO|TDateISOShortTime): string => {
|
||||
let tempDate: Date;
|
||||
if (FormatLib.isShortTimeISO(date as string)) {
|
||||
const isoTimeMatch = (date as string)?.match(/^(\d\d):(\d\d)$/);
|
||||
tempDate = new Date();
|
||||
tempDate.setHours(parseInt(isoTimeMatch[1], 10));
|
||||
tempDate.setMinutes(parseInt(isoTimeMatch[2], 10));
|
||||
if (FormatLib.isShortTimeISO(date as string) || FormatLib.isDateISO(date as string)) {
|
||||
tempDate = FormatLib.parseISOtime(date as TDateISOShortTime);
|
||||
} else {
|
||||
tempDate = moment(date).toDate();
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
// from https://gist.github.com/MrChocolatine/367fb2a35d02f6175cc8ccb3d3a20054
|
||||
// inspired from https://gist.github.com/MrChocolatine/367fb2a35d02f6175cc8ccb3d3a20054
|
||||
|
||||
type TYear = `${number}${number}${number}${number}`;
|
||||
type TMonth = `${number}${number}`;
|
||||
@ -13,10 +13,15 @@ type TMilliseconds = `${number}${number}${number}`;
|
||||
*/
|
||||
type TDateISODate = `${TYear}-${TMonth}-${TDay}`;
|
||||
|
||||
/**
|
||||
* Represent a string like `14:42`
|
||||
*/
|
||||
type TDateISOShortTime = `${THours}:${TMinutes}`;
|
||||
|
||||
/**
|
||||
* Represent a string like `14:42:34.678`
|
||||
*/
|
||||
type TDateISOTime = `${THours}:${TMinutes}:${TSeconds}`|`${THours}:${TMinutes}:${TSeconds}.${TMilliseconds}`;
|
||||
type TDateISOTime = `${TDateISOShortTime}:${TSeconds}`|`${TDateISOShortTime}:${TSeconds}.${TMilliseconds}`;
|
||||
|
||||
/**
|
||||
* Represent a timezone like `+0100`
|
||||
|
36
test/frontend/lib/format.test.ts
Normal file
36
test/frontend/lib/format.test.ts
Normal file
@ -0,0 +1,36 @@
|
||||
import FormatLib from 'lib/format';
|
||||
import { IFablab } from 'models/fablab';
|
||||
|
||||
declare const Fablab: IFablab;
|
||||
describe('FormatLib', () => {
|
||||
test('format a date', () => {
|
||||
Fablab.intl_locale = 'fr-FR';
|
||||
const str = FormatLib.date(new Date('2023-01-12T12:00:00+0100'));
|
||||
expect(str).toBe('12/01/2023');
|
||||
});
|
||||
test('format an iso8601 short date', () => {
|
||||
Fablab.intl_locale = 'fr-FR';
|
||||
const str = FormatLib.date('2023-01-12');
|
||||
expect(str).toBe('12/01/2023');
|
||||
});
|
||||
test('format an iso8601 date', () => {
|
||||
Fablab.intl_locale = 'fr-CA';
|
||||
const str = FormatLib.date('2023-01-12T23:59:14-0500');
|
||||
expect(str).toBe('2023-01-12');
|
||||
});
|
||||
test('format a time', () => {
|
||||
Fablab.intl_locale = 'fr-FR';
|
||||
const str = FormatLib.time(new Date('2023-01-12T23:59:14+0100'));
|
||||
expect(str).toBe('23:59');
|
||||
});
|
||||
test('format an iso8601 short time', () => {
|
||||
Fablab.intl_locale = 'fr-FR';
|
||||
const str = FormatLib.time('23:59');
|
||||
expect(str).toBe('23:59');
|
||||
});
|
||||
test('format an iso8601 time', () => {
|
||||
Fablab.intl_locale = 'fr-CA';
|
||||
const str = FormatLib.time('2023-01-12T23:59:14-0500');
|
||||
expect(str).toBe('23 h 59');
|
||||
});
|
||||
});
|
@ -2,7 +2,7 @@
|
||||
"references": [
|
||||
{ "path": "../../" }
|
||||
],
|
||||
"include": ["components/**/*", "__fixtures__/**/*", "__lib__/**/*"],
|
||||
"include": ["components/**/*", "lib/**/*", "__fixtures__/**/*", "__lib__/**/*"],
|
||||
"compilerOptions": {
|
||||
"jsx": "react-jsx",
|
||||
"target": "ES2015",
|
||||
|
Loading…
x
Reference in New Issue
Block a user