File size: 2,508 Bytes
a1ff683
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
const CHINA_TIME_ZONE = "Asia/Shanghai";

const PLAIN_DATE_TIME_RE = /^(\d{4})-(\d{2})-(\d{2})(?:[ T](\d{2}):(\d{2})(?::(\d{2}))?)?$/;

function pad(value: string | undefined) {
  return value || "00";
}

function formatPlainChinaDateTime(value: string, withSeconds = false) {
  const match = value.trim().match(PLAIN_DATE_TIME_RE);
  if (!match) {
    return null;
  }
  const [, year, month, day, hour, minute, second] = match;
  if (!hour || !minute) {
    return `${year}/${month}/${day}`;
  }
  return withSeconds
    ? `${year}/${month}/${day} ${hour}:${minute}:${pad(second)}`
    : `${year}/${month}/${day} ${hour}:${minute}`;
}

export function formatChinaDateTime(value?: string | number | null, options?: { seconds?: boolean }) {
  if (value === null || value === undefined || value === "") {
    return "—";
  }
  const raw = String(value).trim();
  const plain = formatPlainChinaDateTime(raw, Boolean(options?.seconds));
  if (plain) {
    return plain;
  }
  const date = new Date(raw);
  if (Number.isNaN(date.getTime())) {
    return raw;
  }
  return new Intl.DateTimeFormat("zh-CN", {
    timeZone: CHINA_TIME_ZONE,
    year: "numeric",
    month: "2-digit",
    day: "2-digit",
    hour: "2-digit",
    minute: "2-digit",
    second: options?.seconds ? "2-digit" : undefined,
    hour12: false,
  }).format(date);
}

export function formatChinaShortDateTime(value?: string | number | null) {
  if (value === null || value === undefined || value === "") {
    return "";
  }
  const raw = String(value).trim();
  const plain = formatPlainChinaDateTime(raw);
  if (plain) {
    return plain.slice(5);
  }
  const date = new Date(raw);
  if (Number.isNaN(date.getTime())) {
    return raw;
  }
  return new Intl.DateTimeFormat("zh-CN", {
    timeZone: CHINA_TIME_ZONE,
    month: "2-digit",
    day: "2-digit",
    hour: "2-digit",
    minute: "2-digit",
    hour12: false,
  }).format(date);
}

export function formatChinaTime(value?: string | number | null) {
  if (value === null || value === undefined || value === "") {
    return "";
  }
  const raw = String(value).trim();
  const match = raw.match(PLAIN_DATE_TIME_RE);
  if (match?.[4] && match?.[5]) {
    return `${match[4]}:${match[5]}:${pad(match[6])}`;
  }
  const date = new Date(raw);
  if (Number.isNaN(date.getTime())) {
    return raw;
  }
  return new Intl.DateTimeFormat("zh-CN", {
    timeZone: CHINA_TIME_ZONE,
    hour: "2-digit",
    minute: "2-digit",
    second: "2-digit",
    hour12: false,
  }).format(date);
}