41 lines
1.9 KiB
TypeScript
41 lines
1.9 KiB
TypeScript
// 后端按北京时间存储(无时区标记),此处显式按 Asia/Shanghai 渲染,
|
|
// 避免浏览器本地时区导致时间显示错乱。
|
|
export function formatBjTime(t?: string | null): string {
|
|
if (!t) return '-';
|
|
const iso = /[Z+]/.test(t) ? t : t + '+08:00';
|
|
const d = new Date(iso);
|
|
if (isNaN(d.getTime())) return t;
|
|
return d.toLocaleString('zh-CN', { timeZone: 'Asia/Shanghai', hour12: false });
|
|
}
|
|
|
|
// 仅日期(北京时间)
|
|
export function formatBjDate(t?: string | null): string {
|
|
if (!t) return '-';
|
|
const iso = /[Z+]/.test(t) ? t : t + '+08:00';
|
|
const d = new Date(iso);
|
|
if (isNaN(d.getTime())) return t;
|
|
return d.toLocaleDateString('zh-CN', { timeZone: 'Asia/Shanghai' });
|
|
}
|
|
|
|
// 将任意 Date 换算为「北京墙钟」对应的 UTC 视图,便于按北京日历日比较
|
|
function toBjView(d: Date): Date {
|
|
return new Date(d.getTime() + (d.getTimezoneOffset() + 480) * 60000);
|
|
}
|
|
|
|
// 聊天消息时间:今天 HH:MM / 昨天 HH:MM / MM-DD HH:MM / YYYY-MM-DD HH:MM(北京时间)
|
|
export function formatChatTime(iso?: string | null): string {
|
|
if (!iso) return '';
|
|
const s = /[Z+]/.test(iso) ? iso : iso + '+08:00';
|
|
const d = new Date(s);
|
|
if (isNaN(d.getTime())) return '';
|
|
const bj = toBjView(d);
|
|
const nowBj = toBjView(new Date());
|
|
const dayDiff = Math.floor(nowBj.getTime() / 86400000) - Math.floor(bj.getTime() / 86400000);
|
|
const hhmm = d.toLocaleTimeString('zh-CN', { timeZone: 'Asia/Shanghai', hour: '2-digit', minute: '2-digit' });
|
|
if (dayDiff <= 0) return hhmm;
|
|
if (dayDiff === 1) return '昨天 ' + hhmm;
|
|
const md = d.toLocaleDateString('zh-CN', { timeZone: 'Asia/Shanghai', month: '2-digit', day: '2-digit' });
|
|
if (bj.getUTCFullYear() === nowBj.getUTCFullYear()) return md + ' ' + hhmm;
|
|
return d.toLocaleDateString('zh-CN', { timeZone: 'Asia/Shanghai', year: 'numeric', month: '2-digit', day: '2-digit' }) + ' ' + hhmm;
|
|
}
|