From 443c847a9bb4dd03768732a2578135adc4d691ba Mon Sep 17 00:00:00 2001 From: "chandrashekhara.n" Date: Tue, 21 May 2024 15:00:47 +0530 Subject: [PATCH] feat: updated the date time to support timezone #2663 --- package-lock.json | 15 +++++++ .../tests/trendCursors/trendCursors.spec.ts | 13 +++++- .../assetTableColumnDefinitionsFactory.tsx | 6 +-- ...ateModeledDataStreamColumnDefinitions.tsx} | 14 ++++-- .../unmodeledDataStreamTable.tsx | 17 ++++--- packages/react-components/package.json | 1 + .../chart/chartOptions/tooltip/time.tsx | 4 +- .../table/columnDefinitions/factory.tsx | 2 +- .../trendCursor/trendCursorHeader.tsx | 11 +++-- .../chart/legend/table/table.spec.tsx | 7 ++- .../src/components/kpi/kpi.spec.tsx | 4 +- .../src/components/kpi/kpiBase.spec.tsx | 4 +- .../src/components/kpi/kpiBase.tsx | 3 +- .../src/components/timeZone/index.ts | 1 + .../src/components/timeZone/timeZone.tsx | 44 +++++++++++++++++++ .../src/components/timestampBar/index.tsx | 11 +++-- .../trendCursors/view/utils/dateTime.ts | 10 +++++ .../trendCursors/view/utils/index.ts | 1 + .../extensions/trendCursors/view/view.ts | 12 +++-- packages/react-components/src/index.ts | 1 + .../useSiteWiseAnomalyDataSource/constants.ts | 2 +- packages/react-components/src/utils/time.ts | 1 + 22 files changed, 149 insertions(+), 35 deletions(-) rename packages/dashboard/src/components/queryEditor/iotSiteWiseQueryEditor/modeledDataStreamQueryEditor/modeledDataStreamExplorer/modeledDataStreamTable/{createModeledDataStreamColumnDefinitions.ts => createModeledDataStreamColumnDefinitions.tsx} (83%) create mode 100644 packages/react-components/src/components/timeZone/index.ts create mode 100644 packages/react-components/src/components/timeZone/timeZone.tsx create mode 100644 packages/react-components/src/echarts/extensions/trendCursors/view/utils/dateTime.ts diff --git a/package-lock.json b/package-lock.json index 67514741b..9e94e0ca2 100644 --- a/package-lock.json +++ b/package-lock.json @@ -40372,6 +40372,14 @@ "url": "https://opencollective.com/date-fns" } }, + "node_modules/date-fns-tz": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/date-fns-tz/-/date-fns-tz-2.0.1.tgz", + "integrity": "sha512-fJCG3Pwx8HUoLhkepdsP7Z5RsucUi+ZBOxyM5d0ZZ6c4SdYustq0VMmOu6Wf7bli+yS/Jwp91TOCqn9jMcVrUA==", + "peerDependencies": { + "date-fns": "2.x" + } + }, "node_modules/debounce": { "version": "1.2.1", "integrity": "sha512-XRRe6Glud4rd/ZGQfiV1ruXSfbvfJedlV9Y6zOlP+2K04vBYiJEte6stfFkCP03aMnY5tsipamumUjL14fofug==", @@ -73072,6 +73080,7 @@ "d3-format": "^3.1.0", "d3-shape": "^3.2.0", "date-fns": "^3.4.0", + "date-fns-tz": "^2.0.1", "dompurify": "3.0.5", "echarts": "^5.4.3", "is-hotkey": "^0.2.0", @@ -89986,6 +89995,7 @@ "d3-format": "^3.1.0", "d3-shape": "^3.2.0", "date-fns": "^3.4.0", + "date-fns-tz": "^2.0.1", "dompurify": "3.0.5", "echarts": "^5.4.3", "eslint-config-iot-app-kit": "10.5.0", @@ -113204,6 +113214,11 @@ "version": "2.29.2", "integrity": "sha512-0VNbwmWJDS/G3ySwFSJA3ayhbURMTJLtwM2DTxf9CWondCnh6DTNlO9JgRSq6ibf4eD0lfMJNBxUdEAHHix+bA==" }, + "date-fns-tz": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/date-fns-tz/-/date-fns-tz-2.0.1.tgz", + "integrity": "sha512-fJCG3Pwx8HUoLhkepdsP7Z5RsucUi+ZBOxyM5d0ZZ6c4SdYustq0VMmOu6Wf7bli+yS/Jwp91TOCqn9jMcVrUA==" + }, "debounce": { "version": "1.2.1", "integrity": "sha512-XRRe6Glud4rd/ZGQfiV1ruXSfbvfJedlV9Y6zOlP+2K04vBYiJEte6stfFkCP03aMnY5tsipamumUjL14fofug==" diff --git a/packages/dashboard/e2e/tests/trendCursors/trendCursors.spec.ts b/packages/dashboard/e2e/tests/trendCursors/trendCursors.spec.ts index 3cb8b2cd5..c6f26773e 100644 --- a/packages/dashboard/e2e/tests/trendCursors/trendCursors.spec.ts +++ b/packages/dashboard/e2e/tests/trendCursors/trendCursors.spec.ts @@ -1,4 +1,5 @@ import { test, expect, Page, Locator } from '@playwright/test'; +import { parse } from 'date-fns'; import { ADD_TREND_CURSOR, ASSET_MODEL_TAB, @@ -185,8 +186,16 @@ test('can drag a trend cursor', async ({ page }) => { expect(initialTrendCursorDateString).not.toEqual( updatedTrendCursorDateString ); - const initialDate = new Date(initialTrendCursorDateString); - const updatedDate = new Date(updatedTrendCursorDateString); + const initialDate = parse( + `${initialTrendCursorDateString.split('\n').join(' ')}`, + 'dd/MM/yyyy HH:mm:ss', + new Date() + ); + const updatedDate = parse( + `${updatedTrendCursorDateString.split('\n').join(' ')}`, + 'dd/MM/yyyy HH:mm:ss', + new Date() + ); expect(initialDate.getTime()).toBeGreaterThan(updatedDate.getTime()); // trend cursor should have some value diff --git a/packages/dashboard/src/components/queryEditor/iotSiteWiseQueryEditor/modeledDataStreamQueryEditor/assetExplorer/assetTable/assetTableColumnDefinitionsFactory.tsx b/packages/dashboard/src/components/queryEditor/iotSiteWiseQueryEditor/modeledDataStreamQueryEditor/assetExplorer/assetTable/assetTableColumnDefinitionsFactory.tsx index bf8de815d..0bcc182d9 100644 --- a/packages/dashboard/src/components/queryEditor/iotSiteWiseQueryEditor/modeledDataStreamQueryEditor/assetExplorer/assetTable/assetTableColumnDefinitionsFactory.tsx +++ b/packages/dashboard/src/components/queryEditor/iotSiteWiseQueryEditor/modeledDataStreamQueryEditor/assetExplorer/assetTable/assetTableColumnDefinitionsFactory.tsx @@ -2,8 +2,8 @@ import { AssetSummary } from '@aws-sdk/client-iotsitewise'; import { type TableProps } from '@cloudscape-design/components/table'; import React from 'react'; +import { DateTime } from '@iot-app-kit/react-components'; import type { AssetTableNameLinkProps } from './assetTableNameLink'; -import { getFormattedDateTime } from '~/components/util/dateTimeUtil'; type AssetTableColumnDefinitions = TableProps['columnDefinitions']; @@ -87,7 +87,7 @@ export class AssetTableColumnDefinitionsFactory { id: 'creationDate', header: 'Creation Date', cell: ({ creationDate }) => - creationDate ? getFormattedDateTime(creationDate) : '-', + creationDate ? : '-', sortingField: 'creationDate', }; } @@ -97,7 +97,7 @@ export class AssetTableColumnDefinitionsFactory { id: 'lastUpdateDate', header: 'Last Update Date', cell: ({ lastUpdateDate }) => - lastUpdateDate ? getFormattedDateTime(lastUpdateDate) : '-', + lastUpdateDate ? : '-', sortingField: 'lastUpdateDate', }; } diff --git a/packages/dashboard/src/components/queryEditor/iotSiteWiseQueryEditor/modeledDataStreamQueryEditor/modeledDataStreamExplorer/modeledDataStreamTable/createModeledDataStreamColumnDefinitions.ts b/packages/dashboard/src/components/queryEditor/iotSiteWiseQueryEditor/modeledDataStreamQueryEditor/modeledDataStreamExplorer/modeledDataStreamTable/createModeledDataStreamColumnDefinitions.tsx similarity index 83% rename from packages/dashboard/src/components/queryEditor/iotSiteWiseQueryEditor/modeledDataStreamQueryEditor/modeledDataStreamExplorer/modeledDataStreamTable/createModeledDataStreamColumnDefinitions.ts rename to packages/dashboard/src/components/queryEditor/iotSiteWiseQueryEditor/modeledDataStreamQueryEditor/modeledDataStreamExplorer/modeledDataStreamTable/createModeledDataStreamColumnDefinitions.tsx index 7081413b3..e74f1afa8 100644 --- a/packages/dashboard/src/components/queryEditor/iotSiteWiseQueryEditor/modeledDataStreamQueryEditor/modeledDataStreamExplorer/modeledDataStreamTable/createModeledDataStreamColumnDefinitions.ts +++ b/packages/dashboard/src/components/queryEditor/iotSiteWiseQueryEditor/modeledDataStreamQueryEditor/modeledDataStreamExplorer/modeledDataStreamTable/createModeledDataStreamColumnDefinitions.tsx @@ -1,7 +1,8 @@ +import React from 'react'; import { isNumeric, round } from '@iot-app-kit/core-util'; +import { DateTime } from '@iot-app-kit/react-components'; import { type TableProps } from '@cloudscape-design/components/table'; import type { ModeledDataStream } from '../types'; -import { getFormattedDateTimeFromEpoch } from '~/components/util/dateTimeUtil'; export function createModeledDataStreamColumnDefinitions( significantDigits: number @@ -33,12 +34,17 @@ export function createModeledDataStreamColumnDefinitions( id: 'latestValueTime', header: 'Latest value time', cell: ({ latestValueTime }) => { + if (!latestValueTime) return '-'; if (latestValueTime && isNumeric(latestValueTime)) { - return getFormattedDateTimeFromEpoch( - Number(round(latestValueTime, significantDigits)) + return ( + ); } - return getFormattedDateTimeFromEpoch(latestValueTime); + return ; }, sortingField: 'latestValueTime', }, diff --git a/packages/dashboard/src/components/queryEditor/iotSiteWiseQueryEditor/unmodeledDataStreamExplorer/unmodeledDataStreamTable/unmodeledDataStreamTable.tsx b/packages/dashboard/src/components/queryEditor/iotSiteWiseQueryEditor/unmodeledDataStreamExplorer/unmodeledDataStreamTable/unmodeledDataStreamTable.tsx index 36c21f018..35ca9c735 100644 --- a/packages/dashboard/src/components/queryEditor/iotSiteWiseQueryEditor/unmodeledDataStreamExplorer/unmodeledDataStreamTable/unmodeledDataStreamTable.tsx +++ b/packages/dashboard/src/components/queryEditor/iotSiteWiseQueryEditor/unmodeledDataStreamExplorer/unmodeledDataStreamTable/unmodeledDataStreamTable.tsx @@ -2,6 +2,8 @@ import React from 'react'; import { useSelector } from 'react-redux'; import { type IoTSiteWiseClient } from '@aws-sdk/client-iotsitewise'; import { isNumeric, round } from '@iot-app-kit/core-util'; +import { getPlugin } from '@iot-app-kit/core'; +import { DateTime } from '@iot-app-kit/react-components'; import { useCollection } from '@cloudscape-design/collection-hooks'; import Box from '@cloudscape-design/components/box'; @@ -16,10 +18,8 @@ import { useExplorerPreferences } from '../../useExplorerPreferences'; import { SUPPORTED_PAGE_SIZES } from '../../constants'; import { useLatestValues } from '../../useLatestValues'; import { DashboardState } from '~/store/state'; -import { getFormattedDateTimeFromEpoch } from '~/components/util/dateTimeUtil'; -import { ResourceExplorerFooter } from '../../footer/footer'; -import { getPlugin } from '@iot-app-kit/core'; import { disableAdd } from '~/components/queryEditor/iotSiteWiseQueryEditor/footer/disableAdd'; +import { ResourceExplorerFooter } from '../../footer/footer'; export interface UnmodeledDataStreamTableProps { onClickAdd: (unmodeledDataStreams: UnmodeledDataStream[]) => void; @@ -162,12 +162,17 @@ export function UnmodeledDataStreamTable({ id: 'latestValueTime', header: 'Latest value time', cell: ({ latestValueTime }) => { + if (!latestValueTime) return '-'; if (latestValueTime && isNumeric(latestValueTime)) { - return getFormattedDateTimeFromEpoch( - Number(round(latestValueTime, significantDigits)) + return ( + ); } - return getFormattedDateTimeFromEpoch(latestValueTime); + return ; }, sortingField: 'latestValueTime', }, diff --git a/packages/react-components/package.json b/packages/react-components/package.json index 583d4bf67..e7e2735db 100644 --- a/packages/react-components/package.json +++ b/packages/react-components/package.json @@ -125,6 +125,7 @@ "d3-format": "^3.1.0", "d3-shape": "^3.2.0", "date-fns": "^3.4.0", + "date-fns-tz": "^2.0.1", "dompurify": "3.0.5", "echarts": "^5.4.3", "is-hotkey": "^0.2.0", diff --git a/packages/react-components/src/components/chart/chartOptions/tooltip/time.tsx b/packages/react-components/src/components/chart/chartOptions/tooltip/time.tsx index c84705d26..28dc5385f 100644 --- a/packages/react-components/src/components/chart/chartOptions/tooltip/time.tsx +++ b/packages/react-components/src/components/chart/chartOptions/tooltip/time.tsx @@ -1,13 +1,13 @@ import React from 'react'; -import { format } from 'date-fns'; import { fontWeightHeadingS } from '@cloudscape-design/design-tokens'; import { FULL_DATE } from '../../../../utils/time'; +import { DateTime } from '../../../timeZone'; export type XYPlotTooltipTimeOptions = { time?: number; }; export const XYPlotTooltipTime = ({ time }: XYPlotTooltipTimeOptions) => ( - {time ? format(new Date(time), FULL_DATE) : ''} + {time ? : ''} ); diff --git a/packages/react-components/src/components/chart/legend/table/columnDefinitions/factory.tsx b/packages/react-components/src/components/chart/legend/table/columnDefinitions/factory.tsx index b8b9bee5f..01df66dd3 100644 --- a/packages/react-components/src/components/chart/legend/table/columnDefinitions/factory.tsx +++ b/packages/react-components/src/components/chart/legend/table/columnDefinitions/factory.tsx @@ -89,7 +89,7 @@ const createTrendCursorColumnDefinition = ({ date, }: TrendCursor): LegendTableColumnDefinitions[number] => ({ id: trendCursorId, - header: , + header: , sortingComparator: (a, b) => { const aValue = a.trendCursorValues[trendCursorId] ?? 0; const bValue = b.trendCursorValues[trendCursorId] ?? 0; diff --git a/packages/react-components/src/components/chart/legend/table/columnDefinitions/trendCursor/trendCursorHeader.tsx b/packages/react-components/src/components/chart/legend/table/columnDefinitions/trendCursor/trendCursorHeader.tsx index 35623809e..8074a5156 100644 --- a/packages/react-components/src/components/chart/legend/table/columnDefinitions/trendCursor/trendCursorHeader.tsx +++ b/packages/react-components/src/components/chart/legend/table/columnDefinitions/trendCursor/trendCursorHeader.tsx @@ -1,7 +1,10 @@ import React from 'react'; +import { parse, format } from 'date-fns'; +import { useDateTime } from '../../../../../timeZone'; +import { FULL_DATE_TIME } from '../../../../../../utils/time'; type TrendCursorColumnHeaderOptions = { - date: Date; + date: number; color?: string; }; @@ -9,12 +12,14 @@ export const TrendCursorColumnHeader = ({ date, color, }: TrendCursorColumnHeaderOptions) => { + const dateTime = useDateTime(date, FULL_DATE_TIME.replace(',', '')); + const parsedDate = parse(dateTime, 'dd/MM/yyyy HH:mm:ss', new Date()); return (
- {date.toLocaleDateString()} + {format(parsedDate, 'dd/MM/yyyy')}
- {date.toLocaleTimeString()} + {format(parsedDate, 'hh:mm:ss')}
{ expect(table).not.toBeNull(); expect( - screen.getByText(new Date(trendCursors[0].date).toLocaleTimeString()) + screen + .getAllByText(format(new Date(trendCursors[0].date), 'dd/MM/yyyy')) + .at(0) ).not.toBeNull(); expect( - screen.getByText(new Date(trendCursors[1].date).toLocaleTimeString()) + screen.getByText(format(new Date(trendCursors[1].date), 'hh:mm:ss')) ).not.toBeNull(); expect(screen.getByText('111')).not.toBeNull(); diff --git a/packages/react-components/src/components/kpi/kpi.spec.tsx b/packages/react-components/src/components/kpi/kpi.spec.tsx index 8e26b303d..bf84a2ec7 100644 --- a/packages/react-components/src/components/kpi/kpi.spec.tsx +++ b/packages/react-components/src/components/kpi/kpi.spec.tsx @@ -1,7 +1,9 @@ import React from 'react'; import { render, screen } from '@testing-library/react'; import { mockTimeSeriesDataQuery } from '@iot-app-kit/testing-util'; +import { format } from 'date-fns-tz'; import { KPI } from './kpi'; +import { FULL_DATE_TIME } from '../../utils/time'; const VIEWPORT = { duration: '5m' }; @@ -35,6 +37,6 @@ it('renders', async () => { `${DATA_STREAM.data[0].y} ` ); expect(screen.getByTestId('kpi-timestamp').textContent).toContain( - new Date(DATA_STREAM.data[0].x).toLocaleString() + format(new Date(DATA_STREAM.data[0].x), FULL_DATE_TIME) ); }); diff --git a/packages/react-components/src/components/kpi/kpiBase.spec.tsx b/packages/react-components/src/components/kpi/kpiBase.spec.tsx index c3dfd90a2..bc402e104 100644 --- a/packages/react-components/src/components/kpi/kpiBase.spec.tsx +++ b/packages/react-components/src/components/kpi/kpiBase.spec.tsx @@ -1,7 +1,9 @@ import React from 'react'; +import { format } from 'date-fns-tz'; import { render, screen } from '@testing-library/react'; import { KpiBase } from './kpiBase'; import type { DataPoint } from '@iot-app-kit/core'; +import { FULL_DATE_TIME } from '../../utils/time'; describe('name', () => { it('renders name when showName is true', () => { @@ -149,7 +151,7 @@ describe('timestamp', () => { ); expect( - screen.queryByText(PROPERTY_POINT_DATE.toLocaleString()) + screen.queryByText(format(PROPERTY_POINT_DATE, FULL_DATE_TIME)) ).not.toBeNull(); }); diff --git a/packages/react-components/src/components/kpi/kpiBase.tsx b/packages/react-components/src/components/kpi/kpiBase.tsx index a15474f06..5856e2fc2 100644 --- a/packages/react-components/src/components/kpi/kpiBase.tsx +++ b/packages/react-components/src/components/kpi/kpiBase.tsx @@ -15,6 +15,7 @@ import { fontSizeBodyS, } from '@cloudscape-design/design-tokens'; import { DataQualityText } from '../data-quality/data-quality-text'; +import { DateTime } from '../timeZone'; export const KpiBase: React.FC = ({ propertyPoint, @@ -138,7 +139,7 @@ export const KpiBase: React.FC = ({ }} />
- {isLoading ? '-' : new Date(point.x).toLocaleString()} + {isLoading ? '-' : }
)} diff --git a/packages/react-components/src/components/timeZone/index.ts b/packages/react-components/src/components/timeZone/index.ts new file mode 100644 index 000000000..874fe61c7 --- /dev/null +++ b/packages/react-components/src/components/timeZone/index.ts @@ -0,0 +1 @@ +export * from './timeZone'; diff --git a/packages/react-components/src/components/timeZone/timeZone.tsx b/packages/react-components/src/components/timeZone/timeZone.tsx new file mode 100644 index 000000000..c225ea8eb --- /dev/null +++ b/packages/react-components/src/components/timeZone/timeZone.tsx @@ -0,0 +1,44 @@ +import React, { createContext, useContext } from 'react'; + +import { utcToZonedTime, format } from 'date-fns-tz'; +import { FULL_DATE_TIME } from '../../utils/time'; + +// https://date-fns.org/v3.6.0/docs/Time-Zones#date-fns-tz +// converts a utc date to a formatted string in a specific timeZone +export const formatDate = ( + dateTime: number, + { timeZone, pattern }: { timeZone: string; pattern: string } +) => { + const zonedDate = utcToZonedTime(new Date(dateTime).toISOString(), timeZone); + const formattedDate = format(zonedDate, pattern, { timeZone: timeZone }); + + return formattedDate; +}; + +// Helper components for use in a React Context +export type DateTimeFormatContextOptions = { + timeZone: string; +}; +export const DateTimeFormatContext = + createContext({ + timeZone: Intl.DateTimeFormat().resolvedOptions().timeZone, + }); + +export type DateTimeOptions = { + dateTime: number; + pattern?: string; +}; +export const DateTime = ({ dateTime, pattern }: DateTimeOptions) => { + const formattedDate = useDateTime(dateTime, pattern); + + return <>{formattedDate}; +}; + +export const useDateTime = (dateTime: number, pattern?: string) => { + const dateTimeFormatPattern = pattern ?? FULL_DATE_TIME; + const { timeZone } = useContext(DateTimeFormatContext); + return formatDate(dateTime, { + timeZone, + pattern: dateTimeFormatPattern, + }); +}; diff --git a/packages/react-components/src/components/timestampBar/index.tsx b/packages/react-components/src/components/timestampBar/index.tsx index aa373e7b1..78a1a47fa 100644 --- a/packages/react-components/src/components/timestampBar/index.tsx +++ b/packages/react-components/src/components/timestampBar/index.tsx @@ -14,6 +14,7 @@ import { Spinner } from '@cloudscape-design/components'; import './timestamp.css'; import { useViewport } from '../../hooks/useViewport'; import { convertViewportToMs } from '../../utils/convertViewportToMs'; +import { DateTime } from '../timeZone'; type TimestampProps = { showLoadingIndicator: boolean; @@ -34,8 +35,6 @@ export const Timestamp = ({ }: TimestampProps) => { const { viewport } = useViewport(); const { initial, end } = convertViewportToMs(viewport); - const timestampStart = new Date(initial).toLocaleString(); - const timestampEnd = new Date(end).toLocaleString(); const timestampStyle = { ...styleProps, backgroundColor: showLoadingIndicator ? '' : colorBorderDividerSecondary, @@ -65,8 +64,12 @@ export const Timestamp = ({ color: colorTextBodyDefault, }} > - {timestampStart} - {timestampEnd} + + + + + +
); diff --git a/packages/react-components/src/echarts/extensions/trendCursors/view/utils/dateTime.ts b/packages/react-components/src/echarts/extensions/trendCursors/view/utils/dateTime.ts new file mode 100644 index 000000000..c64d6e285 --- /dev/null +++ b/packages/react-components/src/echarts/extensions/trendCursors/view/utils/dateTime.ts @@ -0,0 +1,10 @@ +import { formatDate } from '../../../../../components/timeZone'; + +export const getDateTime = (date: number) => { + const timeZone = Intl.DateTimeFormat().resolvedOptions().timeZone; + const formatedDate = formatDate(date, { + timeZone: timeZone, + pattern: 'dd/MM/yyyy HH:mm:ss', + }); + return formatedDate; +}; diff --git a/packages/react-components/src/echarts/extensions/trendCursors/view/utils/index.ts b/packages/react-components/src/echarts/extensions/trendCursors/view/utils/index.ts index c6ff3461a..f1bebae5e 100644 --- a/packages/react-components/src/echarts/extensions/trendCursors/view/utils/index.ts +++ b/packages/react-components/src/echarts/extensions/trendCursors/view/utils/index.ts @@ -2,3 +2,4 @@ export * from './coordinateSystem'; export * from './grid'; export * from './polyline'; export * from './xAxis'; +export * from './dateTime'; diff --git a/packages/react-components/src/echarts/extensions/trendCursors/view/view.ts b/packages/react-components/src/echarts/extensions/trendCursors/view/view.ts index 78175b07b..90a777001 100644 --- a/packages/react-components/src/echarts/extensions/trendCursors/view/view.ts +++ b/packages/react-components/src/echarts/extensions/trendCursors/view/view.ts @@ -6,7 +6,12 @@ import { SeriesModel } from 'echarts'; import Axis2D from 'echarts/types/src/coord/cartesian/Axis2D'; import { round } from '@iot-app-kit/core-util'; import useDataStore from '../../../../store'; -import { getGrid, getXAxisCoord, getXAxisDataValue } from './utils'; +import { + getGrid, + getDateTime, + getXAxisCoord, + getXAxisDataValue, +} from './utils'; import { onDeleteTrendCursor, onUpdateTrendCursor, @@ -131,9 +136,8 @@ export class TrendCursorView extends echarts.ComponentView { } toDateTimeText(date: number) { - const localeDateString = new Date(date).toLocaleDateString(); - const localeTimeString = new Date(date).toLocaleTimeString(); - const dateTimeText = `{timestamp|${localeDateString} ${localeTimeString}}`; + const dateTime = getDateTime(date); + const dateTimeText = `{timestamp|${dateTime}}`; return dateTimeText; } diff --git a/packages/react-components/src/index.ts b/packages/react-components/src/index.ts index 5a129de71..bd9febb80 100644 --- a/packages/react-components/src/index.ts +++ b/packages/react-components/src/index.ts @@ -33,6 +33,7 @@ export { useHasFeatureFlag } from './hooks/useHasFeatureFlag'; export { useGetConfigValue } from './store/index'; export { Chart } from './components/chart'; +export * from './components/timeZone'; export { AnomalyChart } from './components/anomaly-chart'; export type { diff --git a/packages/react-components/src/queries/useSiteWiseAnomalyDataSource/constants.ts b/packages/react-components/src/queries/useSiteWiseAnomalyDataSource/constants.ts index 2d4e8fa9c..19be163ec 100644 --- a/packages/react-components/src/queries/useSiteWiseAnomalyDataSource/constants.ts +++ b/packages/react-components/src/queries/useSiteWiseAnomalyDataSource/constants.ts @@ -1,5 +1,5 @@ import { HistoricalViewport } from '@iot-app-kit/core'; -import { sub } from 'date-fns/sub'; +import { sub } from 'date-fns'; export const DEFAULT_ANOMALY_DATA_SOURCE_VIEWPORT: HistoricalViewport = { start: sub(Date.now(), { days: 7 }), diff --git a/packages/react-components/src/utils/time.ts b/packages/react-components/src/utils/time.ts index 8ae5b9786..d7050caa2 100644 --- a/packages/react-components/src/utils/time.ts +++ b/packages/react-components/src/utils/time.ts @@ -13,6 +13,7 @@ export const YEAR_IN_MS = 12 * MONTH_IN_MS; // Global time format strings export const SHORT_TIME = 'hh:mm a'; export const FULL_DATE = 'yyy-MM-dd hh:mm:ss a'; +export const FULL_DATE_TIME = 'dd/MM/yyyy, hh:mm:ss'; /** * ConvertMS is a helper function that will take in milliseconds and convert it to the highest detonator