diff --git a/src/features/hall/hall-draw-panel.tsx b/src/features/hall/hall-draw-panel.tsx index 46a0179..be770a5 100644 --- a/src/features/hall/hall-draw-panel.tsx +++ b/src/features/hall/hall-draw-panel.tsx @@ -15,7 +15,7 @@ import type { HallDrawLiveSnapshot } from "@/features/hall/use-hall-draw-live"; import { formatSecondsClock } from "@/lib/format-gmt"; import { LOTTERY_SCHEDULE_TIMEZONE } from "@/lib/lottery-schedule-timezone"; import { - formatLotteryInstant, + formatPlayerInstant, formatLotteryScheduleClock, getBrowserTimeZoneLabel, } from "@/lib/player-datetime"; @@ -34,7 +34,7 @@ function ScheduleAnchorTime({ payload }: { payload: DrawCurrentPayload }) { : isOpen ? "draw.scheduledEnd" : "draw.scheduledClose"; - const formatted = source ? formatLotteryInstant(source) : null; + const formatted = source ? formatPlayerInstant(source) : null; if (!formatted) { return ( <> diff --git a/src/features/orders/order-meta-line.tsx b/src/features/orders/order-meta-line.tsx index f21fe94..374a8b6 100644 --- a/src/features/orders/order-meta-line.tsx +++ b/src/features/orders/order-meta-line.tsx @@ -2,7 +2,7 @@ import type { TFunction } from "i18next"; -import { formatLotteryInstant } from "@/lib/player-datetime"; +import { formatPlayerInstant } from "@/lib/player-datetime"; type OrderMetaLineProps = { orderNo: string | null | undefined; @@ -21,7 +21,7 @@ export function OrderMetaLine({ orderNo, placedAt, t, className }: OrderMetaLine {t("orders.orderNoLabel")}{" "} {displayNo} · - {formatLotteryInstant(placedAt ?? null)} + {formatPlayerInstant(placedAt ?? null)}
); } diff --git a/src/features/orders/ticket-order-detail-screen.tsx b/src/features/orders/ticket-order-detail-screen.tsx index 8551daf..496f06a 100644 --- a/src/features/orders/ticket-order-detail-screen.tsx +++ b/src/features/orders/ticket-order-detail-screen.tsx @@ -20,7 +20,7 @@ import { TwentyThreeResultsGrid } from "@/features/results/twenty-three-results- import { useCurrencyCatalog } from "@/hooks/use-currency-catalog"; import { orderGroupPath } from "@/features/orders/group-ticket-items"; import { StatusDot, ticketStatusDisplay } from "@/features/orders/ticket-item-status"; -import { formatLotteryInstant } from "@/lib/player-datetime"; +import { formatPlayerInstant } from "@/lib/player-datetime"; import { formatMinorAsCurrency } from "@/lib/money"; import { norm4d } from "@/lib/norm-4d"; import { useActivePlayerCurrency } from "@/hooks/use-active-player-currency"; @@ -274,7 +274,7 @@ export function TicketOrderDetailScreen({ ticketNo }: { ticketNo: string }) {{row.code}
- {formatLotteryInstant(row.time)} + {formatPlayerInstant(row.time)}
))} @@ -422,7 +422,7 @@ export function TicketOrderDetailScreen({ ticketNo }: { ticketNo: string }) { {data.settled_at ? (- {t("orders.settledAt", { time: formatLotteryInstant(data.settled_at) })} + {t("orders.settledAt", { time: formatPlayerInstant(data.settled_at) })}
) : null} diff --git a/src/features/player/notifications-screen.tsx b/src/features/player/notifications-screen.tsx index ceb0770..1745298 100644 --- a/src/features/player/notifications-screen.tsx +++ b/src/features/player/notifications-screen.tsx @@ -7,7 +7,7 @@ import { useTranslation } from "react-i18next"; import { Button } from "@/components/ui/button"; import { PlayerPanel } from "@/components/layout/player-panel"; import { usePendingWalletReconcile } from "@/hooks/use-pending-wallet-reconcile"; -import { formatLocalDateTime } from "@/lib/format-local-datetime"; +import { formatPlayerInstant } from "@/lib/player-datetime"; import { formatMinorAsCurrency } from "@/lib/money"; import { pendingReconcileDescriptionKey, @@ -74,7 +74,7 @@ export function NotificationsScreen() { {t(pendingReconcileTitleKey(item.type))}- {formatLocalDateTime(item.created_at)} + {formatPlayerInstant(item.created_at)}
{t("results.drawTime", { time: "" }).replace(":", "").trim()}
- {formatLotteryInstant(data.draw.draw_time_iso ?? data.draw.draw_time ?? null)} + {formatPlayerInstant(data.draw.draw_time_iso ?? data.draw.draw_time ?? null)}
{t("results.drawTime", { - time: formatLotteryInstant( + time: formatPlayerInstant( featured.draw_time_iso ?? featured.draw_time ?? null, ), })} @@ -283,7 +283,7 @@ export function DrawResultsListScreen() { {row.draw_no}
- {formatLotteryInstant(row.draw_time_iso ?? row.draw_time ?? null)} + {formatPlayerInstant(row.draw_time_iso ?? row.draw_time ?? null)}
diff --git a/src/features/wallet/wallet-logs-block.tsx b/src/features/wallet/wallet-logs-block.tsx index f55ee9a..7b46659 100644 --- a/src/features/wallet/wallet-logs-block.tsx +++ b/src/features/wallet/wallet-logs-block.tsx @@ -5,7 +5,7 @@ import { useTranslation } from "react-i18next"; import { Button } from "@/components/ui/button"; import { Skeleton } from "@/components/ui/skeleton"; -import { formatLocalDateTime } from "@/lib/format-local-datetime"; +import { formatPlayerInstant } from "@/lib/player-datetime"; import { formatMinorAsCurrency } from "@/lib/money"; import type { WalletLogItem, WalletLogsData } from "@/types/api/wallet-logs"; @@ -225,7 +225,7 @@ export function LogRow({- {formatLocalDateTime(item.created_at)} + {formatPlayerInstant(item.created_at)}
{item.ref_id ? (diff --git a/src/lib/format-local-datetime.ts b/src/lib/format-local-datetime.ts deleted file mode 100644 index 872a074..0000000 --- a/src/lib/format-local-datetime.ts +++ /dev/null @@ -1,26 +0,0 @@ -function pad2(n: number): string { - return String(n).padStart(2, "0"); -} - -/** - * 将接口 ISO 8601 时间格式化为浏览器 **本地时区** 下的 `YYYY-MM-DD HH:mm:ss`。 - * - * 避免对原始字符串仅 `slice(0,19)`(易把 UTC 刻度误当本地钟面)。 - */ -export function formatLocalDateTime(iso: string | null | undefined): string { - if (iso == null || iso === "") { - return "—"; - } - const ms = Date.parse(iso); - if (Number.isNaN(ms)) { - return "—"; - } - const date = new Date(ms); - const y = date.getFullYear(); - const m = pad2(date.getMonth() + 1); - const d = pad2(date.getDate()); - const h = pad2(date.getHours()); - const min = pad2(date.getMinutes()); - const s = pad2(date.getSeconds()); - return `${y}-${m}-${d} ${h}:${min}:${s}`; -} diff --git a/src/lib/player-datetime.ts b/src/lib/player-datetime.ts index cfe7ece..5c62178 100644 --- a/src/lib/player-datetime.ts +++ b/src/lib/player-datetime.ts @@ -126,9 +126,12 @@ export function getBrowserTimeZoneLabel(date = new Date()): string { } /** - * 将接口 ISO 时间串格式化为 **浏览器本地时区** 下的 `YYYY-MM-DD HH:mm:ss`。 + * 将接口 ISO 8601 时间格式化为浏览器 **本地时区** 下的 `YYYY-MM-DD HH:mm:ss`。 + * + * 玩家端订单、钱包、通知、开奖结果等“已发生事件时间”统一走这里。 + * 避免对原始字符串仅 `slice(0,19)`(易把 UTC 刻度误当本地钟面)。 */ -export function formatLotteryInstant(iso: string | null | undefined): string { +export function formatPlayerInstant(iso: string | null | undefined): string { if (iso == null || iso === "") { return "—"; } @@ -139,6 +142,9 @@ export function formatLotteryInstant(iso: string | null | undefined): string { return formatParts(new Date(ms)); } +/** @deprecated 玩家端新代码请使用 {@link formatPlayerInstant}。 */ +export const formatLotteryInstant = formatPlayerInstant; + /** * 将服务端计划时刻(无时区的 `YYYY-MM-DD HH:mm:ss`,按 schedule_timezone 解释,默认 UTC) * 格式化为浏览器本地时区的 `YYYY-MM-DD HH:mm:ss`。 @@ -158,7 +164,7 @@ export function formatLotteryScheduleClock( } /** - * 按指定 IANA 时区格式化(管理端等场景);玩家端展示请用 {@link formatLotteryInstant}。 + * 按指定 IANA 时区格式化(管理端等场景);玩家端展示请用 {@link formatPlayerInstant}。 */ export function formatLotteryInstantInTimeZone( iso: string | null | undefined,