-
Notifications
You must be signed in to change notification settings - Fork 10
Expand file tree
/
Copy pathTimeUtil.cs
More file actions
170 lines (147 loc) · 5.97 KB
/
Copy pathTimeUtil.cs
File metadata and controls
170 lines (147 loc) · 5.97 KB
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
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
using System;
using System.Collections.Generic;
using Newtonsoft.Json.Linq;
using System.Globalization;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
namespace JyDraft
{
public static class TimeUtil
{
public const long SEC = 1000000; // 一秒 = 1e6 微秒
// 将输入的字符串转换为微秒, 支持 "1h52m3s" 或 "0.15s" 这样的格式
public static int Tim(object inp)
{
if (inp is int || inp is long || inp is float || inp is double)
{
return Convert.ToInt32(Math.Round(Convert.ToDouble(inp)));
}
string input = inp.ToString().Trim().ToLower();
int sign = 1;
if (input.StartsWith("-"))
{
sign = -1;
input = input.Substring(1);
}
int lastIndex = 0;
double totalTime = 0;
foreach (var (unit, factor) in new[] {
("h", 3600 * SEC),
("m", 60 * SEC),
("s", SEC),
})
{
int unitIndex = input.IndexOf(unit);
if (unitIndex == -1) continue;
string numberStr = input.Substring(lastIndex, unitIndex - lastIndex);
totalTime += double.Parse(numberStr, CultureInfo.InvariantCulture) * factor;
lastIndex = unitIndex + 1;
}
return (int)Math.Round(totalTime) * sign;
}
// Timerange类
public class Timerange : IEquatable<Timerange>
{
// 起始时间, 单位为微秒
public long Start { get; set; }
// 持续长度, 单位为微秒
public long Duration { get; set; }
public Timerange(long start, long duration)
{
Start = start;
Duration = duration;
}
/// <summary>
/// 从草稿 JSON 里解析时间区间。真实草稿是 {"start":..,"duration":..},
/// 早期写法是 "[start=.., end=..]",两种都认(原实现只认后者,导致导入自己的草稿必炸)。
/// </summary>
public static Timerange ImportJson(object jsonObj)
{
if (jsonObj == null) return null;
if (jsonObj is Dictionary<string, object> dict)
return FromParts(dict, jsonObj.ToString());
var text = jsonObj.ToString();
if (text.TrimStart().StartsWith("{"))
{
var jo = JObject.Parse(text);
return FromParts(new Dictionary<string, object>
{
["start"] = jo["start"]?.Value<long>() ?? 0L,
["duration"] = jo["duration"]?.Value<long>(),
["end"] = jo["end"]?.Value<long>()
}, text);
}
var match = Regex.Match(text, @"^\[start=(\d+),\s*end=(\d+)\]$");
if (!match.Success) throw new FormatException("Invalid format");
return new Timerange(int.Parse(match.Groups[1].Value),
int.Parse(match.Groups[2].Value) - int.Parse(match.Groups[1].Value));
}
private static Timerange FromParts(Dictionary<string, object> parts, string raw)
{
long start = Convert.ToInt64(parts.GetValueOrDefault("start", 0L) ?? 0L);
if (parts.TryGetValue("duration", out var d) && d != null)
return new Timerange(start, Convert.ToInt64(d));
if (parts.TryGetValue("end", out var e) && e != null)
return new Timerange(start, Convert.ToInt64(e) - start);
throw new FormatException("Invalid timerange: " + raw);
}
public long End => Start + Duration;
public bool Equals(Timerange other)
{
if (other == null) return false;
return Start == other.Start && Duration == other.Duration;
}
public override bool Equals(object obj)
{
return Equals(obj as Timerange);
}
public override int GetHashCode()
{
return (Start, Duration).GetHashCode();
}
// 判断两个时间范围是否有重叠
public bool Overlaps(Timerange other)
{
return !(End <= other.Start || other.End <= Start);
}
public override string ToString()
{
return $"[start={Start}, end={End}]";
}
public string Repr()
{
return $"Timerange(start={Start}, duration={Duration})";
}
public Dictionary<string, long> ExportJson()
{
return new Dictionary<string, long>
{
{"start", Start },
{"duration", Duration }
};
}
}
// Timerange的简便构造函数, 接受字符串或微秒数作为参数
public static Timerange Trange(object start, object duration)
{
return new Timerange(Tim(start), Tim(duration));
}
// 解析SRT中的时间戳字符串, 返回微秒数
public static long SrtTstamp(string srtTstamp)
{
var parts = srtTstamp.Split(',');
var secParts = parts[0].Split(':');
// secParts[0]: hours, secParts[1]: minutes, secParts[2]: seconds, parts[1]: milliseconds
long totalTime = 0;
long[] factors = { 3600 * SEC, 60 * SEC, SEC, 1000 };
for (int i = 0; i < 3; i++)
{
totalTime += long.Parse(secParts[i]) * factors[i];
}
totalTime += long.Parse(parts[1]) * factors[3];
return totalTime;
}
}
}