Transformations: Convert field type should handle Unix timestamps in seconds (#94442)

* Parse seconds unix formatted timestamps as expected

* clarify comment

---------

Co-authored-by: Ihor Yeromin <yeryomin.igor@gmail.com>
This commit is contained in:
Kristina
2024-10-15 10:49:07 -05:00
committed by GitHub
co-authored by Ihor Yeromin
parent 6e39ea5e46
commit 2a6b73ca5f
2 changed files with 59 additions and 4 deletions
@@ -486,4 +486,52 @@ describe('fieldToTimeField', () => {
],
});
});
it('should properly parse Unix timestamps - in seconds', () => {
const numberTimeField: Field = {
config: {},
name: 'Unix second timestamps',
type: FieldType.number,
values: [1728397800, 1728397815, 1728397830],
};
expect(fieldToTimeField(numberTimeField, 'X')).toEqual({
config: {},
name: 'Unix second timestamps',
type: FieldType.time,
values: [1728397800000, 1728397815000, 1728397830000],
});
});
it('should properly parse Unix timestamps - in millseconds (with format)', () => {
const numberTimeField: Field = {
config: {},
name: 'Unix MS timestamps',
type: FieldType.number,
values: [1728397800000, 1728397815000, 1728397830000],
};
expect(fieldToTimeField(numberTimeField, 'x')).toEqual({
config: {},
name: 'Unix MS timestamps',
type: FieldType.time,
values: [1728397800000, 1728397815000, 1728397830000],
});
});
it('should properly parse Unix timestamps - in millseconds (without format)', () => {
const numberTimeField: Field = {
config: {},
name: 'Unix MS timestamps',
type: FieldType.number,
values: [1728397800000, 1728397815000, 1728397830000],
};
expect(fieldToTimeField(numberTimeField)).toEqual({
config: {},
name: 'Unix MS timestamps',
type: FieldType.time,
values: [1728397800000, 1728397815000, 1728397830000],
});
});
});
@@ -131,13 +131,17 @@ export function fieldToTimeField(field: Field, dateFormat?: string): Field {
const timeValues = field.values.slice();
let firstDefined = timeValues.find((v) => v != null);
let isISO8601 = typeof firstDefined === 'string' && iso8601Regex.test(firstDefined);
const convertToMS = typeof firstDefined === 'number' && dateFormat === 'X';
const isISO8601 = typeof firstDefined === 'string' && iso8601Regex.test(firstDefined);
for (let t = 0; t < timeValues.length; t++) {
if (timeValues[t]) {
let parsed = isISO8601 ? Date.parse(timeValues[t]) : dateTimeParse(timeValues[t], opts).valueOf();
timeValues[t] = Number.isFinite(parsed) ? parsed : null;
if (Number.isFinite(parsed)) {
timeValues[t] = convertToMS ? parsed * 1000 : parsed;
} else {
timeValues[t] = null;
}
} else {
timeValues[t] = null;
}
@@ -254,10 +258,13 @@ function fieldToComplexField(field: Field): Field {
*/
export function ensureTimeField(field: Field, dateFormat?: string): Field {
const firstValueTypeIsNumber = typeof field.values[0] === 'number';
// if the format is unix seconds, we don't want to skip formatting
const isUnixSecondsFormat = dateFormat === 'X';
if (field.type === FieldType.time && firstValueTypeIsNumber) {
return field; //already time
}
if (firstValueTypeIsNumber) {
if (firstValueTypeIsNumber && !isUnixSecondsFormat) {
return {
...field,
type: FieldType.time, //assumes it should be time