diff --git a/packages/grafana-ui/src/components/DateTimePickers/TimeRangePicker.test.tsx b/packages/grafana-ui/src/components/DateTimePickers/TimeRangePicker.test.tsx index 386c79ec53a..e99ada9c5d1 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; @@ -151,3 +151,55 @@ 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.getByText('UTC, GMT')).toBeInTheDocument(); + }); + + it('renders time range without timezone if timezone is not passed in', () => { + render(); + expect(screen.queryByText('United States, EDT')).not.toBeInTheDocument(); + }); + + it('renders time range with browser timezone', () => { + render(); + + expect(screen.getByText('Local browser time')).toBeInTheDocument(); + expect(screen.getByText('United States, EDT')).toBeInTheDocument(); // 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 4a6bfb7bc14..f4d4ff8bab1 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'; @@ -238,16 +240,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)} +
); @@ -316,6 +325,7 @@ const getLabelStyles = (theme: GrafanaTheme2) => { display: 'flex', alignItems: 'center', whiteSpace: 'nowrap', + columnGap: theme.spacing(0.5), }), utc: css({ color: theme.v1.palette.orange,