初始化
This commit is contained in:
@@ -0,0 +1,218 @@
|
||||
import 'package:hgdj/hj_utils/text_util.dart';
|
||||
import 'package:hgdj/tools_base/net/net_manager.dart';
|
||||
|
||||
class DateTimeUtil {
|
||||
/// 计算当前时间差值
|
||||
static int calTime3(String? date) {
|
||||
if (TextUtil.isEmpty(date) || date?.contains("0001-01-01") == true)
|
||||
return -1;
|
||||
final time = DateTime.parse(utc2iso(date)).toLocal();
|
||||
return time.difference(DateTime.now()).inSeconds;
|
||||
}
|
||||
|
||||
/// 日期时间本地格式化 yyyy-MM-dd HH:mm:ss
|
||||
static String utc2iso(String? formattedString) {
|
||||
if (formattedString == null || formattedString.isEmpty) return '';
|
||||
try {
|
||||
final dt = DateTime.parse(formattedString).toLocal();
|
||||
return '${_fourDigits(dt.year)}-${_twoDigits(dt.month)}-${_twoDigits(dt.day)} '
|
||||
'${_twoDigits(dt.hour)}:${_twoDigits(dt.minute)}:${_twoDigits(dt.second)}';
|
||||
} catch (e) {
|
||||
return '';
|
||||
}
|
||||
}
|
||||
|
||||
/// utc 转 MM月dd日
|
||||
static String utc2isoMD(String? formattedString) {
|
||||
if (formattedString == null || formattedString.isEmpty) return '';
|
||||
try {
|
||||
final dt = DateTime.parse(formattedString).toLocal();
|
||||
return '${_twoDigits(dt.month)}月${_twoDigits(dt.day)}日';
|
||||
} catch (e) {
|
||||
return '';
|
||||
}
|
||||
}
|
||||
|
||||
/// 2020-11-26T17:44:45.000Z
|
||||
static String? format2utc(DateTime dateTime) {
|
||||
return '${_fourDigits(dateTime.year)}-${_twoDigits(dateTime.month)}-${_twoDigits(dateTime.day)}'
|
||||
'T${_twoDigits(dateTime.hour)}:${_twoDigits(dateTime.minute)}:${_twoDigits(dateTime.second)}'
|
||||
'.${_threeDigits(dateTime.millisecond)}Z';
|
||||
}
|
||||
|
||||
/// 4 位补零(年份),负数前置符号,例:5 → "0005",-5 → "-0005"
|
||||
static String _fourDigits(int n) {
|
||||
final absN = n.abs();
|
||||
final sign = n < 0 ? '-' : '';
|
||||
if (absN >= 1000) return '$n';
|
||||
if (absN >= 100) return '${sign}0$absN';
|
||||
if (absN >= 10) return '${sign}00$absN';
|
||||
return '${sign}000$absN';
|
||||
}
|
||||
|
||||
/// 3 位补零(毫秒),例:5 → "005"
|
||||
static String _threeDigits(int n) {
|
||||
if (n >= 100) return '$n';
|
||||
if (n >= 10) return '0$n';
|
||||
return '00$n';
|
||||
}
|
||||
|
||||
/// 2 位补零(月/日/时/分/秒),例:5 → "05"
|
||||
static String _twoDigits(int n) {
|
||||
if (n >= 10) return '$n';
|
||||
return '0$n';
|
||||
}
|
||||
|
||||
/// utc 转 年月日
|
||||
static String utcTurnYear(String? date,
|
||||
{String? char, bool? isChina, bool showHM = false}) {
|
||||
if (date == null || date.isEmpty) return '';
|
||||
final gap = char ?? '-';
|
||||
final dt = DateTime.parse(date).toLocal();
|
||||
final y = _fourDigits(dt.year);
|
||||
final m = _twoDigits(dt.month);
|
||||
final d = _twoDigits(dt.day);
|
||||
if (isChina == true) return '$y年$m月$d日';
|
||||
if (showHM == true) {
|
||||
return '$y$gap$m$gap$d ${_twoDigits(dt.hour)}:${_twoDigits(dt.minute)}';
|
||||
}
|
||||
return '$y$gap$m$gap$d ';
|
||||
}
|
||||
|
||||
static String utc3YearMonthDay(DateTime dateTime) {
|
||||
try {
|
||||
return '${_twoDigits(dateTime.year)}-${_twoDigits(dateTime.month)}-${_twoDigits(dateTime.day)} ';
|
||||
} catch (e) {
|
||||
return '';
|
||||
}
|
||||
}
|
||||
|
||||
/// 计算字符串时间差值
|
||||
static String? calTimediffFromNow(String? date) {
|
||||
final time = DateTime.parse(date ?? '').toLocal();
|
||||
final difference = time.difference(DateTime.now());
|
||||
final day = difference.inDays;
|
||||
final hours = difference.inHours % 24;
|
||||
return '$day天$hours小时';
|
||||
}
|
||||
|
||||
/// 秒 → MM:SS / HH:MM:SS(小时补零)。[alwaysHour] 为 true 时不足 1 小时也带小时位(00:MM:SS)
|
||||
/// 时长格式化的唯一入口,外部各处统一走这里
|
||||
static String formatHMS(int seconds, {bool alwaysHour = false}) {
|
||||
if (seconds < 0) seconds = 0;
|
||||
final h = seconds ~/ 3600;
|
||||
final m = (seconds % 3600) ~/ 60;
|
||||
final s = seconds % 60;
|
||||
final ms = '${_twoDigits(m)}:${_twoDigits(s)}';
|
||||
return (h == 0 && !alwaysHour) ? ms : '${_twoDigits(h)}:$ms';
|
||||
}
|
||||
|
||||
/// 时长 → MM:SS / HH:MM:SS(统一走 [formatHMS])
|
||||
static String? formatDuration(Duration position) =>
|
||||
formatHMS(position.inSeconds);
|
||||
|
||||
/// 秒 → (时, 分, 秒) 各两位补零字符串;时为总小时数(不取模 24),供分段倒计时 UI 用
|
||||
static (String, String, String) hms(int seconds) => (
|
||||
_twoDigits(seconds ~/ 3600),
|
||||
_twoDigits((seconds ~/ 60) % 60),
|
||||
_twoDigits(seconds % 60),
|
||||
);
|
||||
|
||||
/// 这个时间是否**还没到期**(晚于服务器当前时间)。名字有歧义,别按字面理解成「已过期」。
|
||||
/// 解析不了一律当没权益:这里被登录/刷新用户信息那条主路调用(见 GlobalStore._setMe),
|
||||
/// 裸 DateTime.parse 遇到后端换格式会把整条链抛断,登录都进不去
|
||||
static bool isExpireDate(String? time) {
|
||||
if (time == null || time.isEmpty) return false;
|
||||
final dt = DateTime.tryParse(time);
|
||||
return dt != null && dt.isAfter(netManager.getFixedCurTime());
|
||||
}
|
||||
}
|
||||
|
||||
/// 构建分秒 MM:SS
|
||||
String buildMMSS(int seconds) {
|
||||
final minute = seconds ~/ 60;
|
||||
final second = seconds % 60;
|
||||
return '${_formatTime(minute)}:${_formatTime(second)}';
|
||||
}
|
||||
|
||||
/// 数字格式化,将 0~9 的时间转换为 00~09
|
||||
String _formatTime(int timeNum) => timeNum.toString().padLeft(2, '0');
|
||||
|
||||
const String kFormatTimeFallback = '—';
|
||||
|
||||
/// 最早可展示时间(早于该时间视为非正常)
|
||||
final DateTime _kMinValidDateTime = DateTime(1970, 1, 1);
|
||||
|
||||
/// 非正常时间兜底:占位默认时间、过早/未来时间等不可用于展示
|
||||
bool _isAbnormalDateTime(DateTime date, {DateTime? now}) {
|
||||
if (date.year <= 1) return true;
|
||||
if (date.isBefore(_kMinValidDateTime)) return true;
|
||||
final reference = now ?? DateTime.now();
|
||||
if (date.isAfter(reference)) return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
/// 解析时间;空值、解析失败、非正常时间返回 null
|
||||
DateTime? _parseFormatTimeDate(String? utcTime) {
|
||||
if (utcTime == null || utcTime.trim().isEmpty) return null;
|
||||
try {
|
||||
final date = DateTime.parse(utcTime.trim()).toLocal();
|
||||
if (_isAbnormalDateTime(date)) return null;
|
||||
return date;
|
||||
} catch (_) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
bool _isSameDay(DateTime a, DateTime b) =>
|
||||
a.year == b.year && a.month == b.month && a.day == b.day;
|
||||
|
||||
/// 1 小时内 →「X分钟前」;当天 →「HH:mm」;其余 →「MM-DD HH:mm」;非正常时间 →「—」
|
||||
String formatTime(String? utcTime,
|
||||
{String gap = '-', bool hasTimeGap = false}) {
|
||||
final date = _parseFormatTimeDate(utcTime);
|
||||
if (date == null) return kFormatTimeFallback;
|
||||
|
||||
final now = DateTime.now();
|
||||
final diff = now.difference(date);
|
||||
|
||||
if (diff.inHours < 1) {
|
||||
final minutes = diff.inMinutes;
|
||||
return minutes < 1 ? '1分钟前' : '$minutes分钟前';
|
||||
}
|
||||
|
||||
if (_isSameDay(date, now)) {
|
||||
return '${DateTimeUtil._twoDigits(date.hour)}:${DateTimeUtil._twoDigits(date.minute)}';
|
||||
}
|
||||
|
||||
return '${DateTimeUtil._twoDigits(date.month)}$gap${DateTimeUtil._twoDigits(date.day)} '
|
||||
'${DateTimeUtil._twoDigits(date.hour)}:${DateTimeUtil._twoDigits(date.minute)}';
|
||||
}
|
||||
|
||||
String formatTimeTwo(String? utcTime) {
|
||||
if (utcTime?.isNotEmpty != true) return '近期';
|
||||
final now = DateTime.now();
|
||||
final date = DateTime.parse(utcTime!).toLocal();
|
||||
final changeTime =
|
||||
(now.millisecondsSinceEpoch - date.millisecondsSinceEpoch) ~/ 1000;
|
||||
|
||||
final s = changeTime;
|
||||
if (s >= 0 && s < 60) return '刚刚';
|
||||
final m = s ~/ 60;
|
||||
if (m > 0 && m < 60) return '$m分钟前';
|
||||
final h = m ~/ 60;
|
||||
if (h > 0 && h < 24) return '$h小时前';
|
||||
final d = h ~/ 24;
|
||||
if (d > 0 && d < 7) return '$d天前';
|
||||
|
||||
final w = d ~/ 7;
|
||||
if (w > 0 && w < 4) return '$w周前';
|
||||
|
||||
final month = d ~/ 30;
|
||||
if (month > 0 && month < 12) return DateTimeUtil.utc2isoMD(utcTime);
|
||||
|
||||
final year = month ~/ 12;
|
||||
if (year > 0 && year < 12)
|
||||
return DateTimeUtil.utcTurnYear(utcTime, isChina: true);
|
||||
return '';
|
||||
}
|
||||
Reference in New Issue
Block a user