import 'package:intl/intl.dart'; import 'datetime_extension.dart'; /// DateFormat 构造要解析 pattern,列表里高频调用,按 pattern 缓存 final _formatters = {}; 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; } }