TimeSeries: fix & optimize time string parsing (#64640)

This commit is contained in:
Leon Sorokin
2023-03-13 09:59:40 -05:00
committed by GitHub
parent 8bb10f87e9
commit 855de98133
4 changed files with 53 additions and 4 deletions

View File

@@ -18,6 +18,9 @@ export const fieldIndexComparer = (field: Field, reverse = false): IndexComparer
case FieldType.boolean:
return booleanIndexComparer(values, reverse);
case FieldType.time:
if (typeof field.values.get(0) === 'number') {
return timestampIndexComparer(values, reverse);
}
return timeIndexComparer(values, reverse);
default:
return naturalIndexComparer(reverse);
@@ -76,6 +79,12 @@ const falsyComparer = (a: unknown, b: unknown): number => {
return 0;
};
const timestampIndexComparer = (values: Vector<number>, reverse: boolean): IndexComparer => {
let vals = values.toArray();
let mult = reverse ? -1 : 1;
return (a: number, b: number): number => mult * (vals[a] - vals[b]);
};
const timeIndexComparer = (values: Vector<unknown>, reverse: boolean): IndexComparer => {
return (a: number, b: number): number => {
const vA = values.get(a);

View File

@@ -391,12 +391,12 @@ describe('fieldToTimeField', () => {
// this needs to run in a non-UTC timezone env to ensure the parsing is not dependent on env tz settings
//process.env.TZ = 'Pacific/Easter';
it('should always parse ISO 8601 date strings in UTC timezone (e.g. 2011-10-05T14:48:00.000Z)', () => {
it('should properly parse ISO 8601 date strings in UTC offset timezone', () => {
const stringTimeField: Field = {
config: {},
name: 'ISO 8601 date strings',
type: FieldType.time,
values: new ArrayVector(['2021-11-11T19:45:00.000Z']),
values: new ArrayVector(['2021-11-11T19:45:00Z']),
};
expect(fieldToTimeField(stringTimeField)).toEqual({
@@ -406,4 +406,32 @@ describe('fieldToTimeField', () => {
values: new ArrayVector([1636659900000]),
});
});
it('should properly parse additional ISO 8601 date strings with tz offsets and millis', () => {
const stringTimeField: Field = {
config: {},
name: 'ISO 8601 date strings',
type: FieldType.time,
values: new ArrayVector([
'2021-11-11T19:45:00+05:30',
'2021-11-11T19:45:00-05:30',
'2021-11-11T19:45:00+0530',
'2021-11-11T19:45:00-0530',
'2021-11-11T19:45:00.0000000000+05:30',
'2021-11-11T19:45:00.0000000000-0530',
'2021-11-11T19:45:00.000Z',
'2021-11-11T19:45:00.0000000000Z',
]),
};
expect(fieldToTimeField(stringTimeField)).toEqual({
config: {},
name: 'ISO 8601 date strings',
type: FieldType.time,
values: new ArrayVector([
1636640100000, 1636679700000, 1636640100000, 1636679700000, 1636640100000, 1636679700000, 1636659900000,
1636659900000,
]),
});
});
});

View File

@@ -109,8 +109,8 @@ export function convertFieldType(field: Field, opts: ConvertFieldTypeOptions): F
}
}
// matches ISO 8601, e.g. 2021-11-11T19:45:00.000Z (float portion optional)
const iso8601Regex = /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(?:\.\d{3})?Z$/;
// matches common ISO 8601 (see tests)
const iso8601Regex = /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(?:\.\d{3,})?(?:Z|[-+]\d{2}:?\d{2})$/;
/**
* @internal