diff --git a/packages/grafana-data/src/transformations/transformers/formatTime.test.ts b/packages/grafana-data/src/transformations/transformers/formatTime.test.ts index bf3700418a39..fe5096226a37 100644 --- a/packages/grafana-data/src/transformations/transformers/formatTime.test.ts +++ b/packages/grafana-data/src/transformations/transformers/formatTime.test.ts @@ -2,7 +2,7 @@ import { toDataFrame } from '../../dataframe/processDataFrame'; import { FieldType } from '../../types/dataFrame'; import { mockTransformationsRegistry } from '../../utils/tests/mockTransformationsRegistry'; -import { createTimeFormatter, formatTimeTransformer } from './formatTime'; +import { applyFormatTime, formatTimeTransformer } from './formatTime'; describe('Format Time Transformer', () => { beforeAll(() => { @@ -16,7 +16,6 @@ describe('Format Time Transformer', () => { timezone: 'utc', }; - const formatter = createTimeFormatter(options.timeField, options.outputFormat, options.timezone); const frame = toDataFrame({ fields: [ { @@ -27,8 +26,32 @@ describe('Format Time Transformer', () => { ], }); - const newFrame = formatter(frame.fields); - expect(newFrame[0].values).toEqual(['2021-02', '2023-07', '2023-04', '2023-07', '2023-08']); + const newFrames = applyFormatTime(options, [frame]); + expect(newFrames[0].fields[0].values).toEqual(['2021-02', '2023-07', '2023-04', '2023-07', '2023-08']); + }); + + it('will match on getFieldDisplayName', () => { + const options = { + timeField: 'Created', + outputFormat: 'YYYY-MM', + timezone: 'utc', + }; + + const frame = toDataFrame({ + fields: [ + { + name: 'created', + type: FieldType.time, + values: [1612939600000, 1689192000000, 1682025600000, 1690328089000, 1691011200000], + config: { + displayName: 'Created', + }, + }, + ], + }); + + const newFrames = applyFormatTime(options, [frame]); + expect(newFrames[0].fields[0].values).toEqual(['2021-02', '2023-07', '2023-04', '2023-07', '2023-08']); }); it('will handle formats with times', () => { @@ -38,7 +61,6 @@ describe('Format Time Transformer', () => { timezone: 'utc', }; - const formatter = createTimeFormatter(options.timeField, options.outputFormat, options.timezone); const frame = toDataFrame({ fields: [ { @@ -49,8 +71,8 @@ describe('Format Time Transformer', () => { ], }); - const newFrame = formatter(frame.fields); - expect(newFrame[0].values).toEqual([ + const newFrames = applyFormatTime(options, [frame]); + expect(newFrames[0].fields[0].values).toEqual([ '2021-02 6:46:40 am', '2023-07 8:00:00 pm', '2023-04 9:20:00 pm', @@ -66,7 +88,6 @@ describe('Format Time Transformer', () => { timezone: 'utc', }; - const formatter = createTimeFormatter(options.timeField, options.outputFormat, options.timezone); const frame = toDataFrame({ fields: [ { @@ -77,8 +98,8 @@ describe('Format Time Transformer', () => { ], }); - const newFrame = formatter(frame.fields); - expect(newFrame[0].values).toEqual([ + const newFrames = applyFormatTime(options, [frame]); + expect(newFrames[0].fields[0].values).toEqual([ '2021-02 6:46:40 am', '2023-07 8:00:00 pm', '2023-04 9:20:00 pm', diff --git a/packages/grafana-data/src/transformations/transformers/formatTime.ts b/packages/grafana-data/src/transformations/transformers/formatTime.ts index bd5a496562b3..62314055dc3a 100644 --- a/packages/grafana-data/src/transformations/transformers/formatTime.ts +++ b/packages/grafana-data/src/transformations/transformers/formatTime.ts @@ -2,8 +2,9 @@ import { map } from 'rxjs/operators'; import { TimeZone } from '@grafana/schema'; -import { DataFrame, Field, TransformationApplicabilityLevels } from '../../types'; -import { DataTransformerInfo } from '../../types/transformations'; +import { cacheFieldDisplayNames } from '../../field'; +import { DataFrame, TransformationApplicabilityLevels } from '../../types'; +import { DataTransformContext, DataTransformerInfo } from '../../types/transformations'; import { fieldToStringField } from './convertFieldType'; import { DataTransformerID } from './ids'; @@ -34,21 +35,10 @@ export const formatTimeTransformer: DataTransformerInfo (source) => + operator: (options, ctx) => (source) => source.pipe( map((data) => { - // If a field and a format are configured - // then format the time output - const formatter = createTimeFormatter(options.timeField, options.outputFormat, options.timezone); - - if (!Array.isArray(data) || data.length === 0) { - return data; - } - - return data.map((frame) => ({ - ...frame, - fields: formatter(frame.fields), - })); + return applyFormatTime(options, data, ctx); }) ), }; @@ -56,21 +46,27 @@ export const formatTimeTransformer: DataTransformerInfo (fields: Field[]) => { - return fields.map((field) => { - // Find the configured field - if (field.name === timeField) { - // Update values to use the configured format - let formattedField = null; - if (timezone) { - formattedField = fieldToStringField(field, outputFormat, { timeZone: timezone }); - } else { - formattedField = fieldToStringField(field, outputFormat); - } +export const applyFormatTime = ( + { timeField, outputFormat, timezone }: FormatTimeTransformerOptions, + data: DataFrame[], + ctx?: DataTransformContext +) => { + if (!Array.isArray(data) || data.length === 0) { + return data; + } - return formattedField; - } + cacheFieldDisplayNames(data); + + outputFormat = ctx?.interpolate(outputFormat) ?? outputFormat; + + return data.map((frame) => ({ + ...frame, + fields: frame.fields.map((field) => { + if (field.state?.displayName === timeField) { + field = fieldToStringField(field, outputFormat, { timeZone: timezone }); + } - return field; - }); + return field; + }), + })); };