date_time_utils.dart 14 KB

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