柯桥增值式服务
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

899 lines
28KB

  1. package com.ningdatech.kqapi.common.util;
  2. import cn.hutool.core.convert.Convert;
  3. import cn.hutool.core.date.LocalDateTimeUtil;
  4. import cn.hutool.core.util.StrUtil;
  5. import com.ningdatech.kqapi.common.exception.BizException;
  6. import lombok.extern.slf4j.Slf4j;
  7. import java.text.ParseException;
  8. import java.text.SimpleDateFormat;
  9. import java.time.*;
  10. import java.time.format.DateTimeFormatter;
  11. import java.time.temporal.ChronoUnit;
  12. import java.util.*;
  13. import java.util.stream.Stream;
  14. import static cn.hutool.core.date.DatePattern.*;
  15. /**
  16. * 描述:日期工具类
  17. *
  18. * @author WendyYang
  19. * 修改时间:2018/4/24
  20. */
  21. @Slf4j
  22. public final class NdDateUtils {
  23. public static final String DEFAULT_YEAR_FORMAT = "yyyy";
  24. public static final String DEFAULT_MONTH_FORMAT = "yyyy-MM";
  25. public static final String DEFAULT_MONTH_FORMAT_SLASH = "yyyy/MM";
  26. public static final String DEFAULT_MONTH_FORMAT_EN = "yyyy年MM月";
  27. public static final String DEFAULT_WEEK_FORMAT = "yyyy-ww";
  28. public static final String DEFAULT_WEEK_FORMAT_EN = "yyyy年ww周";
  29. public static final String DEFAULT_DATE_FORMAT = NORM_DATE_PATTERN;
  30. public static final String DEFAULT_DATE_FORMAT_EN = CHINESE_DATE_PATTERN;
  31. public static final String DEFAULT_DATE_TIME_FORMAT = NORM_DATETIME_PATTERN;
  32. public static final String DEFAULT_DATE_TIME_START_FORMAT = "yyyy-MM-dd 00:00:00";
  33. public static final String DEFAULT_DATE_TIME_END_FORMAT = "yyyy-MM-dd 23:59:59";
  34. public static final String DEFAULT_DATE_TIME_FORMAT_EN = CHINESE_DATE_TIME_PATTERN;
  35. public static final String DEFAULT_TIME_FORMAT = NORM_TIME_PATTERN;
  36. public static final String DAY = "DAY";
  37. public static final String MONTH = "MONTH";
  38. public static final String WEEK = "WEEK";
  39. public static final String DEFAULT_DATE_FORMAT_MATCHES = "^\\d{4}-\\d{1,2}-\\d{1,2}$";
  40. public static final String DEFAULT_DATE_TIME_FORMAT_MATCHES = "^\\d{4}-\\d{1,2}-\\d{1,2} {1}\\d{1,2}:\\d{1,2}:\\d{1,2}$";
  41. public static final String DEFAULT_DATE_FORMAT_EN_MATCHES = "^\\d{4}年\\d{1,2}月\\d{1,2}日$";
  42. public static final String DEFAULT_DATE_TIME_FORMAT_EN_MATCHES = "^\\d{4}年\\d{1,2}月\\d{1,2}日\\d{1,2}时\\d{1,2}分\\d{1,2}秒$";
  43. public static final String SLASH_DATE_FORMAT_MATCHES = "^\\d{4}/\\d{1,2}/\\d{1,2}$";
  44. public static final String SLASH_DATE_TIME_FORMAT_MATCHES = "^\\d{4}/\\d{1,2}/\\d{1,2} {1}\\d{1,2}:\\d{1,2}:\\d{1,2}$";
  45. public static final String SLASH_DATE_FORMAT = "yyyy/MM/dd";
  46. public static final String SLASH_DATE_TIME_FORMAT = "yyyy/MM/dd HH:mm:ss";
  47. public static final String CRON_FORMAT = "ss mm HH dd MM ? yyyy";
  48. /**
  49. * 一个月平均天数
  50. */
  51. public static final long MAX_MONTH_DAY = 30;
  52. /**
  53. * 3个月平均天数
  54. */
  55. public static final long MAX_3_MONTH_DAY = 90;
  56. /**
  57. * 一年平均天数
  58. */
  59. public static final long MAX_YEAR_DAY = 365;
  60. private static final Map<String, String> DATE_FORMAT = new LinkedHashMap<>(5);
  61. //---------------------------------------------------格式化日期start-------------------------------------------------
  62. static {
  63. DATE_FORMAT.put(DEFAULT_DATE_FORMAT, DEFAULT_DATE_FORMAT_MATCHES);
  64. DATE_FORMAT.put(SLASH_DATE_FORMAT, SLASH_DATE_FORMAT_MATCHES);
  65. DATE_FORMAT.put(DEFAULT_DATE_FORMAT_EN, DEFAULT_DATE_FORMAT_EN_MATCHES);
  66. }
  67. private NdDateUtils() {
  68. }
  69. /**
  70. * 将字符串解析LocalDate
  71. *
  72. * @param source 源参数
  73. * 支持以下格式:
  74. * yyyy-MM-dd
  75. * yyyy/MM/dd
  76. * yyyy年MM月dd日
  77. * @return 日期
  78. */
  79. public static LocalDate parse(String source) {
  80. String sourceTrim = source.trim();
  81. Set<Map.Entry<String, String>> entries = DATE_FORMAT.entrySet();
  82. for (Map.Entry<String, String> entry : entries) {
  83. if (sourceTrim.matches(entry.getValue())) {
  84. return LocalDate.parse(source, DateTimeFormatter.ofPattern(entry.getKey()));
  85. }
  86. }
  87. throw BizException.wrap("解析日期失败, 请传递正确的日期格式");
  88. }
  89. /**
  90. * 转换 Date 为 cron , eg: "0 07 10 15 1 ? 2016"
  91. *
  92. * @param date 时间点
  93. * @return cron 表达式
  94. */
  95. public static String getCron(Date date) {
  96. return format(date, CRON_FORMAT);
  97. }
  98. /**
  99. * 转换 LocalDateTime 为 cron , eg. "0 07 10 15 1 ? 2016"
  100. *
  101. * @param date 时间点
  102. * @return cron 表达式
  103. */
  104. public static String getCron(LocalDateTime date) {
  105. return format(date, CRON_FORMAT);
  106. }
  107. /**
  108. * 格式化日期,返回格式为 yyyy-MM
  109. *
  110. * @param date 日期
  111. * @return 格式化后的字符串
  112. */
  113. public static String format(LocalDateTime date, String pattern) {
  114. if (date == null) {
  115. date = LocalDateTime.now();
  116. }
  117. if (pattern == null) {
  118. pattern = DEFAULT_MONTH_FORMAT;
  119. }
  120. return date.format(DateTimeFormatter.ofPattern(pattern));
  121. }
  122. public static String format(LocalDate date, String pattern) {
  123. if (date == null) {
  124. date = LocalDate.now();
  125. }
  126. if (pattern == null) {
  127. pattern = DEFAULT_MONTH_FORMAT;
  128. }
  129. return date.format(DateTimeFormatter.ofPattern(pattern));
  130. }
  131. /**
  132. * 根据传入的格式格式化日期.默认格式为MM月dd日
  133. *
  134. * @param d 日期
  135. * @param f 格式
  136. * @return 格式化后的字符串
  137. */
  138. public static String format(Date d, String f) {
  139. Date date = d;
  140. String format = f;
  141. if (date == null) {
  142. date = new Date();
  143. }
  144. if (format == null) {
  145. format = DEFAULT_DATE_TIME_FORMAT;
  146. }
  147. SimpleDateFormat df = new SimpleDateFormat(format);
  148. return df.format(date);
  149. }
  150. /**
  151. * 格式化日期,返回格式为 yyyy-MM-dd
  152. *
  153. * @param date 日期
  154. * @return 格式化后的字符串
  155. */
  156. public static String formatAsDate(LocalDateTime date) {
  157. return format(date, DEFAULT_DATE_FORMAT);
  158. }
  159. public static String formatAsDate(LocalDate date) {
  160. return format(date, DEFAULT_DATE_FORMAT);
  161. }
  162. public static String formatAsDateEn(LocalDateTime date) {
  163. return format(date, DEFAULT_DATE_FORMAT_EN);
  164. }
  165. public static String formatAsYearMonth(LocalDateTime date) {
  166. return format(date, DEFAULT_MONTH_FORMAT);
  167. }
  168. public static String formatAsYearMonthEn(LocalDateTime date) {
  169. return format(date, DEFAULT_MONTH_FORMAT_EN);
  170. }
  171. /**
  172. * 格式化日期,返回格式为 yyyy-ww
  173. *
  174. * @param date 日期
  175. * @return 格式化后的字符串
  176. */
  177. public static String formatAsYearWeek(LocalDateTime date) {
  178. return format(date, DEFAULT_WEEK_FORMAT);
  179. }
  180. public static String formatAsYearWeekEn(LocalDateTime date) {
  181. return format(date, DEFAULT_WEEK_FORMAT_EN);
  182. }
  183. /**
  184. * 格式化日期,返回格式为 yyyy-MM
  185. *
  186. * @param date 日期
  187. * @return 格式化后的字符串
  188. */
  189. public static String formatAsYearMonth(Date date) {
  190. SimpleDateFormat df = new SimpleDateFormat(DEFAULT_MONTH_FORMAT);
  191. return df.format(date);
  192. }
  193. /**
  194. * 格式化日期,返回格式为 yyyy-ww
  195. *
  196. * @param date 日期
  197. * @return 格式化后的字符串
  198. */
  199. public static String formatAsYearWeek(Date date) {
  200. SimpleDateFormat df = new SimpleDateFormat(DEFAULT_WEEK_FORMAT);
  201. return df.format(date);
  202. }
  203. /**
  204. * 格式化日期,返回格式为 HH:mm:ss 例:12:24:24
  205. *
  206. * @param date 日期
  207. * @return 格式化后的字符串
  208. */
  209. public static String formatAsTime(Date date) {
  210. SimpleDateFormat df = new SimpleDateFormat(DEFAULT_TIME_FORMAT);
  211. return df.format(date);
  212. }
  213. /**
  214. * 格式化日期,返回格式为 yyyy-MM-dd
  215. *
  216. * @param date 日期
  217. * @return 格式化后的字符串
  218. */
  219. public static String formatAsDate(Date date) {
  220. SimpleDateFormat df = new SimpleDateFormat(DEFAULT_DATE_FORMAT);
  221. return df.format(date);
  222. }
  223. /**
  224. * 格式化日期,返回格式为 yyyy-MM-dd HH:mm:ss
  225. *
  226. * @param date 日期
  227. * @return 格式化后的字符串
  228. */
  229. public static String formatAsDateTime(Date date) {
  230. SimpleDateFormat df = new SimpleDateFormat(DEFAULT_DATE_TIME_FORMAT);
  231. return df.format(date);
  232. }
  233. /**
  234. * 格式化日期,返回格式为 dd ,即对应的天数.
  235. *
  236. * @param date 日期
  237. * @return 格式化后的字符串
  238. */
  239. public static String formatAsDay(Date date) {
  240. SimpleDateFormat df = new SimpleDateFormat("dd");
  241. return df.format(date);
  242. }
  243. //--格式化日期end-----------------------------------------
  244. //--解析日期start-----------------------------------------
  245. /**
  246. * 将字符转换成日期
  247. *
  248. * @param dateStr 日期字符串
  249. * @param format 解析格式
  250. * @return 解析后的日期
  251. */
  252. public static Date parse(String dateStr, String format) {
  253. Date date = null;
  254. SimpleDateFormat dateFormat = new SimpleDateFormat(format);
  255. dateFormat.setLenient(false);
  256. try {
  257. date = dateFormat.parse(dateStr);
  258. } catch (Exception e) {
  259. log.info("DateUtils error", e);
  260. }
  261. return date;
  262. }
  263. /**
  264. * 获取当月最后一天
  265. *
  266. * @param date 日期
  267. * @return 当月最后一天
  268. */
  269. public static Date getLastDateOfMonth(Date date) {
  270. Calendar calendar = Calendar.getInstance();
  271. calendar.setTime(date);
  272. calendar.add(Calendar.MONTH, 1);
  273. calendar.set(Calendar.DAY_OF_MONTH, 0);
  274. return calendar.getTime();
  275. }
  276. /**
  277. * 根据传入的String返回对应的date
  278. *
  279. * @param source 日期字符串
  280. * @return 日期
  281. */
  282. public static Date parseAsDate(String source) {
  283. String sourceTrim = source.trim();
  284. Set<Map.Entry<String, String>> entries = DATE_FORMAT.entrySet();
  285. try {
  286. for (Map.Entry<String, String> entry : entries) {
  287. if (sourceTrim.matches(entry.getValue())) {
  288. return new SimpleDateFormat(entry.getKey()).parse(source);
  289. }
  290. }
  291. } catch (ParseException e) {
  292. throw BizException.wrap("解析日期失败, 请传递正确的日期格式");
  293. }
  294. throw BizException.wrap("解析日期失败, 请传递正确的日期格式");
  295. }
  296. /**
  297. * 按给定参数返回Date对象
  298. *
  299. * @param dateTime 时间对象格式为("yyyy-MM-dd HH:mm:ss");
  300. * @return 解析后的日期
  301. */
  302. public static Date parseAsDateTime(String dateTime) {
  303. SimpleDateFormat simpledateformat = new SimpleDateFormat(DEFAULT_DATE_TIME_FORMAT);
  304. try {
  305. return simpledateformat.parse(dateTime);
  306. } catch (ParseException e) {
  307. return null;
  308. }
  309. }
  310. /**
  311. * 获取指定日期的开始时间
  312. * 如:00:00:00
  313. *
  314. * @param value 日期
  315. * @return 解析后的日期
  316. */
  317. public static Date getDate0000(LocalDateTime value) {
  318. return getDate0000(value.toLocalDate());
  319. }
  320. /**
  321. * 获取指定日期的开始时间
  322. * 如:00:00:00
  323. *
  324. * @param value 日期
  325. * @return 解析后的日期
  326. */
  327. public static Date getDate0000(Date value) {
  328. return getDate0000(NdDateUtils.date2LocalDate(value));
  329. }
  330. /**
  331. * 获取指定日期的开始时间
  332. * 如:00:00:00
  333. *
  334. * @param value 日期
  335. * @return 解析后的日期
  336. */
  337. public static Date getDate0000(LocalDate value) {
  338. LocalDateTime todayStart = LocalDateTime.of(value, LocalTime.MIN);
  339. return NdDateUtils.localDateTime2Date(todayStart);
  340. }
  341. /**
  342. * 获取指定日期的结束时间
  343. * 如:23:59:59
  344. *
  345. * @param value 日期
  346. * @return 解析后的日期
  347. */
  348. public static Date getDate2359(LocalDateTime value) {
  349. return getDate2359(value.toLocalDate());
  350. }
  351. /**
  352. * 获取指定日期的结束时间
  353. * 如:23:59:59
  354. *
  355. * @param value 日期
  356. * @return 解析后的日期
  357. */
  358. public static Date getDate2359(Date value) {
  359. return getDate2359(NdDateUtils.date2LocalDate(value));
  360. }
  361. /**
  362. * 获取指定日期的结束时间
  363. * 如:23:59:59
  364. *
  365. * @param value 日期
  366. * @return 解析后的日期
  367. */
  368. public static Date getDate2359(LocalDate value) {
  369. LocalDateTime dateEnd = LocalDateTime.of(value, LocalTime.MAX);
  370. return NdDateUtils.localDateTime2Date(dateEnd);
  371. }
  372. /**
  373. * LocalDateTime转换为Date
  374. *
  375. * @param localDateTime 日期
  376. * @return 解析后的日期
  377. */
  378. public static Date localDateTime2Date(LocalDateTime localDateTime) {
  379. ZoneId zoneId = ZoneId.systemDefault();
  380. ZonedDateTime zdt = localDateTime.atZone(zoneId);
  381. return Date.from(zdt.toInstant());
  382. }
  383. //--解析日期 end-----------------------------------------
  384. /**
  385. * Date转换为LocalDateTime
  386. *
  387. * @param date 日期
  388. */
  389. public static LocalDateTime date2LocalDateTime(Date date) {
  390. if (date == null) {
  391. return LocalDateTime.now();
  392. }
  393. Instant instant = date.toInstant();
  394. ZoneId zoneId = ZoneId.systemDefault();
  395. return instant.atZone(zoneId).toLocalDateTime();
  396. }
  397. /**
  398. * 日期转 LocalDate
  399. *
  400. * @param date 日期
  401. * @return 解析后的日期
  402. */
  403. public static LocalDate date2LocalDate(Date date) {
  404. if (date == null) {
  405. return LocalDate.now();
  406. }
  407. Instant instant = date.toInstant();
  408. ZoneId zoneId = ZoneId.systemDefault();
  409. return instant.atZone(zoneId).toLocalDate();
  410. }
  411. /**
  412. * 日期转 LocalTime
  413. *
  414. * @param date 日期
  415. * @return 解析后的日期
  416. */
  417. public static LocalTime date2LocalTime(Date date) {
  418. if (date == null) {
  419. return LocalTime.now();
  420. }
  421. Instant instant = date.toInstant();
  422. ZoneId zoneId = ZoneId.systemDefault();
  423. return instant.atZone(zoneId).toLocalTime();
  424. }
  425. /**
  426. * 毫秒转日期
  427. *
  428. * @param epochMilli 毫秒
  429. * @return 解析后的日期
  430. */
  431. public static LocalDateTime getDateTimeOfTimestamp(long epochMilli) {
  432. Instant instant = Instant.ofEpochMilli(epochMilli);
  433. return LocalDateTime.ofInstant(instant, ZoneId.systemDefault());
  434. }
  435. /**
  436. * 秒转日期
  437. *
  438. * @param epochSecond 秒
  439. * @return 解析后的日期
  440. */
  441. public static LocalDateTime getDateTimeOfSecond(long epochSecond) {
  442. Instant instant = Instant.ofEpochSecond(epochSecond);
  443. return LocalDateTime.ofInstant(instant, ZoneId.systemDefault());
  444. }
  445. //-计算日期 start------------------------------------------
  446. /**
  447. * 计算结束时间与当前时间间隔的天数
  448. *
  449. * @param endDate 结束日期
  450. * @return 计算结束时间与当前时间间隔的天数
  451. */
  452. public static long until(Date endDate) {
  453. return LocalDateTime.now().until(date2LocalDateTime(endDate), ChronoUnit.DAYS);
  454. }
  455. /**
  456. * 计算结束时间与开始时间间隔的天数
  457. *
  458. * @param startDate 开始日期
  459. * @param endDate 结束日期
  460. * @return 计算结束时间与开始时间间隔的天数
  461. */
  462. public static long until(Date startDate, Date endDate) {
  463. return date2LocalDateTime(startDate).until(date2LocalDateTime(endDate), ChronoUnit.DAYS);
  464. }
  465. /**
  466. * 计算结束时间与开始时间间隔的天数
  467. *
  468. * @param startDate 开始日期
  469. * @param endDate 结束日期
  470. * @return 计算结束时间与开始时间间隔的天数
  471. */
  472. public static long until(LocalDateTime startDate, LocalDateTime endDate) {
  473. return startDate.until(endDate, ChronoUnit.DAYS);
  474. }
  475. public static long until(LocalDate startDate, LocalDate endDate) {
  476. return startDate.until(endDate, ChronoUnit.DAYS);
  477. }
  478. /**
  479. * 计算2个日期之间的所有的日期 yyyy-MM-dd
  480. * 含头含尾
  481. *
  482. * @param start yyyy-MM-dd
  483. * @param end yyyy-MM-dd
  484. * @return 日期区间的所有日期
  485. */
  486. public static List<String> getBetweenDay(Date start, Date end) {
  487. return getBetweenDay(date2LocalDate(start), date2LocalDate(end));
  488. }
  489. /**
  490. * 计算2个日期之间的所有的日期 yyyy-MM-dd
  491. * 含头含尾
  492. *
  493. * @param start yyyy-MM-dd
  494. * @param end yyyy-MM-dd
  495. */
  496. public static List<String> getBetweenDay(String start, String end) {
  497. return getBetweenDay(LocalDate.parse(start), LocalDate.parse(end));
  498. }
  499. /**
  500. * 计算2个日期之间的所有的日期 yyyy-MM-dd
  501. * 含头含尾
  502. *
  503. * @param startDate yyyy-MM-dd
  504. * @param endDate yyyy-MM-dd
  505. */
  506. public static List<String> getBetweenDay(LocalDate startDate, LocalDate endDate) {
  507. return getBetweenDay(startDate, endDate, DEFAULT_DATE_FORMAT);
  508. }
  509. public static List<String> getBetweenDayEn(LocalDate startDate, LocalDate endDate) {
  510. return getBetweenDay(startDate, endDate, DEFAULT_DATE_FORMAT_EN);
  511. }
  512. public static List<String> getBetweenDay(LocalDate startDate, LocalDate endDate, String pattern) {
  513. if (pattern == null) {
  514. pattern = DEFAULT_DATE_FORMAT;
  515. }
  516. List<String> list = new ArrayList<>();
  517. long distance = ChronoUnit.DAYS.between(startDate, endDate);
  518. if (distance < 1) {
  519. return list;
  520. }
  521. String finalPattern = pattern;
  522. Stream.iterate(startDate, d -> d.plusDays(1)).
  523. limit(distance + 1)
  524. .forEach(f -> list.add(f.format(DateTimeFormatter.ofPattern(finalPattern))));
  525. return list;
  526. }
  527. /**
  528. * 计算2个日期之间的所有的周 yyyy-ww
  529. * 含头含尾
  530. *
  531. * @param start yyyy-MM-dd
  532. * @param end yyyy-MM-dd
  533. */
  534. public static List<String> getBetweenWeek(Date start, Date end) {
  535. return getBetweenWeek(date2LocalDate(start), date2LocalDate(end));
  536. }
  537. /**
  538. * 计算2个日期之间的所有的周 yyyy-ww
  539. * 含头含尾
  540. *
  541. * @param start yyyy-MM-dd
  542. * @param end yyyy-MM-dd
  543. * @return 2个日期之间的所有的周
  544. */
  545. public static List<String> getBetweenWeek(String start, String end) {
  546. return getBetweenWeek(LocalDate.parse(start), LocalDate.parse(end));
  547. }
  548. /**
  549. * 计算2个日期之间的所有的周 yyyy-ww
  550. * 含头含尾
  551. *
  552. * @param startDate yyyy-MM-dd
  553. * @param endDate yyyy-MM-dd
  554. * @return 2个日期之间的所有的周
  555. */
  556. public static List<String> getBetweenWeek(LocalDate startDate, LocalDate endDate) {
  557. return getBetweenWeek(startDate, endDate, DEFAULT_WEEK_FORMAT);
  558. }
  559. public static List<String> getBetweenWeek(LocalDate startDate, LocalDate endDate, String pattern) {
  560. List<String> list = new ArrayList<>();
  561. long distance = ChronoUnit.WEEKS.between(startDate, endDate);
  562. if (distance < 1) {
  563. return list;
  564. }
  565. Stream.iterate(startDate, d -> d.plusWeeks(1)).
  566. limit(distance + 1).forEach(f -> list.add(f.format(DateTimeFormatter.ofPattern(pattern))));
  567. return list;
  568. }
  569. /**
  570. * 计算2个日期之间的所有的月 yyyy-MM
  571. *
  572. * @param start yyyy-MM-dd
  573. * @param end yyyy-MM-dd
  574. * @return 2个日期之间的所有的月
  575. */
  576. public static List<String> getBetweenMonth(Date start, Date end) {
  577. return getBetweenMonth(date2LocalDate(start), date2LocalDate(end));
  578. }
  579. /**
  580. * 计算2个日期之间的所有的月 yyyy-MM
  581. *
  582. * @param start yyyy-MM-dd
  583. * @param end yyyy-MM-dd
  584. * @return 2个日期之间的所有的月
  585. */
  586. public static List<String> getBetweenMonth(String start, String end) {
  587. return getBetweenMonth(LocalDate.parse(start), LocalDate.parse(end));
  588. }
  589. /**
  590. * 计算2个日期之间的所有的月 yyyy-MM
  591. *
  592. * @param startDate yyyy-MM-dd
  593. * @param endDate yyyy-MM-dd
  594. * @return 2个日期之间的所有的月
  595. */
  596. public static List<String> getBetweenMonth(LocalDate startDate, LocalDate endDate) {
  597. return getBetweenMonth(startDate, endDate, DEFAULT_MONTH_FORMAT);
  598. }
  599. public static List<String> getBetweenMonth(LocalDate startDate, LocalDate endDate, String pattern) {
  600. List<String> list = new ArrayList<>();
  601. long distance = ChronoUnit.MONTHS.between(startDate, endDate);
  602. if (distance < 1) {
  603. return list;
  604. }
  605. Stream.iterate(startDate, d -> d.plusMonths(1))
  606. .limit(distance + 1)
  607. .forEach(f -> list.add(f.format(DateTimeFormatter.ofPattern(pattern))));
  608. return list;
  609. }
  610. /**
  611. * 计算时间区间内的日期列表,并返回
  612. *
  613. * @param startTime 开始
  614. * @param endTime 结束
  615. * @param dateList 日期
  616. * @return 计算时间区间内的日期列表
  617. */
  618. public static String calculationEn(LocalDateTime startTime, LocalDateTime endTime, List<String> dateList) {
  619. if (startTime == null) {
  620. startTime = LocalDateTime.now();
  621. }
  622. if (endTime == null) {
  623. endTime = LocalDateTime.now().plusDays(30);
  624. }
  625. return calculationEn(startTime.toLocalDate(), endTime.toLocalDate(), dateList);
  626. }
  627. public static String calculation(LocalDate startDate, LocalDate endDate, List<String> dateList) {
  628. if (startDate == null) {
  629. startDate = LocalDate.now();
  630. }
  631. if (endDate == null) {
  632. endDate = LocalDate.now().plusDays(30);
  633. }
  634. if (dateList == null) {
  635. dateList = new ArrayList<>();
  636. }
  637. long day = until(startDate, endDate);
  638. String dateType;
  639. if (day >= 0 && day <= MAX_MONTH_DAY) {
  640. dateType = DAY;
  641. dateList.addAll(NdDateUtils.getBetweenDay(startDate, endDate, DEFAULT_DATE_FORMAT));
  642. } else if (day > MAX_MONTH_DAY && day <= MAX_3_MONTH_DAY) {
  643. dateType = WEEK;
  644. dateList.addAll(NdDateUtils.getBetweenWeek(startDate, endDate, DEFAULT_WEEK_FORMAT));
  645. } else if (day > MAX_3_MONTH_DAY && day <= MAX_YEAR_DAY) {
  646. dateType = MONTH;
  647. dateList.addAll(NdDateUtils.getBetweenMonth(startDate, endDate, DEFAULT_MONTH_FORMAT));
  648. } else {
  649. throw new BizException("日期参数只能介于0-365天之间");
  650. }
  651. return dateType;
  652. }
  653. public static String calculationEn(LocalDate startDate, LocalDate endDate, List<String> dateList) {
  654. if (startDate == null) {
  655. startDate = LocalDate.now();
  656. }
  657. if (endDate == null) {
  658. endDate = LocalDate.now().plusDays(30);
  659. }
  660. if (dateList == null) {
  661. dateList = new ArrayList<>();
  662. }
  663. long day = until(startDate, endDate);
  664. String dateType;
  665. if (day >= 0 && day <= MAX_MONTH_DAY) {
  666. dateType = DAY;
  667. dateList.addAll(NdDateUtils.getBetweenDay(startDate, endDate, DEFAULT_DATE_FORMAT_EN));
  668. } else if (day > MAX_MONTH_DAY && day <= MAX_3_MONTH_DAY) {
  669. dateType = WEEK;
  670. dateList.addAll(NdDateUtils.getBetweenWeek(startDate, endDate, DEFAULT_WEEK_FORMAT_EN));
  671. } else if (day > MAX_3_MONTH_DAY && day <= MAX_YEAR_DAY) {
  672. dateType = MONTH;
  673. dateList.addAll(NdDateUtils.getBetweenMonth(startDate, endDate, DEFAULT_MONTH_FORMAT_EN));
  674. } else {
  675. throw new BizException("日期参数只能介于0-365天之间");
  676. }
  677. return dateType;
  678. }
  679. //----------//----------//----------//----------//----------//----------//----------//----------//----------//----------//----------
  680. /**
  681. * 计算开始时间
  682. *
  683. * @param time 日期
  684. * @return 计算开始时间
  685. */
  686. public static LocalDateTime getStartTime(String time) {
  687. String startTime = time;
  688. if (time.matches("^\\d{4}-\\d{1,2}$")) {
  689. startTime = time + "-01 00:00:00";
  690. } else if (time.matches("^\\d{4}-\\d{1,2}-\\d{1,2}$")) {
  691. startTime = time + " 00:00:00";
  692. } else if (time.matches("^\\d{4}-\\d{1,2}-\\d{1,2} \\d{1,2}:\\d{1,2}$")) {
  693. startTime = time + ":00";
  694. } else if (time.matches("^\\d{4}-\\d{1,2}-\\d{1,2}T\\d{1,2}:\\d{1,2}:\\d{1,2}.\\d{3}Z$")) {
  695. startTime = time.replace("T", " ").substring(0, time.indexOf('.'));
  696. }
  697. return LocalDateTimeUtil.beginOfDay(LocalDateTime.parse(startTime, DateTimeFormatter.ofPattern(DEFAULT_DATE_TIME_FORMAT)));
  698. }
  699. /**
  700. * 计算结束时间
  701. *
  702. * @param time 日期
  703. * @return 结束时间 精确到毫秒
  704. */
  705. public static LocalDateTime getEndTime(String time) {
  706. String startTime = time;
  707. if (time.matches("^\\d{4}-\\d{1,2}$")) {
  708. Date date = NdDateUtils.parse(time, "yyyy-MM");
  709. date = NdDateUtils.getLastDateOfMonth(date);
  710. startTime = NdDateUtils.formatAsDate(date) + " 23:59:59";
  711. } else if (time.matches("^\\d{4}-\\d{1,2}-\\d{1,2}$")) {
  712. startTime = time + " 23:59:59";
  713. } else if (time.matches("^\\d{4}-\\d{1,2}-\\d{1,2} \\d{1,2}:\\d{1,2}$")) {
  714. startTime = time + ":59";
  715. } else if (time.matches("^\\d{4}-\\d{1,2}-\\d{1,2}T\\d{1,2}:\\d{1,2}:\\d{1,2}.\\d{3}Z$")) {
  716. time = time.replace("T", " ").substring(0, time.indexOf('.'));
  717. startTime = time;
  718. }
  719. return endOfDay(LocalDateTime.parse(startTime, DateTimeFormatter.ofPattern(DEFAULT_DATE_TIME_FORMAT)));
  720. }
  721. public static LocalDateTime endOfDay(LocalDateTime time) {
  722. return time.with(LocalTime.of(23, 59, 59, 999_999_000));
  723. }
  724. /**
  725. * 判断当前时间是否在指定时间范围
  726. *
  727. * @param from 开始时间
  728. * @param to 结束时间
  729. * @return 结果
  730. */
  731. public static boolean between(LocalTime from, LocalTime to) {
  732. if (from == null) {
  733. throw new IllegalArgumentException("开始时间不能为空");
  734. }
  735. if (to == null) {
  736. throw new IllegalArgumentException("结束时间不能为空");
  737. }
  738. LocalTime now = LocalTime.now();
  739. return now.isAfter(from) && now.isBefore(to);
  740. }
  741. /**
  742. * 转换日期
  743. * <p>
  744. * 0: 今天结束的日期
  745. * 1m: 1分钟后的日期
  746. * 1h: 1小时后的日期
  747. * 4d: 4天后的日期
  748. * 2w: 2周后的日期
  749. * 3M: 3个月后的日期
  750. * 5y: 5年后的日期
  751. *
  752. * @param dateTime 待转换日期
  753. * @param time 转换格式 如:
  754. * 0 当天23:59:59
  755. * 1s 1秒后
  756. * 3m 3分钟后
  757. * 2w 2周后
  758. * 1h 1小时后
  759. * 2H 2小时后
  760. * 4d 4天后
  761. * 5M 5月后
  762. * 6y 6年后
  763. * @return 日期
  764. */
  765. public static LocalDateTime conversionDateTime(LocalDateTime dateTime, String time) {
  766. if (StrUtil.isEmpty(time)) {
  767. return LocalDateTime.MAX;
  768. }
  769. if (dateTime == null) {
  770. return endOfDay(LocalDateTime.now());
  771. }
  772. // 今天的23:59:59
  773. if (StrPool.ZERO.equals(time)) {
  774. return endOfDay(dateTime);
  775. }
  776. char unit = Character.toLowerCase(time.charAt(time.length() - 1));
  777. if (time.length() == 1) {
  778. unit = 'd';
  779. }
  780. Long lastTime = Convert.toLong(time.substring(0, time.length() - 1));
  781. switch (unit) {
  782. //秒
  783. case 's':
  784. return dateTime.plusSeconds(lastTime);
  785. //分
  786. case 'm':
  787. return dateTime.plusMinutes(lastTime);
  788. //时
  789. case 'h' | 'H':
  790. return dateTime.plusHours(lastTime);
  791. //周
  792. case 'w':
  793. return dateTime.plusWeeks(lastTime);
  794. //月
  795. case 'M':
  796. return dateTime.plusMonths(lastTime);
  797. //年
  798. case 'y':
  799. return dateTime.plusYears(lastTime);
  800. //天
  801. case 'd':
  802. default:
  803. return dateTime.plusDays(lastTime);
  804. }
  805. }
  806. }