date_time_utils.dart 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474
  1. import 'package:intl/intl.dart';
  2. import 'log_utils.dart';
  3. /// month->days.
  4. Map<int, int> MONTH_DAY = {
  5. 1: 31,
  6. 2: 28,
  7. 3: 31,
  8. 4: 30,
  9. 5: 31,
  10. 6: 30,
  11. 7: 31,
  12. 8: 31,
  13. 9: 30,
  14. 10: 31,
  15. 11: 30,
  16. 12: 31,
  17. };
  18. /// ISO 8601 标准的时间格式字符串
  19. /// 时间与日期的格式化工具类(自定义基于Dart原生Api-DateTime实现)
  20. class DateTimeUtils {
  21. static String full = 'yyyy-MM-dd HH:mm:ss'; //如 2023-05-25 12:05:03
  22. // ===================================== 反格式化时间 ↓ =====================================
  23. /*
  24. 根据指定日期格式得到原生的DateTime对象
  25. 使用:
  26. final date = DateTimeUtils.getDateTime('2023-10-21');
  27. 打印结果 DateTime 对象为:2023-10-21 00:00:00.000
  28. final date = DateTimeUtils.getDateTime('2023-10-21 12:08:55');
  29. 打印结果 DateTime 对象为:2023-10-21 12:08:55.000
  30. final date = DateTimeUtils.getDateTime('2023-10-21 12:55');
  31. 打印结果 DateTime 对象为:2023-10-21 12:55:00.000
  32. final date = DateTimeUtils.getDateTime('2023/10/21 12:08:55');
  33. 这样就不行,因为 2023/10/21 12:08:55 不是标准格式无法转换为 DateTime 对象,必须要 2012-02-27 或 2012-02-27 13:27:00 标准格式
  34. */
  35. static DateTime? getDateTime(String dateStr, {bool? isUtc}) {
  36. DateTime? dateTime = DateTime.tryParse(dateStr);
  37. if (isUtc != null) {
  38. if (isUtc) {
  39. dateTime = dateTime?.toUtc();
  40. } else {
  41. dateTime = dateTime?.toLocal();
  42. }
  43. }
  44. return dateTime;
  45. }
  46. //格式化自定义的时间格式
  47. static DateTime? parseCustomDate(String dateStr, {String format = 'yyyy-MM-dd'}) {
  48. try {
  49. // 使用 DateFormat 来解析您的日期字符串
  50. DateFormat dateFormat = DateFormat(format, 'en_US');
  51. return dateFormat.parse(dateStr);
  52. } catch (e) {
  53. Log.e("Error parsing date: $e");
  54. return null; // 如果解析失败,返回 null
  55. }
  56. }
  57. /*
  58. 根据指定的毫秒时间戳得到原生的DateTime对象
  59. 使用:
  60. final date = DateTimeUtils.getDateTimeByMs(1682304352000)
  61. 打印结果 DateTime 对象为:2023-04-24 10:45:52.000
  62. */
  63. static DateTime getDateTimeByMs(int ms, {bool isUtc = false}) {
  64. return DateTime.fromMillisecondsSinceEpoch(ms, isUtc: isUtc);
  65. }
  66. /*
  67. 根据日期格式得到对应的毫秒值
  68. 使用:
  69. final date = DateTimeUtils.getDateMsByTimeStr('2023-10-21');
  70. 打印结果为:1697817600000
  71. final date = DateTimeUtils.getDateMsByTimeStr('2023-10-21 12:08:55');
  72. 打印结果为:1697861335000
  73. final date = DateTimeUtils.getDateMsByTimeStr('2023-10-21 12:55');
  74. 打印结果为:1697864100000
  75. */
  76. static int? getDateMsByTimeStr(String dateStr, {bool? isUtc}) {
  77. DateTime? dateTime = getDateTime(dateStr, isUtc: isUtc);
  78. return dateTime?.millisecondsSinceEpoch;
  79. }
  80. /*
  81. 获取当前系统日期的毫秒值
  82. 使用:
  83. final date = DateTimeUtils.getNowDateMs();
  84. 打印结果为:1697817600000
  85. */
  86. static int getNowDateMs() {
  87. return DateTime.now().millisecondsSinceEpoch;
  88. }
  89. // ===================================== 反格式化时间 ↑ =====================================
  90. // ===================================== 格式化时间 ↓ =====================================
  91. /*
  92. 获取当前系统日期的格式化时间值。默认格式为 yyyy-MM-dd HH:mm:ss
  93. 使用:
  94. final date = DateTimeUtils.getNowDateStr();
  95. 打印结果为:2023-10-09 09:54:26
  96. final date = DateTimeUtils.getNowDateStr(format: 'yyyy-MM-dd');
  97. 打印结果为:2023-10-09
  98. final date = DateTimeUtils.getNowDateStr(format: 'yyyy-MM-dd HH:mm');
  99. 打印结果为:2023-10-09 09:55
  100. final date = DateTimeUtils.getNowDateStr(format: 'yyyy-MMM-dd HH:mm');
  101. 打印结果为:2023-Oct-09 09:56
  102. final date = DateTimeUtils.getNowDateStr(format: 'yyyy/MMM/dd HH:mm');
  103. 打印结果为:2023/Oct/09 09:57
  104. final date = DateTimeUtils.getNowDateStr(format: 'dd MMM yyyy HH:mm');
  105. 打印结果为:09 Oct 2023 09:58
  106. */
  107. static String formatNowDateStr({String? format, bool isMonthEn = true, bool isMonthEnShort = true}) {
  108. return formatDate(DateTime.now(), format: format, isMonthEn: isMonthEn, isMonthEnShort: isMonthEnShort);
  109. }
  110. /*
  111. 根据指定的毫秒时间戳格式化时间值。默认格式为 yyyy-MM-dd HH:mm:ss
  112. 使用:
  113. final date = DateTimeUtils.formatDateMs(1682304352000,format: 'yyyy-MM-dd')
  114. 打印结果为:2023-04-24
  115. final date = DateTimeUtils.formatDateMs(1682304352000,format: 'dd MMM yyyy HH:mm');
  116. 打印结果为:24 Apr 2023 10:45
  117. */
  118. static String formatDateMs(int ms, {bool isUtc = false, String? format, bool isMonthEn = true, bool isMonthEnShort = true}) {
  119. return formatDate(getDateTimeByMs(ms, isUtc: isUtc), format: format, isMonthEn: isMonthEn, isMonthEnShort: isMonthEnShort);
  120. }
  121. /*
  122. 根据指定的日期字符串格式化时间值。默认格式为 yyyy-MM-dd HH:mm:ss
  123. @Parmas dateStr 参数必须是标准格式如 2012-02-27 或 2012-02-27 13:27:00 ,format的转换格式可以随便写
  124. 使用:
  125. final date = DateTimeUtils.formatDateStr('2023-10-21 12:08:55',format: 'dd MMM yyyy');
  126. 打印结果为:21 Oct 2023 12:08
  127. final date = DateTimeUtils.formatDateStr('2023-10-21 12:08:55',format: 'yyyy-MM-dd');
  128. 打印结果为:2023-10-21
  129. final date = DateTimeUtils.formatDateStr('2023/10/21 12:08:55',format: 'yyyy-MM-dd');
  130. 这样就不行,因为 2023/10/21 12:08:55 不是标准格式无法转换为 DateTime 对象
  131. */
  132. static String formatDateStr(String dateStr, {bool? isUtc, String? format, bool isMonthEn = true, bool isMonthEnShort = true}) {
  133. return formatDate(getDateTime(dateStr, isUtc: isUtc), format: format, isMonthEn: isMonthEn, isMonthEnShort: isMonthEnShort);
  134. }
  135. /*
  136. 总方法 - 根据标准的 DateTime 来格式化时间。默认格式为 yyyy-MM-dd HH:mm:ss
  137. 使用:
  138. final date = DateTimeUtils.formatDate(date, format: "yyyy-MM-dd");
  139. 打印结果为:2023-10-09
  140. */
  141. static String formatDate(DateTime? dateTime, {String? format, bool isMonthEn = true, bool isMonthEnShort = true}) {
  142. if (dateTime == null) return '';
  143. format = format ?? full;
  144. //对Year的处理
  145. if (format.contains('yy')) {
  146. String year = dateTime.year.toString();
  147. if (format.contains('yyyy')) {
  148. format = format.replaceAll('yyyy', year);
  149. } else {
  150. format = format.replaceAll('yy', year.substring(year.length - 2, year.length));
  151. }
  152. }
  153. //对Month的处理
  154. int month = dateTime.month;
  155. if (format.contains("M")) {
  156. if (format.contains("MM")) {
  157. if (format.contains("MMM")) {
  158. if (format.contains("MMMM")) {
  159. //处理4个M,英文显示
  160. format = format.replaceAll("MMMM", getMonthEnStr(month, true, false));
  161. } else {
  162. //处理3个M,英文显示
  163. format = format.replaceAll("MMM", getMonthEnStr(month, isMonthEn, isMonthEnShort));
  164. }
  165. } else {
  166. //处理2个M
  167. format = format.replaceAll("MM", month < 10 ? '0$month' : month.toString());
  168. }
  169. } else {
  170. //处理1个M
  171. format = format.replaceAll("M", month.toString());
  172. }
  173. }
  174. //对其他的处理
  175. format = _comFormat(dateTime.day, format, 'd', 'dd');
  176. format = _comFormat(dateTime.hour, format, 'H', 'HH');
  177. format = _comFormat(dateTime.minute, format, 'm', 'mm');
  178. format = _comFormat(dateTime.second, format, 's', 'ss');
  179. format = _comFormat(dateTime.millisecond, format, 'S', 'SSS');
  180. return format;
  181. }
  182. //格式化1位数为2位数,前面加0 如:2008-01-05 08:05:04
  183. static String _comFormat(int value, String format, String single, String full) {
  184. if (format.contains(single)) {
  185. if (format.contains(full)) {
  186. format = format.replaceAll(full, value < 10 ? '0$value' : value.toString());
  187. } else {
  188. format = format.replaceAll(single, value.toString());
  189. }
  190. }
  191. return format;
  192. }
  193. // 返回自己的月份字符串信息
  194. static String getMonthEnStr(int month, bool isMonthEn, bool isMonthEnShort) {
  195. String monthStr = month.toString();
  196. switch (month) {
  197. case 1:
  198. monthStr = !isMonthEn
  199. ? month.toString()
  200. : isMonthEnShort
  201. ? "Jan"
  202. : "January";
  203. break;
  204. case 2:
  205. monthStr = !isMonthEn
  206. ? month.toString()
  207. : isMonthEnShort
  208. ? "Feb"
  209. : "February";
  210. break;
  211. case 3:
  212. monthStr = !isMonthEn
  213. ? month.toString()
  214. : isMonthEnShort
  215. ? "Mar"
  216. : "March";
  217. break;
  218. case 4:
  219. monthStr = !isMonthEn
  220. ? month.toString()
  221. : isMonthEnShort
  222. ? "Apr"
  223. : "April";
  224. break;
  225. case 5:
  226. monthStr = !isMonthEn
  227. ? month.toString()
  228. : isMonthEnShort
  229. ? "May"
  230. : "May";
  231. break;
  232. case 6:
  233. monthStr = !isMonthEn
  234. ? month.toString()
  235. : isMonthEnShort
  236. ? "Jun"
  237. : "June";
  238. break;
  239. case 7:
  240. monthStr = !isMonthEn
  241. ? month.toString()
  242. : isMonthEnShort
  243. ? "Jul"
  244. : "July";
  245. break;
  246. case 8:
  247. monthStr = !isMonthEn
  248. ? month.toString()
  249. : isMonthEnShort
  250. ? "Aug"
  251. : "August";
  252. break;
  253. case 9:
  254. monthStr = !isMonthEn
  255. ? month.toString()
  256. : isMonthEnShort
  257. ? "Sep"
  258. : "September";
  259. break;
  260. case 10:
  261. monthStr = !isMonthEn
  262. ? month.toString()
  263. : isMonthEnShort
  264. ? "Oct"
  265. : "October";
  266. break;
  267. case 11:
  268. monthStr = !isMonthEn
  269. ? month.toString()
  270. : isMonthEnShort
  271. ? "Nov"
  272. : "November";
  273. break;
  274. case 12:
  275. monthStr = !isMonthEn
  276. ? month.toString()
  277. : isMonthEnShort
  278. ? "Dec"
  279. : "December";
  280. break;
  281. }
  282. return monthStr;
  283. }
  284. /// 获取输入时间是星期几
  285. static String getWeekdayByMs(int milliseconds, {bool isUtc = false, String languageCode = 'en', bool short = false}) {
  286. DateTime dateTime = getDateTimeByMs(milliseconds, isUtc: isUtc);
  287. return getWeekday(dateTime, languageCode: languageCode, short: short);
  288. }
  289. /*
  290. 根据标准的 DateTime 对象,获取 weekDay 属性,并返回自己的星期字符串
  291. */
  292. static String getWeekday(DateTime? dateTime, {String languageCode = 'zh', bool short = false}) {
  293. if (dateTime == null) return "";
  294. String weekday = "";
  295. switch (dateTime.weekday) {
  296. case 1:
  297. weekday = languageCode == 'zh' ? '星期一' : 'Monday';
  298. break;
  299. case 2:
  300. weekday = languageCode == 'zh' ? '星期二' : 'Tuesday';
  301. break;
  302. case 3:
  303. weekday = languageCode == 'zh' ? '星期三' : 'Wednesday';
  304. break;
  305. case 4:
  306. weekday = languageCode == 'zh' ? '星期四' : 'Thursday';
  307. break;
  308. case 5:
  309. weekday = languageCode == 'zh' ? '星期五' : 'Friday';
  310. break;
  311. case 6:
  312. weekday = languageCode == 'zh' ? '星期六' : 'Saturday';
  313. break;
  314. case 7:
  315. weekday = languageCode == 'zh' ? '星期日' : 'Sunday';
  316. break;
  317. default:
  318. break;
  319. }
  320. return languageCode == 'zh' ? (short ? weekday.replaceAll('星期', '周') : weekday) : weekday.substring(0, short ? 3 : weekday.length);
  321. }
  322. /// 在今年的第几天.
  323. static int getDayOfYear(DateTime dateTime) {
  324. int year = dateTime.year;
  325. int month = dateTime.month;
  326. int days = dateTime.day;
  327. for (int i = 1; i < month; i++) {
  328. days = days + MONTH_DAY[i]!;
  329. }
  330. if (isLeapYearByYear(year) && month > 2) {
  331. days = days + 1;
  332. }
  333. return days;
  334. }
  335. /// 在今年的第几天.
  336. static int getDayOfYearByMs(int ms, {bool isUtc = false}) {
  337. return getDayOfYear(DateTime.fromMillisecondsSinceEpoch(ms, isUtc: isUtc));
  338. }
  339. /// 是否是当天.
  340. static bool isToday(int? milliseconds, {bool isUtc = false, int? locMs}) {
  341. if (milliseconds == null || milliseconds == 0) return false;
  342. DateTime old = DateTime.fromMillisecondsSinceEpoch(milliseconds, isUtc: isUtc);
  343. DateTime now;
  344. if (locMs != null) {
  345. now = DateTimeUtils.getDateTimeByMs(locMs);
  346. } else {
  347. now = isUtc ? DateTime.now().toUtc() : DateTime.now().toLocal();
  348. }
  349. return old.year == now.year && old.month == now.month && old.day == now.day;
  350. }
  351. /// 根据 DateTime 判断是否是当天
  352. static bool isTodayByDateTime(DateTime target) {
  353. final now = DateTime.now();
  354. return target.year == now.year &&
  355. target.month == now.month &&
  356. target.day == now.day;
  357. }
  358. /// 是否是昨天.
  359. static bool isYesterday(DateTime dateTime, DateTime locDateTime) {
  360. if (yearIsEqual(dateTime, locDateTime)) {
  361. int spDay = getDayOfYear(locDateTime) - getDayOfYear(dateTime);
  362. return spDay == 1;
  363. } else {
  364. return ((locDateTime.year - dateTime.year == 1) && dateTime.month == 12 && locDateTime.month == 1 && dateTime.day == 31 && locDateTime.day == 1);
  365. }
  366. }
  367. /// 是否是昨天.
  368. static bool isYesterdayByMs(int ms, int locMs) {
  369. return isYesterday(DateTime.fromMillisecondsSinceEpoch(ms), DateTime.fromMillisecondsSinceEpoch(locMs));
  370. }
  371. /// 是否是本周.
  372. static bool isWeek(int? ms, {bool isUtc = false, int? locMs}) {
  373. if (ms == null || ms <= 0) {
  374. return false;
  375. }
  376. DateTime _old = DateTime.fromMillisecondsSinceEpoch(ms, isUtc: isUtc);
  377. DateTime _now;
  378. if (locMs != null) {
  379. _now = DateTimeUtils.getDateTimeByMs(locMs, isUtc: isUtc);
  380. } else {
  381. _now = isUtc ? DateTime.now().toUtc() : DateTime.now().toLocal();
  382. }
  383. DateTime old = _now.millisecondsSinceEpoch > _old.millisecondsSinceEpoch ? _old : _now;
  384. DateTime now = _now.millisecondsSinceEpoch > _old.millisecondsSinceEpoch ? _now : _old;
  385. return (now.weekday >= old.weekday) && (now.millisecondsSinceEpoch - old.millisecondsSinceEpoch <= 7 * 24 * 60 * 60 * 1000);
  386. }
  387. /// 是否同年.
  388. static bool yearIsEqual(DateTime dateTime, DateTime locDateTime) {
  389. return dateTime.year == locDateTime.year;
  390. }
  391. /// 是否同年.
  392. static bool yearIsEqualByMs(int ms, int locMs) {
  393. return yearIsEqual(DateTime.fromMillisecondsSinceEpoch(ms), DateTime.fromMillisecondsSinceEpoch(locMs));
  394. }
  395. /// 是否是闰年
  396. static bool isLeapYear(DateTime dateTime) {
  397. return isLeapYearByYear(dateTime.year);
  398. }
  399. /// 是否是闰年
  400. static bool isLeapYearByYear(int year) {
  401. return year % 4 == 0 && year % 100 != 0 || year % 400 == 0;
  402. }
  403. /// 输入时间距离当前时间有多少年
  404. static int distanceCurrentYear(DateTime date) {
  405. Duration difference = DateTime.now().difference(date);
  406. return (difference.inDays / 365).floor();
  407. }
  408. /// 输入时间距离当前时间有多少天
  409. static int distanceCurrentDay(DateTime date) {
  410. Duration difference = DateTime.now().difference(date);
  411. return difference.inDays;
  412. }
  413. }