feat(web): 请求时间改为 ISO8601+08:00 偏移,响应仍为 Unix 秒

This commit is contained in:
2026-10-08 14:12:07 +08:00
parent 8b54629159
commit b33fc64a28
6 changed files with 79 additions and 29 deletions
+38 -6
View File
@@ -10,6 +10,38 @@ dayjs.extend(timezone);
/** 北京时区展示(固定 +08:00,不随主机时区变) */
const DISPLAY_TZ = "Asia/Shanghai";
/** 请求时间序列化:ISO 8601 带偏移(契约 §4;墙钟按北京时间) */
const REQUEST_OFFSET = "+08:00";
/**
* 绝对时刻(Date / Unix / 带时区的 ISO)→ 北京墙钟 + `+08:00`。
* 先转 Asia/Shanghai,与主机时区无关。
*/
export function toRequestIso(value: Date | string | number | dayjs.Dayjs): string {
return shanghaiIso(dayjs(value as never));
}
/**
* 表单/日历墙钟(用户当作北京时间)→ `+08:00`。
* 不做时区换算,只给墙钟贴偏移。
*/
export function wallAsBeijingIso(value: Date | dayjs.Dayjs): string {
const wall = dayjs(value as never).format("YYYY-MM-DDTHH:mm:ss.SSS");
return `${wall}${REQUEST_OFFSET}`;
}
/** Unix 秒 → 可放进日历控件的「北京墙钟」dayjs */
export function unixToBeijingWall(unixSec: number): dayjs.Dayjs {
return dayjs(
dayjs.unix(unixSec).tz(DISPLAY_TZ).format("YYYY-MM-DD HH:mm:ss.SSS"),
);
}
/** 已在 Asia/Shanghai 上的时刻 → 带偏移 ISO */
function shanghaiIso(d: dayjs.Dayjs): string {
const wall = d.tz(DISPLAY_TZ).format("YYYY-MM-DDTHH:mm:ss.SSS");
return `${wall}${REQUEST_OFFSET}`;
}
/** Unix 秒 → 北京时间「YYYY-MM-DD HH:mm:ss」 */
export function formatDateTime(unixSec: number | null | undefined): string {
@@ -29,26 +61,26 @@ export function formatTimeOfDay(unixSec: number | null | undefined): string {
return dayjs.unix(unixSec).tz(DISPLAY_TZ).format("HH:mm:ss");
}
/** 北京时间日初 → 请求用 ISO 8601 UTC(契约 §4:from/to 收 ISO) */
/** 北京时间日初 → 请求用 ISO(带 +08:00 偏移) */
export function beijingDayStartToIso(date: string): string {
return dayjs.tz(date, DISPLAY_TZ).startOf("day").toISOString();
return shanghaiIso(dayjs.tz(date, DISPLAY_TZ).startOf("day"));
}
/** 北京时间日界(次日零点,左闭右开的 to)→ ISO UTC */
/** 北京时间日界(次日零点,左闭右开的 to)→ ISO 带偏移 */
export function beijingDayEndToIso(date: string): string {
return dayjs.tz(date, DISPLAY_TZ).add(1, "day").startOf("day").toISOString();
return shanghaiIso(dayjs.tz(date, DISPLAY_TZ).add(1, "day").startOf("day"));
}
export type RangeValue = { from: string; to: string };
/** 快捷项:最近 N 天(含今日),返回 [from, to) 的 ISO UTC */
/** 快捷项:最近 N 天(含今日),返回 [from, to) 的 ISO 带偏移 */
export function recentDaysRange(
days: number,
nowMs: number = Date.now(),
): { from: string; to: string } {
const to = dayjs(nowMs).tz(DISPLAY_TZ).add(1, "day").startOf("day");
const from = to.subtract(days, "day");
return { from: from.toISOString(), to: to.toISOString() };
return { from: shanghaiIso(from), to: shanghaiIso(to) };
}
/** 统计口径标注:「2026-09-02 ~ 10-01」(北京时间日) */