unify Shanghai time across Semi UI workspaces
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
import { describe, expect, it } from 'vitest';
|
||||
import { formatZhNumber } from './formatters';
|
||||
import { formatShanghaiDateTime, formatZhNumber } from './formatters';
|
||||
|
||||
describe('formatZhNumber', () => {
|
||||
it('formats Chinese locale numbers with independent precision caches', () => {
|
||||
@@ -13,3 +13,17 @@ describe('formatZhNumber', () => {
|
||||
expect(formatZhNumber(Number.NaN, 2)).toBe('NaN');
|
||||
});
|
||||
});
|
||||
|
||||
describe('formatShanghaiDateTime', () => {
|
||||
it('renders explicit timestamps in Shanghai and preserves local business values', () => {
|
||||
expect(formatShanghaiDateTime('2026-07-18T02:33:00Z')).toBe('2026-07-18 10:33:00');
|
||||
expect(formatShanghaiDateTime('2026-07-18T02:33:00+08:00')).toBe('2026-07-18 02:33:00');
|
||||
expect(formatShanghaiDateTime('2026-07-18 02:33:00')).toBe('2026-07-18 02:33:00');
|
||||
});
|
||||
|
||||
it('converts timezone-less UTC service timestamps only when the source contract says UTC', () => {
|
||||
expect(formatShanghaiDateTime('2026-07-18 02:33:00', { sourceZone: 'utc' })).toBe('2026-07-18 10:33:00');
|
||||
expect(formatShanghaiDateTime('', { sourceZone: 'utc' })).toBe('—');
|
||||
expect(formatShanghaiDateTime(undefined, { empty: '尚未上报' })).toBe('尚未上报');
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,4 +1,16 @@
|
||||
const zhNumberFormatters = new Map<number, Intl.NumberFormat>();
|
||||
const shanghaiDateTimeFormatter = new Intl.DateTimeFormat('sv-SE', {
|
||||
timeZone: 'Asia/Shanghai',
|
||||
year: 'numeric',
|
||||
month: '2-digit',
|
||||
day: '2-digit',
|
||||
hour: '2-digit',
|
||||
minute: '2-digit',
|
||||
second: '2-digit',
|
||||
hour12: false
|
||||
});
|
||||
|
||||
export type DateTimeSourceZone = 'preserve' | 'utc';
|
||||
|
||||
export function formatZhNumber(value: number, maximumFractionDigits = 0) {
|
||||
let formatter = zhNumberFormatters.get(maximumFractionDigits);
|
||||
@@ -8,3 +20,18 @@ export function formatZhNumber(value: number, maximumFractionDigits = 0) {
|
||||
}
|
||||
return formatter.format(value);
|
||||
}
|
||||
|
||||
export function formatShanghaiDateTime(
|
||||
value?: string,
|
||||
{ empty = '—', sourceZone = 'preserve' }: { empty?: string; sourceZone?: DateTimeSourceZone } = {}
|
||||
) {
|
||||
if (!value?.trim()) return empty;
|
||||
const source = value.trim();
|
||||
const fallback = source.replace('T', ' ').replace(/\.\d{1,9}/, '').replace(/Z$/, '').slice(0, 19);
|
||||
const hasExplicitZone = /(?:Z|[+-]\d{2}:?\d{2})$/i.test(source);
|
||||
if (!hasExplicitZone && sourceZone === 'preserve') return fallback;
|
||||
const normalized = hasExplicitZone ? source : `${source.replace(' ', 'T')}Z`;
|
||||
const parsed = new Date(normalized);
|
||||
if (!Number.isFinite(parsed.getTime())) return fallback || empty;
|
||||
return shanghaiDateTimeFormatter.format(parsed).replace('T', ' ');
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user