Files
2026-09-15 15:44:13 +07:00

77 lines
2.3 KiB
Dart

import 'package:intl/intl.dart';
import 'datetime_extension.dart';
/// DateFormat 构造要解析 pattern,列表里高频调用,按 pattern 缓存
final _formatters = <String, DateFormat>{};
DateFormat _formatterOf(String pattern) => _formatters.putIfAbsent(pattern, () => DateFormat(pattern));
/// 可空字符串扩展
extension StringNullableX on String? {
DateTime? get _localDateTime {
final value = this?.trim();
if (value == null || value.isEmpty) return null;
return DateTime.tryParse(value)?.toLocal();
}
String _format(String pattern) {
final date = _localDateTime;
return date == null ? '' : _formatterOf(pattern).format(date);
}
// ============= utc 字符串 → 各种本地格式 =============
/// yyyy-MM-dd HH:mm:ss
String utcToYMDHMS() => _format('yyyy-MM-dd HH:mm:ss');
/// yyyy-MM-dd HH:mm
String utcToYMDHM({String gap = '-'}) => _format('yyyy${gap}MM${gap}dd HH:mm');
/// yyyy-MM-dd
String utcToYMD({String gap = '-'}) => _format('yyyy${gap}MM${gap}dd');
/// MM月dd日
String utcToCnMD() {
final date = _localDateTime;
return date == null ? '' : '${date.month}${date.day}日';
}
/// 相对时间:"刚刚 / N分钟前 / N小时前 / N天前 / yyyy-MM-dd HH:mm"
String utcToAgo({String gap = '-'}) {
final date = _localDateTime;
//解析不出:本来就是空值兜底“近期”,脏数据给空串
if (date == null) return this?.trim().isNotEmpty == true ? '' : '近期';
final diff = DateTime.now().difference(date);
final s = diff.inSeconds;
if (s >= 0 && s < 60) return '刚刚';
final m = diff.inMinutes;
if (m > 0 && m < 60) return '${m + 1}分钟前';
final h = diff.inHours;
if (h > 0 && h < 24) return '${h + 1}小时前';
final d = diff.inDays;
if (d > 0 && d < 3) return '${d + 1}天前';
return date.ymdSMFormat(gap: gap);
}
}
/// 非空字符串扩展
extension StringX on String {
/// 截断到最大长度
String limit(int max) {
if (max <= 0) return '';
return length <= max ? this : substring(0, max);
}
/// 是否含 16 个以上的 0,用于识别全零设备号(如全零 UUID)
bool hasManyZeros() {
const zero = 0x30; //'0'
var count = 0;
for (var i = 0; i < length; i++) {
if (codeUnitAt(i) == zero && ++count >= 16) return true;
}
return false;
}
}