diff --git a/packages/grafana-ui/src/components/DateTimePickers/TimeRangePicker.test.tsx b/packages/grafana-ui/src/components/DateTimePickers/TimeRangePicker.test.tsx index 0b2284e875f..37180a2b413 100644 --- a/packages/grafana-ui/src/components/DateTimePickers/TimeRangePicker.test.tsx +++ b/packages/grafana-ui/src/components/DateTimePickers/TimeRangePicker.test.tsx @@ -5,7 +5,7 @@ import { dateTime, makeTimeRange, TimeRange } from '@grafana/data'; import { selectors as e2eSelectors } from '@grafana/e2e-selectors'; import { TimeRangeProvider } from './TimeRangeContext'; -import { TimeRangePicker } from './TimeRangePicker'; +import { TimePickerTooltip, TimeRangePicker } from './TimeRangePicker'; const selectors = e2eSelectors.components.TimePicker; @@ -113,3 +113,56 @@ it('does not submit wrapping forms', async () => { expect(onSubmit).not.toHaveBeenCalled(); }); + +describe('TimePickerTooltip', () => { + beforeAll(() => { + const mockIntl = { + resolvedOptions: () => ({ + timeZone: 'America/New_York', + }), + }; + + jest.spyOn(Intl, 'DateTimeFormat').mockImplementation(() => mockIntl as Intl.DateTimeFormat); + }); + + afterAll(() => { + jest.restoreAllMocks(); + }); + + const timeRange: TimeRange = { + from: dateTime('2024-01-01T00:00:00Z'), + to: dateTime('2024-01-02T00:00:00Z'), + raw: { + from: dateTime('2024-01-01T00:00:00Z'), + to: dateTime('2024-01-02T00:00:00Z'), + }, + }; + + it('renders time range with UTC timezone', () => { + render(); + + expect(screen.getByText(/2024-01-01 00:00:00/)).toBeInTheDocument(); + expect(screen.getByText('to')).toBeInTheDocument(); + expect(screen.getByText(/2024-01-02 00:00:00/)).toBeInTheDocument(); + expect(screen.getByTestId('time-picker-tooltip-timezone')).toHaveTextContent('UTC, GMT'); + }); + + it('renders time range without timezone if timezone is not passed in', () => { + render(); + + expect(screen.queryByTestId('time-picker-tooltip-timezone')).not.toBeInTheDocument(); + }); + + it('renders time range with browser timezone', () => { + render(); + + expect(screen.getByText('Local browser time')).toBeInTheDocument(); + expect(screen.getByTestId('time-picker-tooltip-timezone')).toHaveTextContent('United States, EDT'); // this was mocked at the beginning, in beforeAll block + }); + + it('renders time range with specific timezone', () => { + render(); + + expect(screen.getByText('Ghana, GMT')).toBeInTheDocument(); + }); +}); diff --git a/packages/grafana-ui/src/components/DateTimePickers/TimeRangePicker.tsx b/packages/grafana-ui/src/components/DateTimePickers/TimeRangePicker.tsx index 0f9e1e5b423..706edff99de 100644 --- a/packages/grafana-ui/src/components/DateTimePickers/TimeRangePicker.tsx +++ b/packages/grafana-ui/src/components/DateTimePickers/TimeRangePicker.tsx @@ -13,6 +13,7 @@ import { TimeRange, TimeZone, dateMath, + getTimeZoneInfo, } from '@grafana/data'; import { selectors } from '@grafana/e2e-selectors'; @@ -25,6 +26,7 @@ import { ToolbarButton } from '../ToolbarButton'; import { Tooltip } from '../Tooltip/Tooltip'; import { TimePickerContent } from './TimeRangePicker/TimePickerContent'; +import { TimeZoneDescription } from './TimeZonePicker/TimeZoneDescription'; import { WeekStart } from './WeekStartPicker'; import { quickOptions } from './options'; import { useTimeSync } from './utils/useTimeSync'; @@ -243,16 +245,23 @@ const ZoomOutTooltip = () => ( export const TimePickerTooltip = ({ timeRange, timeZone }: { timeRange: TimeRange; timeZone?: TimeZone }) => { const styles = useStyles2(getLabelStyles); + const now = Date.now(); + + // Get timezone info only if timeZone is provided + const timeZoneInfo = timeZone ? getTimeZoneInfo(timeZone, now) : undefined; return ( <> - {dateTimeFormat(timeRange.from, { timeZone })}
- to + {dateTimeFormat(timeRange.from, { timeZone })} +
+ to +
+ {dateTimeFormat(timeRange.to, { timeZone })}
- {dateTimeFormat(timeRange.to, { timeZone })} -
+
{timeZoneFormatUserFriendly(timeZone)} +
); @@ -321,6 +330,7 @@ const getLabelStyles = (theme: GrafanaTheme2) => { display: 'flex', alignItems: 'center', whiteSpace: 'nowrap', + columnGap: '4px', }), utc: css({ color: theme.v1.palette.orange, diff --git a/packages/grafana-ui/src/components/DateTimePickers/TimeZonePicker/TimeZoneDescription.tsx b/packages/grafana-ui/src/components/DateTimePickers/TimeZonePicker/TimeZoneDescription.tsx index 12594c31b65..bbb582735f9 100644 --- a/packages/grafana-ui/src/components/DateTimePickers/TimeZonePicker/TimeZoneDescription.tsx +++ b/packages/grafana-ui/src/components/DateTimePickers/TimeZonePicker/TimeZoneDescription.tsx @@ -7,9 +7,10 @@ import { useStyles2 } from '../../../themes'; interface Props { info?: TimeZoneInfo; + testId?: string; } -export const TimeZoneDescription = ({ info }: Props) => { +export const TimeZoneDescription = ({ info, testId }: Props) => { const styles = useStyles2(getStyles); const description = useDescription(info); @@ -17,7 +18,11 @@ export const TimeZoneDescription = ({ info }: Props) => { return null; } - return
{description}
; + return ( +
+ {description} +
+ ); }; const useDescription = (info?: TimeZoneInfo): string => {