返回 slidev
timestring.ts
根目录 / packages / parser / src / timesplit / timestring.ts
1 /**
2 * Parse timestamp into seconds
3 *
4 * Accepts:
5 * - 10:50.1
6 * - 10s
7 * - 5m
8 * - 3min
9 * - 3mins 5secs
10 * - 10.5m3s
11 * - +10s
12 * - 1h10m30s
13 * - 1h4s
14 * - 1:1:1
15 */
16 const RE_ALPHA = /[a-z]/i
17
18 export function parseTimeString(timestamp: string | number): {
19 seconds: number
20 relative: boolean
21 } {
22 if (typeof timestamp === 'number') {
23 return {
24 seconds: timestamp,
25 relative: false,
26 }
27 }
28
29 const relative = timestamp.startsWith('+')
30 if (relative) {
31 timestamp = timestamp.slice(1)
32 }
33 let seconds = 0
34 if (timestamp.includes(':')) {
35 const parts = timestamp.split(':').map(Number)
36 let h = 0
37 let m = 0
38 let s = 0
39 if (parts.length === 3) {
40 h = parts[0]
41 m = parts[1]
42 s = parts[2]
43 }
44 else if (parts.length === 2) {
45 m = parts[0]
46 s = parts[1]
47 }
48 else if (parts.length === 1) {
49 s = parts[0]
50 }
51 else {
52 throw new TypeError('Invalid timestamp format')
53 }
54 if (Number.isNaN(h) || Number.isNaN(m) || Number.isNaN(s)) {
55 throw new TypeError('Invalid timestamp format')
56 }
57 seconds = (h || 0) * 3600 + (m || 0) * 60 + (s || 0)
58 }
59 else if (!RE_ALPHA.test(timestamp)) {
60 seconds = Number(timestamp)
61 if (Number.isNaN(seconds)) {
62 throw new TypeError('Invalid timestamp format')
63 }
64 }
65 else {
66 const unitMap: Record<string, number> = {
67 s: 1,
68 sec: 1,
69 secs: 1,
70 m: 60,
71 min: 60,
72 mins: 60,
73 h: 3600,
74 hr: 3600,
75 hrs: 3600,
76 hour: 3600,
77 hours: 3600,
78 day: 86400,
79 days: 86400,
80 week: 604800,
81 weeks: 604800,
82 month: 2629746,
83 months: 2629746,
84 year: 31556952,
85 years: 31556952,
86 }
87 const regex = /([\d.]+)([a-z]+)/gi
88 const matches = timestamp.matchAll(regex)
89 if (matches) {
90 for (const match of matches) {
91 const value = Number(match[1])
92 if (Number.isNaN(value)) {
93 throw new TypeError(`Invalid timestamp value: ${match[1]}`)
94 }
95 const unit = match[2].toLowerCase()
96 if (!(unit in unitMap)) {
97 throw new TypeError(`Invalid timestamp unit: ${unit}`)
98 }
99 seconds += value * unitMap[unit]
100 }
101 }
102 const remaining = timestamp.replace(regex, '').trim()
103 if (remaining) {
104 throw new TypeError(`Unknown timestamp remaining: ${remaining}`)
105 }
106 }
107
108 return {
109 seconds,
110 relative,
111 }
112 }
113
113 lines TYPESCRIPT