Java日期时间API系列26-----Jdk8中java.time包中的新的日期时间API类,YearMonth类的源码,转换和应用。
Java8中为年月新增了类YearMonth,可以用来表示卡片过期时间等问题。
1.YearMonth
默认格式为:2007-12
1.1 部分源码
* * @implSpec * This class is immutable and thread-safe. * * @since 1.8 */ public final class YearMonth implements Temporal, TemporalAdjuster, Comparable<YearMonth>, Serializable { /** * Serialization version. */ private static final long serialVersionUID = 4183400860270640070L; /** * Parser. */ private static final DateTimeFormatter PARSER = new DateTimeFormatterBuilder() .appendValue(YEAR, 4, 10, SignStyle.EXCEEDS_PAD) .appendLiteral('-') .appendValue(MONTH_OF_YEAR, 2) .toFormatter(); /** * The year. */ private final int year; /** * The month-of-year, not null. */ private final int month;
通过源码可以看出使用final修饰YearMonth,YearMonth是线程安全类,同时实现了Temporal, TemporalAdjuster, Comparable<YearMonth>, Serializable接口,有属性读取,设置和加减等功能。
1.2 创建和基本使用
YearMonth yearMonth = YearMonth.now(); YearMonth yearMonth2 = YearMonth.of(2020, 4); System.out.println(yearMonth); System.out.println(yearMonth2); YearMonth yearMonth3 = YearMonth.parse("2020-05"); System.out.println(yearMonth3); YearMonth yearMonth4 = yearMonth3.plusMonths(1); System.out.println(yearMonth4);
输出:
2020-03 2020-04 2020-05 2020-06
2.应用
2.1 转换
如Date转YearMonth,YearMonth转Date等
/** * Date转YearMonth * @param date * @return */ public static YearMonth toYearMonth(Date date){ LocalDate localDate = toLocalDate(date); return YearMonth.of(localDate.getYear(), localDate.getMonthValue()); } /** * LocalDateTime转YearMonth * @param localDateTime * @return */ public static YearMonth toYearMonth(LocalDateTime localDateTime){ LocalDate localDate = toLocalDate(localDateTime); return YearMonth.of(localDate.getYear(), localDate.getMonthValue()); } /** * LocalDate转YearMonth * @param localDate * @return */ public static YearMonth toYearMonth(LocalDate localDate){ Objects.requireNonNull(localDate, "localDate"); return YearMonth.of(localDate.getYear(), localDate.getMonthValue()); } /** * Instant转YearMonth * @param instant * @return */ public static YearMonth toYearMonth(Instant instant){ LocalDate localDate = toLocalDate(instant); return YearMonth.of(localDate.getYear(), localDate.getMonthValue()); } /** * ZonedDateTime转YearMonth * @param zonedDateTime * @return */ public static YearMonth toYearMonth(ZonedDateTime zonedDateTime){ LocalDate localDate = toLocalDate(zonedDateTime); return YearMonth.of(localDate.getYear(), localDate.getMonthValue()); } /** * YearMonth转Date * 注意dayOfMonth范围:1到31之间,最大值根据月份确定特殊情况,如2月闰年29,非闰年28 * 如果要转换为当月最后一天,可以使用下面方法:toDateEndOfMonth(YearMonth) * @param yearMonth * @param dayOfMonth * @return */ public static Date toDate(YearMonth yearMonth, int dayOfMonth) { Objects.requireNonNull(yearMonth, "yearMonth"); return toDate(yearMonth.atDay(dayOfMonth)); } /** * YearMonth转Date,转换为当月第一天 * @param yearMonth * @return */ public static Date toDateStartOfMonth(YearMonth yearMonth) { return toDate(yearMonth, 1); } /** * YearMonth转Date,转换为当月最后一天 * @param yearMonth * @return */ public static Date toDateEndOfMonth(YearMonth yearMonth) { Objects.requireNonNull(yearMonth, "yearMonth"); return toDate(yearMonth.atEndOfMonth()); } /** * YearMonth转LocalDate * 注意dayOfMonth范围:1到31之间,最大值根据月份确定特殊情况,如2月闰年29,非闰年28 * 如果要转换为当月最后一天,可以使用下面方法:toLocalDateEndOfMonth(YearMonth) * @param yearMonth * @param dayOfMonth * @return */ public static LocalDate toLocalDate(YearMonth yearMonth, int dayOfMonth) { Objects.requireNonNull(yearMonth, "yearMonth"); return yearMonth.atDay(dayOfMonth); } /** * YearMonth转LocalDate,转换为当月第一天 * @param yearMonth * @return */ public static LocalDate toLocalDateStartOfMonth(YearMonth yearMonth) { return toLocalDate(yearMonth, 1); } /** * YearMonth转LocalDate,转换为当月最后一天 * @param yearMonth * @return */ public static LocalDate toLocalDateEndOfMonth(YearMonth yearMonth) { Objects.requireNonNull(yearMonth, "yearMonth"); return yearMonth.atEndOfMonth(); }
测试代码:
@Test public void yearMonthConverterTest(){ System.out.println("===================yearMonthConverterTest====================="); Date date = new Date(); System.out.println(date); YearMonth yearMonth = DateTimeConverterUtil.toYearMonth(date); System.out.println(yearMonth); Date date1 = DateTimeConverterUtil.toDate(yearMonth, 15); //转换为当月第一天 Date date2 = DateTimeConverterUtil.toDateStartOfMonth(yearMonth); //转换为当月最后一天 Date date3 = DateTimeConverterUtil.toDateEndOfMonth(yearMonth); System.out.println(date1); System.out.println(date2); System.out.println(date3); LocalDate LocalDate1 = DateTimeConverterUtil.toLocalDate(yearMonth, 15); //转换为当月第一天 LocalDate LocalDate2 = DateTimeConverterUtil.toLocalDateStartOfMonth(yearMonth); //转换为当月最后一天 LocalDate LocalDate3 = DateTimeConverterUtil.toLocalDateEndOfMonth(yearMonth); System.out.println(LocalDate1); System.out.println(LocalDate2); System.out.println(LocalDate3); }
输出:
===================yearMonthConverterTest===================== Fri Mar 20 23:41:41 CST 2020 2020-03 Sun Mar 15 00:00:00 CST 2020 Sun Mar 01 00:00:00 CST 2020 Tue Mar 31 00:00:00 CST 2020 2020-03-15 2020-03-01 2020-03-31
2.2 计算
获取起始日期中间的日期列表,获取指定月份的日期列表,判断是否过期等等
/** * 获取指定区间的时间列表,包含起始 * @param startInclusive * @param endInclusive * @return */ public static List<LocalDateTime> getLocalDateTimeList(LocalDateTime startInclusive, LocalDateTime endInclusive){ Objects.requireNonNull(startInclusive, "startInclusive"); Objects.requireNonNull(endInclusive, "endInclusive"); if(startInclusive.isAfter(endInclusive)){ throw new DateTimeException("startInclusive must before or equal endInclusive!"); } List<LocalDateTime> localDateTimeList = new ArrayList<LocalDateTime>(); long days = betweenTotalDays(startInclusive, endInclusive)+1; for(long i=0; i<days; i++){ localDateTimeList.add(startInclusive.plusDays(i)); } return localDateTimeList; } /** * 获取指定区间的时间列表,包含起始 * @param startInclusive * @param endInclusive * @return */ public static List<LocalDate> getLocalDateList(LocalDate startInclusive, LocalDate endInclusive){ return getLocalDateTimeList(DateTimeConverterUtil.toLocalDateTime(startInclusive), DateTimeConverterUtil.toLocalDateTime(endInclusive)).stream() .map(localDateTime -> localDateTime.toLocalDate()).collect(Collectors.toList()); } /** * 获取指定区间的时间列表,包含起始 * @param startInclusive * @param endInclusive * @return */ public static List<Date> getDateList(Date startInclusive, Date endInclusive){ return getLocalDateTimeList(DateTimeConverterUtil.toLocalDateTime(startInclusive), DateTimeConverterUtil.toLocalDateTime(endInclusive)).stream() .map(localDateTime -> DateTimeConverterUtil.toDate(localDateTime)).collect(Collectors.toList()); } /** * 获取指定年月的所有日期列表 * @param YearMonth * @return */ public static List<LocalDate> getLocalDateList(YearMonth yearMonth){ Objects.requireNonNull(yearMonth, "yearMonth"); List<LocalDate> localDateList = new ArrayList<LocalDate>(); long days = yearMonth.lengthOfMonth(); LocalDate localDate = DateTimeConverterUtil.toLocalDateStartOfMonth(yearMonth); for(long i=0; i<days; i++){ localDateList.add(plusDays(localDate, i)); } return localDateList; } /** * 获取指定年月的所有日期列表 * @param yearMonthStr yyyy-MM * @return */ public static List<LocalDate> getLocalDateList(String yearMonthStr){ Objects.requireNonNull(yearMonthStr, "yearMonthStr"); YearMonth yearMonth = YearMonth.parse(yearMonthStr); return getLocalDateList(yearMonth); } /** * 获取指定年月的所有日期列表 * @param yearMonth * @return */ public static List<LocalDateTime> getLocalDateTimeList(YearMonth yearMonth){ return getLocalDateList(yearMonth).stream() .map(localDate -> DateTimeConverterUtil.toLocalDateTime(localDate)).collect(Collectors.toList()); } /** * 获取指定年月的所有日期列表 * @param yearMonthStr yyyy-MM * @return */ public static List<LocalDateTime> getLocalDateTimeList(String yearMonthStr){ return getLocalDateList(yearMonthStr).stream() .map(localDate -> DateTimeConverterUtil.toLocalDateTime(localDate)).collect(Collectors.toList()); } /** * 获取指定年月的所有日期列表 * @param yearMonthStr yyyy-MM * @return */ public static List<Date> getDateList(String yearMonthStr){ return getLocalDateList(yearMonthStr).stream().map(localDate -> DateTimeConverterUtil.toDate(localDate)) .collect(Collectors.toList()); } /** * 判断是否过期,(输入年月小于当前年月) * @param yearMonth * @return */ public static boolean isExpiry(YearMonth yearMonth){ Objects.requireNonNull(yearMonth, "yearMonth"); if(yearMonth.isBefore(YearMonth.now())){ return true; } return false; } /** * 判断是否过期,(输入年月小于当前年月) * @param yearMonthStr yyyy-MM * @return */ public static boolean isExpiry(String yearMonthStr){ Objects.requireNonNull(yearMonthStr, "yearMonthStr"); YearMonth yearMonth = YearMonth.parse(yearMonthStr); return isExpiry(yearMonth); }
测试代码:
/** * yearMonth测试 */ @Test public void yearMonthTest(){ //是否过期 System.out.println(DateTimeCalculatorUtil.isExpiry("2020-03")); //获取指定年月的所有日期列表 List<Date> dateList = DateTimeCalculatorUtil.getDateList("2020-03"); dateList.stream().forEach(date->{ System.out.println(DateTimeFormatterUtil.formatToDateStr(date)); }); System.out.println("========================"); //获取指定区间的时间列表,包含起始 List<Date> dateList2 = DateTimeCalculatorUtil.getDateList(dateList.get(0), dateList.get(dateList.size()-1)); dateList2.stream().forEach(date->{ System.out.println(DateTimeFormatterUtil.formatToDateStr(date)); }); }
输出:
false
2020-03-01
2020-03-02
2020-03-03
2020-03-04
2020-03-05
2020-03-06
2020-03-07
2020-03-08
2020-03-09
2020-03-10
2020-03-11
2020-03-12
2020-03-13
2020-03-14
2020-03-15
2020-03-16
2020-03-17
2020-03-18
2020-03-19
2020-03-20
2020-03-21
2020-03-22
2020-03-23
2020-03-24
2020-03-25
2020-03-26
2020-03-27
2020-03-28
2020-03-29
2020-03-30
2020-03-31
========================
2020-03-01
2020-03-02
2020-03-03
2020-03-04
2020-03-05
2020-03-06
2020-03-07
2020-03-08
2020-03-09
2020-03-10
2020-03-11
2020-03-12
2020-03-13
2020-03-14
2020-03-15
2020-03-16
2020-03-17
2020-03-18
2020-03-19
2020-03-20
2020-03-21
2020-03-22
2020-03-23
2020-03-24
2020-03-25
2020-03-26
2020-03-27
2020-03-28
2020-03-29
2020-03-30
2020-03-31
源代码地址:https://github.com/xkzhangsan/xk-time
寻找撬动地球的支点(解决问题的方案),杠杆(Java等编程语言)已经有了。xkzhangsan