Java新日期时间包的使用

Java新日期时间包的使用

参考: unable-to-obtain-localdatetime-from-temporalaccessor-when-parsing-localdatetime


快速开始:

 1@SuppressWarnings("all")
 2public class JTSimpleIntro {
 3    static String DATE_TIME_FORM = "yyyy-MM-dd HH:mm:ss";
 4
 5    static void parseDateTimeString(String yyyyMMdd_HHmmss) {
 6        System.out.println(LocalDateTime.parse(yyyyMMdd_HHmmss));
 7    }
 8
 9    static void parseDateTimeStringWithFormat(String yyyyMMdd_HHmmss) {
10        System.out.println(LocalDateTime
11                .parse(yyyyMMdd_HHmmss,
12                        DateTimeFormatter.ofPattern(DATE_TIME_FORM)));
13    }
14
15    static void parseDateString(String yyyyMMdd) {
16        System.out.println(LocalDate.parse(yyyyMMdd));
17    }
18
19    static void parseTimeString(String HHmmss) {
20        System.out.println(LocalTime.parse(HHmmss));
21    }
22
23    public static void main(String[] args) {
24        parseDateTimeString("2012-06-09T13:12:11");
25        parseDateTimeStringWithFormat("2012-06-09 13:12:11");
26        parseDateString("2012-06-06");
27        parseTimeString("13:12:11");
28    }
29}

以下是API示例:

  1/**
  2 * {@link java.time} 包是jdk8 新增的日期时间包,
  3 * 可以完全替代之前的日期时间系统,包括:
  4 *
  5 * <li>{@link Date}</li>
  6 * <li>{@link java.util.Calendar}</li>
  7 * <li>{@link java.util.TimeZone}</li>
  8 * <li>{@link java.text.DateFormat}</li>
  9 * <li>{@link SimpleDateFormat}</li>
 10 * <p>
 11 * {@link java.time}是全新设计的api,应学习如何使用之。
 12 * <p>
 13 *
 14 * @author wangy
 15 * @date 2021-2-2 9:47
 16 * @see LocalDateTime
 17 */
 18public class JTCommonUsage {
 19    static String yyyy = "yyyy";
 20    static String yyyy_MM = "yyy-MM";
 21    static String yyyy_MM_dd = "yyyy-MM-dd";
 22    static String yyyy_MM_dd_HH_mm_ss = "yyyy-MM-dd HH:mm:ss";
 23    static String yyyy_MM_dd_HH_mm_ss_SSS = "yyyy-MM-dd HH:mm:ss.SSS";
 24
 25    /**
 26     * If the pattern like 'yyyy', result {@link LocalDateTime}
 27     * could be like 'yyyy-01-01 00:00:00'.<br>
 28     * If the pattern like 'yyyy-MM', result {@link LocalDateTime}
 29     * could be like 'yyyy-MM-01 00:00:00'.<br>
 30     * If the pattern like 'yyyy-MM-dd', result {@link LocalDateTime}
 31     * could be like 'yyyy-MM-dd 00:00:00'.<br>
 32     * Other patterns acts the same.
 33     * <p>
 34     *
 35     * <b>Important:</b> the pattern and the the
 36     * {@link LocalDateTime#parse(CharSequence, DateTimeFormatter)}
 37     * method's input
 38     * {@link CharSequence} must match.
 39     * e.g. The following method call will throw
 40     * {@link java.time.format.DateTimeParseException}:
 41     * 
 42     * <pre>
 43     * LocalDateTime localDateTime = LocalDateTime
 44     *         .parse("2021", dtfBuilder("yyyy-MM"));
 45     * </pre>
 46     *
 47     * @param pattern the string pattern
 48     * @see DateTimeFormatter javadoc
 49     * @see LocalDateTime#parse(CharSequence, DateTimeFormatter)
 50     */
 51    static DateTimeFormatter dtfBuilder(String pattern) {
 52        return new DateTimeFormatterBuilder()
 53                .appendPattern(pattern)
 54                .parseDefaulting(ChronoField.YEAR_OF_ERA,
 55                        LocalDateTime.now().getYear())
 56                .parseDefaulting(ChronoField.MONTH_OF_YEAR, 1)
 57                .parseDefaulting(ChronoField.DAY_OF_MONTH, 1)
 58                .parseDefaulting(ChronoField.HOUR_OF_DAY, 0)
 59                .parseDefaulting(ChronoField.MINUTE_OF_HOUR, 0)
 60                .parseDefaulting(ChronoField.SECOND_OF_MINUTE, 0)
 61                .parseDefaulting(ChronoField.NANO_OF_SECOND, 0)
 62                .toFormatter();
 63    }
 64
 65    static SimpleDateFormat sdfBuilder(String pattern) {
 66        return new SimpleDateFormat(pattern);
 67    }
 68
 69    /**
 70     * solution1:
 71     * Get yyyy-MM-dd 00:00:00, start of the day.<br>
 72     * If you use yyyy-MM-dd as parameter
 73     */
 74    static Date getStartOfDay() {
 75        LocalDateTime localDateTime = LocalDateTime
 76                .parse("2021-02-02",
 77                        dtfBuilder(yyyy_MM_dd));
 78        Instant instant = localDateTime
 79                .atZone(ZoneId.systemDefault())
 80                .toInstant();
 81        return Date.from(instant);
 82    }
 83
 84    /**
 85     * solution2:
 86     * get yyyy-MM-dd 00:00:00, start of the day.<br>
 87     * If you use yyyy-MM-dd as parameter<br>
 88     * <p>
 89     * Using {@link LocalDate#atStartOfDay()}
 90     *
 91     * @param dateString datePattern like 2012-09-08
 92     */
 93    static Date getStartOfDay(String dateString) throws ParseException {
 94        // 由于dtfBuilder的设置 这里的时间已经是 00:00:00
 95        LocalDate localDate = LocalDate
 96                .parse(dateString, dtfBuilder(yyyy_MM_dd));
 97        ZonedDateTime zonedDateTime = localDate
 98                .atStartOfDay(ZoneId.systemDefault());
 99        return Date.from(zonedDateTime.toInstant());
100        // return
101        // sdfBuilder()
102        // .parse(zonedDateTime
103        // .format(dtfBuilder(yyyy_MM_dd_HH_mm_ss)));
104    }
105
106    /**
107     *
108     */
109    static Date getStartOfDay(LocalDate localDate) {
110        ZonedDateTime zonedDateTime = localDate
111                .atStartOfDay(ZoneId.systemDefault());
112
113        LocalDateTime localDateTime = localDate.atStartOfDay();
114        Instant instant = localDateTime
115                .toInstant(ZoneOffset.of("+8"));
116        // return Date.from(zonedDateTime.toInstant());
117        return Date.from(instant);
118    }
119
120    /**
121     * Get yyyy-MM-dd 23:59:59.999, end of the day.<br>
122     * By using {@link LocalDateTime#plus(long, TemporalUnit)}
123     */
124    static Date getEndOfDay() {
125        // 由于dtfBuilder的设置 这里的时间已经是 00:00:00
126        LocalDateTime localDateTime = LocalDateTime
127                .parse("2020-12-21", dtfBuilder(yyyy_MM_dd));
128
129        // plusXxx()方法没有提供毫秒/微秒的相应方法,直接到纳秒;
130        // 相应的,可以使用plus方法指定单位
131        localDateTime = localDateTime
132                .plusHours(23)
133                .plusMinutes(59)
134                .plusSeconds(59)
135                .plusNanos(999_999_999);
136
137        /*
138         * 好方法,将其下级单位的值清零
139         * ChronoUnit.DAYS: 清零hh:mm:ss.SSS
140         * 最大单位 DAYS,也就是说此方法只能用来清零时间
141         */
142        localDateTime = localDateTime.truncatedTo(ChronoUnit.DAYS);
143        localDateTime = localDateTime
144                .plus(23, ChronoUnit.HOURS)
145                .plus(59, ChronoUnit.MINUTES)
146                .plus(59, ChronoUnit.SECONDS)
147                .plus(999, ChronoUnit.MILLIS);
148        return Date.from(
149                localDateTime
150                        .atZone(ZoneId.systemDefault())
151                        .toInstant());
152    }
153
154    /**
155     * Get yyyy-MM-dd 23:59:59.999, end of the day.<br>
156     * By using {@link LocalDate#atTime(LocalTime)}
157     *
158     * @param dateString date pattern like '2012-09-18'
159     */
160    static Date getEndOfDay(String dateString) {
161        LocalDate localDate = LocalDate
162                .parse(dateString, dtfBuilder(yyyy_MM_dd));
163        // localDate.
164        LocalDateTime localDateTime = localDate
165                .atTime(23,
166                        59,
167                        59,
168                        999_999_999);
169        return Date.from(localDateTime
170                .atZone(ZoneId.systemDefault())
171                .toInstant());
172
173    }
174
175    /**
176     * Get first day of month
177     *
178     * @param dateString pattern like '2020-10-25'
179     * @return
180     */
181    static Date getFirstDayOfMonth(String dateString) {
182        LocalDateTime localDateTime = LocalDateTime
183                .parse(dateString, dtfBuilder(yyyy_MM_dd));
184        localDateTime = localDateTime.withDayOfMonth(1);
185        return Date.from(localDateTime
186                .atZone(ZoneId.systemDefault())
187                .toInstant());
188    }
189
190    /**
191     * Get the first day of year.
192     *
193     * @param yearString pattern like '2012'
194     */
195    static Date getFirstDayOfYear(String yearString) {
196        LocalDateTime localDateTime = LocalDateTime
197                .parse(yearString, dtfBuilder(yyyy));
198        return Date.from(localDateTime
199                .atZone(ZoneId.systemDefault())
200                .toInstant());
201    }
202
203    public static void main(String[] args) throws ParseException {
204        System.out.println(sdfBuilder(yyyy_MM_dd_HH_mm_ss)
205                .format(getStartOfDay()));
206
207        System.out.println(sdfBuilder(yyyy_MM_dd_HH_mm_ss)
208                .format(getStartOfDay("2021-02-02")));
209
210        System.out.println(sdfBuilder(yyyy_MM_dd_HH_mm_ss_SSS)
211                .format(getStartOfDay(
212                        LocalDate
213                                .parse("2021-02-22",
214                                        dtfBuilder(yyyy_MM_dd)))));
215
216        System.out.println(sdfBuilder(yyyy_MM_dd_HH_mm_ss_SSS)
217                .format(getEndOfDay()));
218
219        System.out.println(sdfBuilder(yyyy_MM_dd_HH_mm_ss_SSS)
220                .format(getEndOfDay("2020-12-21")));
221
222        System.out.println(sdfBuilder(yyyy_MM_dd)
223                .format(getFirstDayOfMonth("2020-12-18")));
224
225        System.out.println(sdfBuilder(yyyy_MM_dd_HH_mm_ss)
226                .format(getFirstDayOfYear("2012")));
227    }
228}