001/**
002 * Copyright (c) 2015-2022, Michael Yang 杨福海 (fuhai999@gmail.com).
003 * <p>
004 * Licensed under the Apache License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 * <p>
008 * http://www.apache.org/licenses/LICENSE-2.0
009 * <p>
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 */
016package io.jboot.utils;
017
018import com.jfinal.kit.SyncWriteMap;
019
020import java.sql.Timestamp;
021import java.text.ParseException;
022import java.text.SimpleDateFormat;
023import java.time.*;
024import java.time.format.DateTimeFormatter;
025import java.util.*;
026
027/**
028 * @author michael yang (fuhai999@gmail.com)
029 */
030public class DateUtil {
031
032    public static String datePatternWithoutDividing = "yyyyMMdd";
033    public static String datePattern = "yyyy-MM-dd";
034    public static final String dateMinutePattern = "yyyy-MM-dd HH:mm";
035    public static final String dateMinutePattern2 = "yyyy-MM-dd'T'HH:mm";
036    public static String datetimePattern = "yyyy-MM-dd HH:mm:ss";
037    public static final String dateMillisecondPattern = "yyyy-MM-dd HH:mm:ss SSS";
038    public static final String dateCSTPattern = "EEE MMM dd HH:mm:ss zzz yyyy";
039
040    public static String dateChinesePattern = "yyyy年MM月dd日";
041    public static String datetimeChinesePattern = "yyyy年MM月dd日 HH时mm分ss秒";
042
043    private static final String[] WEEKS = {"星期日", "星期一", "星期二", "星期三", "星期四", "星期五", "星期六"};
044
045    private static final ThreadLocal<HashMap<String, SimpleDateFormat>> TL = ThreadLocal.withInitial(() -> new HashMap<>());
046
047    private static final Map<String, DateTimeFormatter> dateTimeFormatters = new SyncWriteMap<>();
048
049    public static DateTimeFormatter getDateTimeFormatter(String pattern) {
050        DateTimeFormatter ret = dateTimeFormatters.get(pattern);
051        if (ret == null) {
052            ret = DateTimeFormatter.ofPattern(pattern);
053            dateTimeFormatters.put(pattern, ret);
054        }
055        return ret;
056    }
057
058    public static SimpleDateFormat getSimpleDateFormat(String pattern) {
059        SimpleDateFormat ret = TL.get().get(pattern);
060        if (ret == null) {
061            if (dateCSTPattern.equals(pattern)) {
062                ret = new SimpleDateFormat(dateCSTPattern, Locale.US);
063            } else {
064                ret = new SimpleDateFormat(pattern);
065            }
066            TL.get().put(pattern, ret);
067        }
068        return ret;
069    }
070
071
072    public static String toDateString(Date date) {
073        return toString(date, datePattern);
074    }
075
076
077    public static String toDateMinuteString(Date date) {
078        return toString(date, dateMinutePattern);
079    }
080
081    public static String toDateTimeString(Date date) {
082        return toString(date, datetimePattern);
083    }
084
085
086    public static String toDateMillisecondString(Date date) {
087        return toString(date, dateMillisecondPattern);
088    }
089
090
091    public static String toString(Date date, String pattern) {
092        return date == null ? null : getSimpleDateFormat(pattern).format(date);
093    }
094
095
096    public static String toString(LocalDateTime localDateTime, String pattern) {
097        return localDateTime.format(getDateTimeFormatter(pattern));
098    }
099
100    public static String toString(LocalDate localDate, String pattern) {
101        return localDate.format(getDateTimeFormatter(pattern));
102    }
103
104    public static String toString(LocalTime localTime, String pattern) {
105        return localTime.format(getDateTimeFormatter(pattern));
106    }
107
108
109    public static Date parseDate(Object value) {
110        if (value instanceof Number) {
111            return new Date(((Number) value).longValue());
112        }
113        if (value instanceof Timestamp) {
114            return new Date(((Timestamp) value).getTime());
115        }
116        if (value instanceof LocalDate) {
117            return DateUtil.toDate((LocalDate) value);
118        }
119        if (value instanceof LocalDateTime) {
120            return DateUtil.toDate((LocalDateTime) value);
121        }
122        if (value instanceof LocalTime) {
123            return DateUtil.toDate((LocalTime) value);
124        }
125        String s = value.toString();
126        if (StrUtil.isNumeric(s)) {
127            return new Date(Long.parseLong(s));
128        }
129        return DateUtil.parseDate(s);
130    }
131
132
133    public static Date parseDate(String dateString) {
134        if (StrUtil.isBlank(dateString)) {
135            return null;
136        }
137        dateString = dateString.trim();
138        try {
139            SimpleDateFormat sdf = getSimpleDateFormat(getPattern(dateString));
140            try {
141                return sdf.parse(dateString);
142            } catch (ParseException ex) {
143                //2022-10-23 00:00:00.0
144                int lastIndexOf = dateString.lastIndexOf(".");
145                if (lastIndexOf == 19) {
146                    return parseDate(dateString.substring(0, lastIndexOf));
147                }
148
149                //2022-10-23 00:00:00,0
150                lastIndexOf = dateString.lastIndexOf(",");
151                if (lastIndexOf == 19) {
152                    return parseDate(dateString.substring(0, lastIndexOf));
153                }
154
155                //2022-10-23 00:00:00 000123
156                lastIndexOf = dateString.lastIndexOf(" ");
157                if (lastIndexOf == 19) {
158                    return parseDate(dateString.substring(0, lastIndexOf));
159                }
160
161                if (dateString.contains(".") || dateString.contains("/")) {
162                    dateString = dateString.replace(".", "-").replace("/", "-");
163                    return sdf.parse(dateString);
164                } else {
165                    throw ex;
166                }
167            }
168        } catch (ParseException ex) {
169            throw new IllegalArgumentException("The date format is not supported for the date string: " + dateString);
170        }
171    }
172
173
174    private static String getPattern(String dateString) {
175        int length = dateString.length();
176        if (length == datetimePattern.length()) {
177            return datetimePattern;
178        } else if (length == datePattern.length()) {
179            return datePattern;
180        } else if (length == dateMinutePattern.length()) {
181            if (dateString.contains("T")) {
182                return dateMinutePattern2;
183            }
184            return dateMinutePattern;
185        } else if (length == dateMillisecondPattern.length()) {
186            return dateMillisecondPattern;
187        } else if (length == datePatternWithoutDividing.length()) {
188            return datePatternWithoutDividing;
189        } else if (length == dateCSTPattern.length()) {
190            return dateCSTPattern;
191        } else {
192            throw new IllegalArgumentException("The date format is not supported for the date string: " + dateString);
193        }
194    }
195
196
197    public static Date parseDate(String dateString, String pattern) {
198        if (StrUtil.isBlank(dateString)) {
199            return null;
200        }
201        try {
202            return getSimpleDateFormat(pattern).parse(dateString.trim());
203        } catch (ParseException e) {
204            throw new IllegalArgumentException("The date format is not supported for the date string: " + dateString);
205        }
206    }
207
208
209    public static LocalDateTime parseLocalDateTime(String localDateTimeString, String pattern) {
210        return LocalDateTime.parse(localDateTimeString, getDateTimeFormatter(pattern));
211    }
212
213    public static LocalDate parseLocalDate(String localDateString, String pattern) {
214        return LocalDate.parse(localDateString, getDateTimeFormatter(pattern));
215    }
216
217
218    public static LocalTime parseLocalTime(String localTimeString, String pattern) {
219        return LocalTime.parse(localTimeString, getDateTimeFormatter(pattern));
220    }
221
222
223    /**
224     * java.util.Date --> java.time.LocalDateTime
225     */
226    public static LocalDateTime toLocalDateTime(Date date) {
227        if (date == null) {
228            return null;
229        }
230        // java.sql.Date 不支持 toInstant(),需要先转换成 java.util.Date
231        if (date instanceof java.sql.Date) {
232            date = new Date(date.getTime());
233        }
234
235        Instant instant = date.toInstant();
236        ZoneId zone = ZoneId.systemDefault();
237        return LocalDateTime.ofInstant(instant, zone);
238    }
239
240    /**
241     * java.util.Date --> java.time.LocalDate
242     */
243    public static LocalDate toLocalDate(Date date) {
244        if (date == null) {
245            return null;
246        }
247        // java.sql.Date 不支持 toInstant(),需要先转换成 java.util.Date
248        if (date instanceof java.sql.Date) {
249            date = new Date(date.getTime());
250        }
251
252        Instant instant = date.toInstant();
253        ZoneId zone = ZoneId.systemDefault();
254        LocalDateTime localDateTime = LocalDateTime.ofInstant(instant, zone);
255        return localDateTime.toLocalDate();
256    }
257
258    /**
259     * java.util.Date --> java.time.LocalTime
260     */
261    public static LocalTime toLocalTime(Date date) {
262        if (date == null) {
263            return null;
264        }
265        // java.sql.Date 不支持 toInstant(),需要先转换成 java.util.Date
266        if (date instanceof java.sql.Date) {
267            date = new Date(date.getTime());
268        }
269
270        Instant instant = date.toInstant();
271        ZoneId zone = ZoneId.systemDefault();
272        LocalDateTime localDateTime = LocalDateTime.ofInstant(instant, zone);
273        return localDateTime.toLocalTime();
274    }
275
276    /**
277     * java.time.LocalDateTime --> java.util.Date
278     */
279    public static Date toDate(LocalDateTime localDateTime) {
280        if (localDateTime == null) {
281            return null;
282        }
283        ZoneId zone = ZoneId.systemDefault();
284        Instant instant = localDateTime.atZone(zone).toInstant();
285        return Date.from(instant);
286    }
287
288    /**
289     * java.time.LocalDate --> java.util.Date
290     */
291    public static Date toDate(LocalDate localDate) {
292        if (localDate == null) {
293            return null;
294        }
295        ZoneId zone = ZoneId.systemDefault();
296        Instant instant = localDate.atStartOfDay().atZone(zone).toInstant();
297        return Date.from(instant);
298    }
299
300    /**
301     * java.time.LocalTime --> java.util.Date
302     */
303    public static Date toDate(LocalTime localTime) {
304        if (localTime == null) {
305            return null;
306        }
307        LocalDate localDate = LocalDate.now();
308        LocalDateTime localDateTime = LocalDateTime.of(localDate, localTime);
309        ZoneId zone = ZoneId.systemDefault();
310        Instant instant = localDateTime.atZone(zone).toInstant();
311        return Date.from(instant);
312    }
313
314    /**
315     * java.time.LocalTime --> java.util.Date
316     */
317    public static Date toDate(LocalDate localDate, LocalTime localTime) {
318        if (localDate == null) {
319            return null;
320        }
321
322        if (localTime == null) {
323            localTime = LocalTime.of(0, 0, 0);
324        }
325
326        LocalDateTime localDateTime = LocalDateTime.of(localDate, localTime);
327        ZoneId zone = ZoneId.systemDefault();
328        Instant instant = localDateTime.atZone(zone).toInstant();
329        return Date.from(instant);
330    }
331
332
333    /**
334     * 任意一天的开始时间
335     *
336     * @return date
337     */
338    public static Date getStartOfDay(Date date) {
339        Calendar calendar = Calendar.getInstance();
340        calendar.setTime(date);
341        calendar.set(Calendar.HOUR_OF_DAY, 0);
342        calendar.set(Calendar.MINUTE, 0);
343        calendar.set(Calendar.SECOND, 0);
344        calendar.set(Calendar.MILLISECOND, 0);
345        return calendar.getTime();
346    }
347
348    /**
349     * 任意一天的结束时间
350     *
351     * @return date
352     */
353    public static Date getEndOfDay(Date date) {
354        Calendar calendar = Calendar.getInstance();
355        calendar.setTime(date);
356        calendar.set(Calendar.HOUR_OF_DAY, 24);
357        calendar.set(Calendar.MINUTE, 0);
358        calendar.set(Calendar.SECOND, 0);
359        calendar.set(Calendar.MILLISECOND, 0);
360        return calendar.getTime();
361    }
362
363
364    /**
365     * 获取今天的开始时间
366     *
367     * @return
368     */
369    public static Date getStartOfToday() {
370        Calendar cal = Calendar.getInstance();
371        cal.set(Calendar.HOUR_OF_DAY, 0);
372        cal.set(Calendar.SECOND, 0);
373        cal.set(Calendar.MINUTE, 0);
374        cal.set(Calendar.MILLISECOND, 0);
375        return cal.getTime();
376    }
377
378
379    /**
380     * 获取昨天的开始时间
381     *
382     * @return
383     */
384    public static Date getStartOfYesterday() {
385        Calendar cal = Calendar.getInstance();
386        cal.setTimeInMillis(getStartOfToday().getTime() - 3600L * 24 * 1000);
387        return cal.getTime();
388    }
389
390
391    /**
392     * 获取最近 7 天的开始时间
393     *
394     * @return
395     */
396    public static Date getStartOfNearest7Days() {
397        return getStartOfNearestDays(7);
398    }
399
400
401    /**
402     * 获取最近 N 天的开始时间
403     *
404     * @param days
405     * @return
406     */
407    public static Date getStartOfNearestDays(int days) {
408        Calendar cal = Calendar.getInstance();
409        cal.setTimeInMillis(getStartOfToday().getTime() - 3600L * 24 * 1000 * days);
410        return cal.getTime();
411    }
412
413
414    /**
415     * 获取今天的结束数据
416     *
417     * @return
418     */
419    public static Date getEndOfToday() {
420        Calendar cal = Calendar.getInstance();
421        cal.set(Calendar.HOUR_OF_DAY, 24);
422        cal.set(Calendar.SECOND, 0);
423        cal.set(Calendar.MINUTE, 0);
424        cal.set(Calendar.MILLISECOND, 0);
425        return cal.getTime();
426    }
427
428
429    /**
430     * 获取 本周 的开始时间
431     *
432     * @return
433     */
434    public static Date getStartOfThisWeek() {
435        Calendar cal = Calendar.getInstance();
436        cal.setFirstDayOfWeek(Calendar.MONDAY);
437        cal.set(cal.get(Calendar.YEAR), cal.get(Calendar.MONDAY), cal.get(Calendar.DAY_OF_MONTH), 0, 0, 0);
438        cal.set(Calendar.DAY_OF_WEEK, Calendar.MONDAY);
439        return cal.getTime();
440    }
441
442    /**
443     * 获取 本周 的结束时间
444     *
445     * @return
446     */
447    public static Date getEndOfThisWeek() {
448        Calendar cal = Calendar.getInstance();
449        cal.setFirstDayOfWeek(Calendar.MONDAY);
450        cal.setTime(getStartOfThisWeek());
451        cal.add(Calendar.DAY_OF_WEEK, 7);
452        return cal.getTime();
453    }
454
455
456    /**
457     * 获取 本月 的开始时间
458     *
459     * @return
460     */
461    public static Date getStartOfThisMonth() {
462        Calendar cal = Calendar.getInstance();
463        cal.set(cal.get(Calendar.YEAR), cal.get(Calendar.MONDAY), cal.get(Calendar.DAY_OF_MONTH), 0, 0, 0);
464        cal.set(Calendar.DAY_OF_MONTH, cal.getActualMinimum(Calendar.DAY_OF_MONTH));
465        return cal.getTime();
466    }
467
468    /**
469     * 获取 本月 的结束时间
470     *
471     * @return
472     */
473    public static Date getEndOfThisMonth() {
474        Calendar cal = Calendar.getInstance();
475        cal.set(cal.get(Calendar.YEAR), cal.get(Calendar.MONDAY), cal.get(Calendar.DAY_OF_MONTH), 0, 0, 0);
476        cal.set(Calendar.DAY_OF_MONTH, cal.getActualMaximum(Calendar.DAY_OF_MONTH));
477        cal.set(Calendar.HOUR_OF_DAY, 24);
478        return cal.getTime();
479    }
480
481
482    /**
483     * 获取上个月的开始时间
484     *
485     * @return
486     */
487    public static Date getStartOfLastMonth() {
488        Calendar cal = Calendar.getInstance();
489        cal.setTime(getStartOfThisMonth());
490        cal.add(Calendar.MONTH, -1);
491        return cal.getTime();
492    }
493
494
495    /**
496     * 获取 本季度 的开始时间
497     *
498     * @return
499     */
500    public static Date getStartOfThisQuarter() {
501        Calendar cal = Calendar.getInstance();
502        int currentMonth = cal.get(Calendar.MONTH) + 1;
503        if (currentMonth <= 3) {
504            cal.set(Calendar.MONTH, 0);
505        } else if (currentMonth <= 6) {
506            cal.set(Calendar.MONTH, 3);
507        } else if (currentMonth <= 9) {
508            cal.set(Calendar.MONTH, 6);
509        } else if (currentMonth <= 12) {
510            cal.set(Calendar.MONTH, 9);
511        }
512        cal.set(Calendar.DATE, 0);
513
514        cal.set(Calendar.HOUR_OF_DAY, 24);
515        cal.set(Calendar.SECOND, 0);
516        cal.set(Calendar.MINUTE, 0);
517        cal.set(Calendar.MILLISECOND, 0);
518
519        return cal.getTime();
520    }
521
522
523    /**
524     * 获取 本季度的 结束时间
525     *
526     * @return
527     */
528    public static Date getEndOfThisQuarter() {
529        Calendar cal = Calendar.getInstance();
530        cal.setTime(getStartOfThisQuarter());
531        cal.add(Calendar.MONTH, 3);
532        return cal.getTime();
533    }
534
535
536    /**
537     * 获取 季度 的开始时间
538     *
539     * @param quarterNumber
540     * @return
541     */
542    public static Date getStartOfQuarter(int quarterNumber) {
543        if (quarterNumber < 1 || quarterNumber > 4) {
544            throw new IllegalArgumentException("quarterNumber must equals 1,2,3,4");
545        }
546        Calendar cal = Calendar.getInstance();
547        if (quarterNumber == 1) {
548            cal.set(Calendar.MONTH, 0);
549        } else if (quarterNumber == 2) {
550            cal.set(Calendar.MONTH, 3);
551        } else if (quarterNumber == 3) {
552            cal.set(Calendar.MONTH, 6);
553        } else {
554            cal.set(Calendar.MONTH, 9);
555        }
556
557        cal.set(Calendar.DATE, 0);
558        cal.set(Calendar.HOUR_OF_DAY, 24);
559        cal.set(Calendar.SECOND, 0);
560        cal.set(Calendar.MINUTE, 0);
561        cal.set(Calendar.MILLISECOND, 0);
562
563        return cal.getTime();
564    }
565
566
567    /**
568     * 获取 季度 的结束时间
569     *
570     * @param quarterNumber
571     * @return
572     */
573    public static Date getEndOfQuarter(int quarterNumber) {
574        Calendar cal = Calendar.getInstance();
575        cal.setTime(getStartOfQuarter(quarterNumber));
576        cal.add(Calendar.MONTH, 3);
577        return cal.getTime();
578    }
579
580
581    /**
582     * 获取 今年 的开始时间
583     *
584     * @return
585     */
586    public static Date getStartOfThisYear() {
587        Calendar cal = Calendar.getInstance();
588        cal.setTime(new Date());
589        cal.set(cal.get(Calendar.YEAR), 0, 1, 0, 0, 0);
590        return cal.getTime();
591    }
592
593
594    /**
595     * 获取 今年 的结束时间
596     *
597     * @return
598     */
599    public static Date getEndOfThisYear() {
600        Calendar cal = Calendar.getInstance();
601        cal.setTime(getStartOfThisYear());
602        cal.add(Calendar.YEAR, 1);
603        return cal.getTime();
604    }
605
606
607    /**
608     * 获取 去年的 开始时间
609     *
610     * @return
611     */
612    public static Date getStartOfLastYear() {
613        Calendar cal = Calendar.getInstance();
614        cal.setTime(getStartOfThisYear());
615        cal.add(Calendar.YEAR, -1);
616        return cal.getTime();
617    }
618
619    /**
620     * 获取两个时间直接的间隔:单位 秒
621     *
622     * @param date1
623     * @param date2
624     * @return
625     */
626    public static int diffSecond(Date date1, Date date2) {
627        long date1ms = date1.getTime();
628        long date2ms = date2.getTime();
629        return Math.abs((int) ((date1ms - date2ms) / (1000)));
630    }
631
632    /**
633     * 获取两个时间直接的间隔:单位 分钟
634     *
635     * @param date1
636     * @param date2
637     * @return
638     */
639    public static int diffMinute(Date date1, Date date2) {
640        long date1ms = date1.getTime();
641        long date2ms = date2.getTime();
642        return Math.abs((int) ((date1ms - date2ms) / (1000 * 60)));
643    }
644
645
646    /**
647     * 获取两个时间直接的间隔:单位 小时
648     *
649     * @param date1
650     * @param date2
651     * @return
652     */
653    public static int diffHours(Date date1, Date date2) {
654        long date1ms = date1.getTime();
655        long date2ms = date2.getTime();
656        return Math.abs((int) ((date1ms - date2ms) / (1000 * 60 * 60)));
657    }
658
659    /**
660     * 获取两个时间直接的间隔:单位 天
661     *
662     * @param date1
663     * @param date2
664     * @return
665     */
666    public static int diffDays(Date date1, Date date2) {
667        long date1ms = date1.getTime();
668        long date2ms = date2.getTime();
669        return Math.abs((int) ((date1ms - date2ms) / (1000 * 60 * 60 * 24)));
670    }
671
672    /**
673     * 获取两个时间直接的间隔:单位 星期
674     *
675     * @param date1
676     * @param date2
677     * @return
678     */
679    public static int diffWeeks(Date date1, Date date2) {
680        long date1ms = date1.getTime();
681        long date2ms = date2.getTime();
682        return Math.abs((int) ((date1ms - date2ms) / (1000 * 60 * 60 * 24 * 7)));
683    }
684
685    /**
686     * 获取两个时间直接的间隔:单位 月
687     *
688     * @param date1
689     * @param date2
690     * @return
691     */
692    public static int diffMonths(Date date1, Date date2) {
693        int diffYears = diffYears(date1, date2) * 12;
694        int number1 = getMonthNumber(date1);
695        int number2 = getMonthNumber(date2);
696        return Math.abs(diffYears + number1 - number2);
697    }
698
699    /**
700     * 获取两个时间直接的间隔:单位 年
701     *
702     * @param date1
703     * @param date2
704     * @return
705     */
706    public static int diffYears(Date date1, Date date2) {
707        int number1 = getYearNumber(date1);
708        int number2 = getYearNumber(date2);
709        return Math.abs(number1 - number2);
710    }
711
712
713    /**
714     * 获取日期的月份
715     *
716     * @param date
717     * @return
718     */
719    public static int getMonthNumber(Date date) {
720        Calendar cal = Calendar.getInstance();
721        cal.setTime(date);
722        return cal.get(Calendar.MONTH) + 1;
723    }
724
725
726    /**
727     * 获取日期的季度
728     *
729     * @param date
730     * @return
731     */
732    public static int getQuarterNumber(Date date) {
733        int monthNumber = getMonthNumber(date);
734        if (monthNumber >= 1 && monthNumber <= 3) {
735            return 1;
736        } else if (monthNumber >= 4 && monthNumber <= 6) {
737            return 2;
738        } else if (monthNumber >= 7 && monthNumber <= 9) {
739            return 3;
740        } else {
741            return 4;
742        }
743    }
744
745
746    /**
747     * 获取日期的年份
748     *
749     * @param date
750     * @return
751     */
752    public static int getYearNumber(Date date) {
753        Calendar cal = Calendar.getInstance();
754        cal.setTime(date);
755        return cal.get(Calendar.YEAR);
756    }
757
758
759    /**
760     * 获取日期的是当年的第几天
761     *
762     * @param date
763     * @return
764     */
765    public static int getDayOfYearNumber(Date date) {
766        Calendar cal = Calendar.getInstance();
767        cal.setTime(date);
768        return cal.get(Calendar.DAY_OF_YEAR);
769    }
770
771    /**
772     * 获取日期的当月的第几天
773     *
774     * @param date
775     * @return
776     */
777    public static int getDayOfMonthNumber(Date date) {
778        Calendar cal = Calendar.getInstance();
779        cal.setTime(date);
780        return cal.get(Calendar.DAY_OF_MONTH);
781    }
782
783    /**
784     * 获取日期的当星期的第几天
785     *
786     * @param date
787     * @return
788     */
789    public static int getDayOfWeekNumber(Date date) {
790        Calendar cal = Calendar.getInstance();
791        cal.setFirstDayOfWeek(Calendar.MONDAY);
792        cal.setTime(date);
793        return cal.get(Calendar.DAY_OF_WEEK);
794    }
795
796
797    /**
798     * 获取日期的是当年的第个星期
799     *
800     * @param date
801     * @return
802     */
803    public static int getWeekOfYearNumber(Date date) {
804        Calendar cal = Calendar.getInstance();
805        cal.setFirstDayOfWeek(Calendar.MONDAY);
806        cal.setTime(date);
807        return cal.get(Calendar.WEEK_OF_YEAR);
808    }
809
810    /**
811     * 获取日期的当月的第几星期
812     *
813     * @param date
814     * @return
815     */
816    public static int getWeekOfMonthNumber(Date date) {
817        Calendar cal = Calendar.getInstance();
818        cal.setFirstDayOfWeek(Calendar.MONDAY);
819        cal.setTime(date);
820        return cal.get(Calendar.WEEK_OF_MONTH);
821    }
822
823
824    /**
825     * 取得在指定时间上加减seconds天后的时间
826     *
827     * @param date    指定的时间
828     * @param seconds 秒钟,正为加,负为减
829     * @return 在指定时间上加减seconds天后的时间
830     */
831    public static Date addSeconds(Date date, int seconds) {
832        Calendar cal = Calendar.getInstance();
833        cal.setTime(date);
834        cal.add(Calendar.SECOND, seconds);
835        return cal.getTime();
836    }
837
838
839    /**
840     * 取得在指定时间上加减minutes天后的时间
841     *
842     * @param date    指定的时间
843     * @param minutes 分钟,正为加,负为减
844     * @return 在指定时间上加减minutes天后的时间
845     */
846    public static Date addMinutes(Date date, int minutes) {
847        Calendar cal = Calendar.getInstance();
848        cal.setTime(date);
849        cal.add(Calendar.MINUTE, minutes);
850        return cal.getTime();
851    }
852
853    /**
854     * 取得在指定时间上加减hours天后的时间
855     *
856     * @param date  指定的时间
857     * @param hours 小时,正为加,负为减
858     * @return 在指定时间上加减dhours天后的时间
859     */
860    public static Date addHours(Date date, int hours) {
861        Calendar cal = Calendar.getInstance();
862        cal.setTime(date);
863        cal.add(Calendar.HOUR, hours);
864        return cal.getTime();
865    }
866
867    /**
868     * 取得在指定时间上加减days天后的时间
869     *
870     * @param date 指定的时间
871     * @param days 天数,正为加,负为减
872     * @return 在指定时间上加减days天后的时间
873     */
874    public static Date addDays(Date date, int days) {
875        Calendar cal = Calendar.getInstance();
876        cal.setTime(date);
877        cal.add(Calendar.DAY_OF_MONTH, days);
878        return cal.getTime();
879    }
880
881    /**
882     * 取得在指定时间上加减weeks天后的时间
883     *
884     * @param date  指定的时间
885     * @param weeks 星期,正为加,负为减
886     * @return 在指定时间上加减weeks天后的时间
887     */
888    public static Date addWeeks(Date date, int weeks) {
889        Calendar cal = Calendar.getInstance();
890        cal.setTime(date);
891        cal.add(Calendar.WEEK_OF_YEAR, weeks);
892        return cal.getTime();
893    }
894
895    /**
896     * 取得在指定时间上加减months月后的时间
897     *
898     * @param date   指定时间
899     * @param months 月数,正为加,负为减
900     * @return 在指定时间上加减months月后的时间
901     */
902    public static Date addMonths(Date date, int months) {
903        Calendar cal = Calendar.getInstance();
904        cal.setTime(date);
905        cal.add(Calendar.MONTH, months);
906        return cal.getTime();
907    }
908
909    /**
910     * 取得在指定时间上加减years年后的时间
911     *
912     * @param date  指定时间
913     * @param years 年数,正为加,负为减
914     * @return 在指定时间上加减years年后的时间
915     */
916    public static Date addYears(Date date, int years) {
917        Calendar cal = Calendar.getInstance();
918        cal.setTime(date);
919        cal.add(Calendar.YEAR, years);
920        return cal.getTime();
921    }
922
923
924    /**
925     * 判断 A 的时间是否在 B 的时间 "之后"
926     */
927    public static boolean isAfter(Date self, Date other) {
928        return self != null && other != null && self.getTime() > other.getTime();
929    }
930
931    /**
932     * 判断 A 的时间是否在 B 的时间 "之后"
933     */
934    public static boolean isBefore(Date self, Date other) {
935        return self != null && other != null && self.getTime() < other.getTime();
936    }
937
938    /**
939     * 是否是相同的一天
940     */
941    public static boolean isSameDay(Date self, Date other) {
942        return self != null && other != null && getYearNumber(self) == getYearNumber(other)
943                && getDayOfYearNumber(self) == getDayOfYearNumber(other);
944    }
945
946    /**
947     * 是否是相同的星期
948     */
949    public static boolean isSameWeek(Date self, Date other) {
950        return self != null && other != null && getYearNumber(self) == getYearNumber(other)
951                && getWeekOfYearNumber(self) == getWeekOfYearNumber(other);
952    }
953
954    /**
955     * 是否是相同的月份
956     */
957    public static boolean isSameMonth(Date self, Date other) {
958        return self != null && other != null && getYearNumber(self) == getYearNumber(other)
959                && getMonthNumber(self) == getMonthNumber(other);
960    }
961
962    /**
963     * 是否是相同的月份
964     */
965    public static boolean isSameQuarter(Date self, Date other) {
966        return self != null && other != null && getYearNumber(self) == getYearNumber(other)
967                && getQuarterNumber(self) == getQuarterNumber(other);
968    }
969
970    /**
971     * 是否是相同的月份
972     */
973    public static boolean isSameYear(Date self, Date other) {
974        return self != null && other != null && getYearNumber(self) == getYearNumber(other);
975    }
976
977
978    /**
979     * 此日期是否是今天
980     */
981    public static boolean isToday(Date date) {
982        return isSameDay(new Date(), date);
983    }
984
985    /**
986     * 此日期是否是本星期
987     */
988    public static boolean isThisWeek(Date date) {
989        return isSameWeek(new Date(), date);
990    }
991
992    /**
993     * 此日期是否是本月份
994     */
995    public static boolean isThisMonth(Date date) {
996        return isSameMonth(new Date(), date);
997    }
998
999
1000    /**
1001     * 此日期是否是本月份
1002     */
1003    public static boolean isThisQuarter(Date date) {
1004        return isSameQuarter(new Date(), date);
1005    }
1006
1007    /**
1008     * 此日期是否是本年份
1009     */
1010    public static boolean isThisYear(Date date) {
1011        return date != null && getYearNumber(new Date()) == getYearNumber(date);
1012    }
1013
1014    /**
1015     * 判断是否是润年
1016     */
1017    public static boolean isLeapYear(Date date) {
1018        return date != null && new GregorianCalendar().isLeapYear(getYearNumber(date));
1019    }
1020
1021    /**
1022     * 求出指定的时间那天是星期几
1023     */
1024    public static String getWeekDay(Date date) {
1025        return date == null ? null : DateUtil.WEEKS[getDayOfWeekNumber(date) - 1];
1026    }
1027
1028
1029    public static void main(String[] args) {
1030        System.out.println("两天后的开始时间:" + toDateTimeString(getStartOfDay(addDays(new Date(), 2))));
1031        System.out.println("两天后的结束时间:" + toDateTimeString(getEndOfDay(addDays(new Date(), 2))));
1032
1033        System.out.println("CST时间解析:" + toDateTimeString(parseDate("Mon Sep 02 11:23:45 CST 2019")));
1034
1035
1036        System.out.println("当天24点时间:" + toDateTimeString(getEndOfToday()));
1037        System.out.println("当前时间:" + toDateTimeString(new Date()));
1038        System.out.println("当天0点时间:" + toDateTimeString(getStartOfToday()));
1039        System.out.println("昨天0点时间:" + toDateTimeString(getStartOfYesterday()));
1040        System.out.println("近7天时间:" + toDateTimeString(getStartOfNearest7Days()));
1041        System.out.println("本周周一0点时间:" + toDateTimeString(getStartOfThisWeek()));
1042        System.out.println("本周周日24点时间:" + toDateTimeString(getEndOfThisWeek()));
1043        System.out.println("本月初0点时间:" + toDateTimeString(getStartOfThisMonth()));
1044        System.out.println("本月未24点时间:" + toDateTimeString(getEndOfThisMonth()));
1045        System.out.println("上月初0点时间:" + toDateTimeString(getStartOfLastMonth()));
1046        System.out.println("本季度开始点时间:" + toDateTimeString(getStartOfThisQuarter()));
1047        System.out.println("本季度结束点时间:" + toDateTimeString(getEndOfThisQuarter()));
1048        System.out.println("本年开始点时间:" + toDateTimeString(getStartOfThisYear()));
1049        System.out.println("本年结束点时间:" + toDateTimeString(getEndOfThisYear()));
1050        System.out.println("上年开始点时间:" + toDateTimeString(getStartOfLastYear()));
1051        System.out.println("=============");
1052        System.out.println("秒间隔:" + diffSecond(parseDate("2020-02-11 12:21:55"), parseDate("2020-02-11 12:22:58")));
1053        System.out.println("分钟间隔:" + diffMinute(parseDate("2020-02-11 12:21:55"), parseDate("2020-02-11 12:22:01")));
1054        System.out.println("小时间隔:" + diffHours(parseDate("2020-02-11 12:21:55"), parseDate("2020-02-12 12:22:01")));
1055        System.out.println("天间隔:" + diffDays(parseDate("2020-02-11 12:21:55"), parseDate("2020-02-12 12:22:01")));
1056        System.out.println("星期间隔:" + diffWeeks(parseDate("2020-01-11 12:21:55"), parseDate("2020-02-12 12:22:01")));
1057        System.out.println("月间隔:" + diffMonths(parseDate("2019-10-11 12:21:55"), parseDate("2020-09-11 12:21:55")));
1058        System.out.println("年间隔:" + diffYears(parseDate("1990-01-11 12:21:55"), parseDate("2020-02-12 12:22:01")));
1059        System.out.println("当前年份:" + getYearNumber(new Date()));
1060        System.out.println("当前月份:" + getMonthNumber(new Date()));
1061        System.out.println("=============");
1062
1063        System.out.println("新增秒:" + toDateTimeString(addSeconds(parseDate("2020-02-11 12:21:55"), 20)));
1064        System.out.println("新增分钟:" + toDateTimeString(addMinutes(parseDate("2020-02-11 12:21:55"), 20)));
1065        System.out.println("新增小时:" + toDateTimeString(addHours(parseDate("2020-02-11 12:21:55"), 20)));
1066        System.out.println("新增天:" + toDateTimeString(addDays(parseDate("2020-02-11 12:21:55"), 20)));
1067        System.out.println("新增星期:" + toDateTimeString(addWeeks(parseDate("2020-02-11 12:21:55"), 10)));
1068        System.out.println("新增月份:" + toDateTimeString(addMonths(parseDate("2020-02-11 12:21:55"), 20)));
1069        System.out.println("新增年份:" + toDateTimeString(addYears(parseDate("2020-02-11 12:21:55"), 20)));
1070
1071        System.out.println("=============");
1072        System.out.println("今天星期:" + getWeekDay(parseDate("2020-11-24")));
1073        System.out.println("isToday:" + isToday(parseDate("2020-12-01")));
1074        System.out.println("isThisWeek:" + isThisWeek(parseDate("2020-11-24")));
1075        System.out.println("isThisMonth:" + isThisMonth(parseDate("2020-10-02")));
1076        System.out.println("isThisQuarter:" + isThisQuarter(parseDate("2020-10-02")));
1077        System.out.println("isThisYear:" + isThisYear(parseDate("2020-02-02")));
1078        System.out.println("第1季度:" + toDateTimeString(getEndOfQuarter(1)));
1079        System.out.println("第2季度:" + toDateTimeString(getEndOfQuarter(2)));
1080        System.out.println("第3季度:" + toDateTimeString(getEndOfQuarter(3)));
1081        System.out.println("第4季度:" + toDateTimeString(getEndOfQuarter(4)));
1082        System.out.println("本季度:" + toDateTimeString(getStartOfThisQuarter()));
1083        System.out.println("本季度:" + toDateTimeString(getEndOfThisQuarter()));
1084
1085
1086        System.out.println("datetime-local解析:" + parseDate("2022-12-03T16:00"));
1087
1088    }
1089}