Files
new-api-key-usage/apps/web/src/utils/time.ts
T

73 lines
2.7 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/**
* 时间展示:API 响应时刻为 Unix 秒(UTC);界面一律北京时间(交互共性 §3.3)。
*/
import dayjs from "dayjs";
import utc from "dayjs/plugin/utc";
import timezone from "dayjs/plugin/timezone";
dayjs.extend(utc);
dayjs.extend(timezone);
/** 北京时区展示(固定 +08:00,不随主机时区变) */
const DISPLAY_TZ = "Asia/Shanghai";
/** Unix 秒 → 北京时间「YYYY-MM-DD HH:mm:ss」 */
export function formatDateTime(unixSec: number | null | undefined): string {
if (unixSec == null) return "—";
return dayjs.unix(unixSec).tz(DISPLAY_TZ).format("YYYY-MM-DD HH:mm:ss");
}
/** Unix 秒 → 北京时间「YYYY-MM-DD」(统计口径到日) */
export function formatDate(unixSec: number | null | undefined): string {
if (unixSec == null) return "—";
return dayjs.unix(unixSec).tz(DISPLAY_TZ).format("YYYY-MM-DD");
}
/** Unix 秒 → 北京时间「HH:mm:ss」(明细时刻) */
export function formatTimeOfDay(unixSec: number | null | undefined): string {
if (unixSec == null) return "—";
return dayjs.unix(unixSec).tz(DISPLAY_TZ).format("HH:mm:ss");
}
/** 北京时间日初 → 请求用 ISO 8601 UTC(契约 §4:from/to 收 ISO) */
export function beijingDayStartToIso(date: string): string {
return dayjs.tz(date, DISPLAY_TZ).startOf("day").toISOString();
}
/** 北京时间日界(次日零点,左闭右开的 to)→ ISO UTC */
export function beijingDayEndToIso(date: string): string {
return dayjs.tz(date, DISPLAY_TZ).add(1, "day").startOf("day").toISOString();
}
export type RangeValue = { from: string; to: string };
/** 快捷项:最近 N 天(含今日),返回 [from, to) 的 ISO UTC */
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() };
}
/** 统计口径标注:「2026-09-02 ~ 10-01」(北京时间日) */
export function formatRangeCaption(fromIso: string, toIso: string): string {
if (!fromIso || !toIso) return "—";
const from = dayjs(fromIso).tz(DISPLAY_TZ).format("YYYY-MM-DD");
const to = dayjs(toIso).tz(DISPLAY_TZ).format("YYYY-MM-DD");
return `${from} ~ ${to}`;
}
/** 「数据截止」到分钟(交互共性 §3.3) */
export function formatMinute(unixSec: number | null | undefined): string {
if (unixSec == null) return "—";
return dayjs.unix(unixSec).tz(DISPLAY_TZ).format("YYYY-MM-DD HH:mm");
}
/** 距今小时数(用于数据截止停滞判定) */
export function hoursSince(unixSec: number | null | undefined): number | null {
if (unixSec == null) return null;
return (Date.now() / 1000 - unixSec) / 3600;
}