-
Notifications
You must be signed in to change notification settings - Fork 27
Expand file tree
/
Copy pathformat.dart
More file actions
221 lines (192 loc) · 6.59 KB
/
format.dart
File metadata and controls
221 lines (192 loc) · 6.59 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
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
import 'package:intl/intl.dart';
/// 格式化工具类,用于格式化文件大小、速度和时间
class FormatUtil {
/// 格式化文件大小
static String formatFileSize(int bytes) {
if (bytes < 1024) {
return '$bytes B';
} else if (bytes < 1024 * 1024) {
return '${(bytes / 1024).toStringAsFixed(1)} KB';
} else if (bytes < 1024 * 1024 * 1024) {
return '${(bytes / (1024 * 1024)).toStringAsFixed(1)} MB';
} else {
return '${(bytes / (1024 * 1024 * 1024)).toStringAsFixed(1)} GB';
}
}
/// 格式化速度
static String formatSpeed(int bytesPerSecond) {
if (bytesPerSecond < 1024) {
return '$bytesPerSecond B/s';
} else if (bytesPerSecond < 1024 * 1024) {
return '${(bytesPerSecond / 1024).toStringAsFixed(1)} KB/s';
} else if (bytesPerSecond < 1024 * 1024 * 1024) {
return '${(bytesPerSecond / (1024 * 1024)).toStringAsFixed(1)} MB/s';
} else {
return '${(bytesPerSecond / (1024 * 1024 * 1024)).toStringAsFixed(1)} GB/s';
}
}
/// 格式化剩余时间
static String formatEta(int seconds) {
if (seconds < 0) {
return '未知';
}
final hours = seconds ~/ 3600;
final minutes = (seconds % 3600) ~/ 60;
final remainingSeconds = seconds % 60;
if (hours > 0) {
return '$hours:${minutes.toString().padLeft(2, '0')}:${remainingSeconds.toString().padLeft(2, '0')}';
} else {
return '${minutes.toString().padLeft(2, '0')}:${remainingSeconds.toString().padLeft(2, '0')}';
}
}
static final RegExp _nonDigitRegExp = RegExp(r'\D');
/// 解析字符串为整数
/// 先判断有没有小数点,有的话则截取整数部分,然后移除掉所有的非数字字符,最后返回int.tryParse的结果
static int? parseInt(dynamic value) {
if (value == null) return null;
String str = value.toString();
if (str.isEmpty) return null;
// 如果包含小数点,截取整数部分
if (str.contains('.')) {
str = str.substring(0, str.indexOf('.'));
}
// 移除所有非数字字符
// ⚡ Bolt: Cache RegExp to avoid recompiling on every call
str = str.replaceAll(_nonDigitRegExp, '');
return int.tryParse(str);
}
}
class Formatters {
static final NumberFormat _num2 = NumberFormat('#,##0.00');
// ⚡ Bolt: Cache RegExp to avoid recompiling on every call
static final RegExp _timezoneRegExp = RegExp(r'Z|[+-]\d{2}:?\d{2}$');
// 输入单位为 B(字节),格式化为 GB 或 TB(保留两位小数)
static String dataFromBytes(num bytes) {
final double gb = bytes / (1024 * 1024 * 1024); // B -> GB
if (gb >= 1024) {
final tb = gb / 1024; // GB -> TB
return '${_num2.format(tb)} TB';
}
return '${_num2.format(gb)} GB';
}
// 新增:输入单位为 B/s(字节每秒),格式化为 KB/s、MB/s 或 GB/s
static String speedFromBytesPerSec(num bytesPerSec) {
if (bytesPerSec < 1024) return '${bytesPerSec.toInt()} B/s';
final kb = bytesPerSec / 1024;
if (kb < 1024) return '${kb.toStringAsFixed(1)} KB/s';
final mb = kb / 1024;
if (mb < 1024) return '${mb.toStringAsFixed(1)} MB/s';
final gb = mb / 1024;
return '${gb.toStringAsFixed(2)} GB/s';
}
static String shareRate(num rate) => _num2.format(rate);
static String bonus(num bonus) {
final int v = bonus.toInt();
final int absV = v.abs();
if (absV >= 1000000) {
return '${v ~/ 1000000} M';
}
if (absV >= 1000) {
return '${v ~/ 1000} K';
}
return v.toString();
}
// 新增:格式化种子创建时间为距离现在过了多久
static String formatTorrentCreatedDate(DateTime date) {
try {
final now = DateTime.now();
final difference = now.difference(date);
// 计算各个时间单位
final years = difference.inDays ~/ 365;
final months = (difference.inDays % 365) ~/ 30;
final days = difference.inDays % 30;
final hours = difference.inHours % 24;
final minutes = difference.inMinutes % 60;
// 按优先级返回两段显示
if (years > 0) {
if (months > 0) {
return '$years 年 $months 月 前';
}
return '$years 年 前';
}
if (months > 0) {
if (days > 0) {
return '$months 月 $days 天 前';
}
return '$months 月 前';
}
if (days > 0) {
if (hours > 0) {
return '$days 天 $hours 小时 前';
}
return '$days 天 前';
}
if (hours > 0) {
if (minutes > 0) {
return '$hours 小时 $minutes 分钟 前';
}
return '$hours 小时 前';
}
// 最小单位为分钟
if (minutes > 0) {
return '$minutes 分钟 前';
}
return '刚刚'; // 不足1分钟显示为刚刚
} catch (e) {
return "- -";
}
}
static String? laterDateTime(String? a, String? b) {
DateTime? d1;
DateTime? d2;
try {
d1 = a != null && a.isNotEmpty ? DateTime.parse(a) : null;
} catch (_) {}
try {
d2 = b != null && b.isNotEmpty ? DateTime.parse(b) : null;
} catch (_) {}
if (d1 != null && d2 != null) {
return d1.isAfter(d2) ? a : b;
}
return a ?? b;
}
static DateTime parseDateTimeCustom(
String? dateStr, {
String? format,
String? zone,
}) {
if (dateStr == null || dateStr.isEmpty) return DateTime.now();
try {
String actualZone = zone ?? "+08:00";
DateTime parsed;
if (format != null && format.isNotEmpty) {
// 使用 DateFormat 解析自定义格式
parsed = DateFormat(format).parse(dateStr.trim());
} else {
// 回退逻辑:处理常见的 "yyyy-MM-dd HH:mm:ss" 或标准 ISO 格式
String normalizedDate = dateStr.trim();
if (normalizedDate.length >= 19 && normalizedDate[10] == ' ') {
normalizedDate = normalizedDate.replaceRange(10, 11, 'T');
}
if (normalizedDate.contains(_timezoneRegExp)) {
return DateTime.parse(normalizedDate).toLocal();
} else {
return DateTime.parse("$normalizedDate$actualZone").toLocal();
}
}
// 修正时区:将 DateFormat 解析出的不带时区的时间视为指定时区的时间,再转换为本地时间
String iso = parsed
.toIso8601String()
.split('.')
.first; // 取 yyyy-MM-ddTHH:mm:ss 部分
if (iso.contains('.')) iso = iso.split('.').first;
return DateTime.parse("$iso$actualZone").toLocal();
} catch (e) {
try {
return DateTime.parse(dateStr).toLocal();
} catch (_) {
return DateTime.now();
}
}
}
}