一、Java8之前日期类所存在的问题
在Java8
之前通常会使用Date
结合 SimpleDateFormat
、Calender
来处理时间和日期的相关需求。
但是这些API
也存在明显的缺点:
可读性差、易用性差、使用起来冗余繁琐
java.util.Date
是非线程安全的
java.util.Date
存在千年虫问题、并且不支持国际化和时区、故大部分方法被声明为过时、不建议再使用
java.util
和java.sql
两包中都有Date
类,设计上并不合理
而java8
在java.time
包下重新实现了日期相关类。
每个类功能明确清晰、类之间协作简单、API 定义清晰、功能强大无需借助外部工具类,并且线程安全。
二、Java8新增日期类
Java8
新增的日期类主要有三个:
LocalDate
:表示日期(年月日)
LocalTime
:表示时间(时分秒)
LocalDateTime
:表示时间+ 日期 (年月日时分秒),是java8
最常用的日期类
这些类使用了final来修饰,使得这些类是不可变的,一旦实例化,值就固定了,有点类似于String类。
因此它们都是线程安全的。
2.1 LocalDate
2.1.1 常用API
方法 | 描述 |
---|---|
static LocalDate now() | 获取默认时区的当前日期对象 |
static LocalDate now(Clock clock) | 从指定时钟获取当前日期对象 |
static LocalDate now(ZoneId zone) | 获取指定时区的当前日期对象 |
of | 根据指定年月日创建LocalDate对象 |
getYear | 获得年份 |
getMonthValue | 获得月份(1-12) |
getMonth | 获得月份枚举值 |
getDayOfMonth | 获得月份中的第几天(1-31) |
getDayOfWeek | 获得星期几 |
getDayOfYear | 获得年份中的第几天(1-366) |
lengthOfYear | 获得当年总天数 |
lengthOfMonth | 获得当月总天数 |
toEpochDay | 与时间纪元(1970年1月1日)相差的天数 |
plusDays | 加天 |
plusWeeks | 加周 |
plusMonths | 加月 |
plusYears | 加年 |
minusDays | 减年 |
minusWeeks | 减周 |
minusMonths | 减月 |
minusYears | 减年 |
withYear | 替换年份 |
withMonth | 替换月份 |
withDayOfMonth | 替换月份中的第几天(1-31) |
withDayOfYear | 替换年份中的第几天(1-366) |
isBefore | 是否日期在之前 |
isAfter | 是否日期在之后 |
isEqual | 是否是当前日期 |
isleapYear | 是否是闰年 |
2.1.2 使用示例
1)创建方法
LocalDate now1 = LocalDate.now();// 当前日期 LocalDate now2 = LocalDate.now(ZoneId.of("Asia/Shanghai"));// 当前日期 (指定时区)LocalDate now3 = LocalDate.now(Clock.systemDefaultZone());// 当前日期 (指定时钟)LocalDate localDate = LocalDate.of(2023, 1, 1);// 指定日期 2023-01-01
2)获取方法
LocalDate now = LocalDate.now();int year = now.getYear();// 获取年份int month = now.getMonthValue();// 获取月份(1-12)Month monthEnum = now.getMonth();// 获取月份的枚举值int dayOfMonth = now.getDayOfMonth();// 获取月份中的第几天(1-31)int dayOfYear = now.getDayOfYear();// 获取一年中的第几天(1-366)DayOfWeek dayOfWeek = now.getDayOfWeek();// 获取现在是星期几int dayOfYear = now.getDayOfYear();// 获取一年中的第几天(1-366)int lengthOfYear = now.lengthOfYear();// 获得当年总天数int lengthOfMonth = now.lengthOfMonth();// 获得当月总天数long epochDay = now.toEpochDay();// 与时间纪元(1970年1月1日)相差的天数
3)运算方法
LocalDate now = LocalDate.now();LocalDate localDate1 = now.plusDays(1);// 给当前时间加一天LocalDate localDate2 = now.plusDays(1);// 给当前时间加一周LocalDate localDate3 = now.plusMonths(1);// 给当前时间加一月LocalDate localDate4 = now.plusYears(1);// 给当前时间加一年LocalDate localDate5 = now.minusDays(1);// 给当前时间减一天LocalDate localDate6 = now.minusWeeks(1);// 给当前时间减一周LocalDate localDate7 = now.minusMonths(1);// 给当前时间减一月LocalDate localDate8 = now.minusYears(1);// 给当前时间减一年
4)修改方法
LocalDate now = LocalDate.now();LocalDate localDate1 = now.withYear(2020);// 修改日期对象年份为2020LocalDate localDate2 = now.withMonth(1);// 修改日期对象月份为1LocalDate localDate3 = now.withDayOfMonth(1);// 修改日期对象的日期(一月中的第几天)LocalDate localDate4 = now.withDayOfYear(1);// 修改日期对象的日期(一年中的第几天)
5)比较方法
LocalDate now = LocalDate.now();LocalDate localDate = LocalDate.of(2023, 1, 1) boolean isBefore = localDate.isBefore(now);// localDate是否在当天之前boolean isAfter = localDate.isAfter(now);// localDate是否在当天之后boolean isEqual = localDate.isEqual(now);// localDate是否在当天boolean isLeapYear = localDate.isLeapYear();// localDate是否是闰年
6)LocalDate 与 Date之间的转换
/** * LocalDate转Date * @param localDate * @return */public static Date toDate(LocalDate localDate) { return Date.from(localDate.atStartOfDay().atZone(ZoneId.systemDefault()).toInstant());}/** * Date转LocalDate * @param Date * @return */public static Date toLocalDate(Date date) { return date.toInstant().atZone(ZoneId.systemDefault()).toLocalDate();}
7)LocalDate 与 String之间的转换
/** * String转LocalDate * @param dateStr 日期的字符串 * @param pattern 格式示例: yyyy-MM-dd * @return */public static LocalDate toLocalDate(String dateStr, String pattern) { DateTimeFormatter formatter = DateTimeFormatter.ofPattern(pattern); return LocalDate.parse(dateStr, formatter);}/** * LocalDate转String * @param localDate localDate对象 * @param pattern 格式示例: yyyy-MM-dd * @return */public static String LocalDatetoStr(LocalDate localDate, String pattern) { DateTimeFormatter formatter = DateTimeFormatter.ofPattern(pattern); return localDate.format(formatter);}
2.2 LocalTime
2.2.1 常用API
方法 | 描述 |
---|---|
static LocalTime now() | 获取默认时区的当前时间 |
static LocalTime now(ZoneId zone) | 获取指定时区的当前时间 |
static LocalTime now(Clock clock) | 从指定时钟获取当前时间 |
of | 根据指定的时、分、秒获取LocalTime 实例 |
getHour | 获取小时 |
getMinute | 获取分钟 |
getSecond | 获取秒 |
getNano | 获取纳秒 |
plusHours | 增加小时数 |
plusMinutes | 增加分钟数 |
plusSeconds | 增加秒数 |
plusNanos | 增加纳秒数 |
minusHours | 减少小时数 |
minusMinutes | 减少分钟数 |
minusSeconds | 减少秒数 |
minusNanos | 减少纳秒数 |
withHour | 替换小时 |
withMinute | 替换分钟 |
withSecond | 替换秒钟 |
withNano | 替换纳秒 |
compareTo | 时间与另一个时间比较 |
isAfter | 检查时间是否在指定时间之后 |
isBefore | 检查时间是否在指定时间之前 |
2.2.2 使用示例
1)创建方法
LocalTime now1 = LocalTime.now();// 当前时间 LocalTime now2 = LocalTime.now(ZoneId.of("Asia/Shanghai"));// 当前时间 (指定时区)LocalTime now3 = LocalTime.now(Clock.systemDefaultZone());// 当前时间 (指定时钟)LocalTime localTime = LocalTime.of(9, 9, 9);// 指定时间 09:09:09
2)获取方法
LocalTime now = LocalTime.now();int hour = now.getHour();// 获取小时int minute = now.getMinute();// 获取小时int second = now.getSecond();// 获取秒int nano = now.getNano();// 获取纳秒
3)运算方法
LocalTime now = LocalTime.now();LocalTime localTime1 = now.plusHours(1);// 给当前时间加一小时LocalTime localTime2 = now.plusMinutes(1);// 给当前时间加一分钟LocalTime localTime3 = now.plusSeconds(1);// 给当前时间加一秒LocalTime localTime4 = now.plusNanos(1);// 给当前时间加一纳秒LocalTime localTime1 = now.minusHours(1);// 给当前时间减一小时LocalTime localTime2 = now.minusMinutes(1);// 给当前时间减一分钟LocalTime localTime3 = now.minusSeconds(1);// 给当前时间减一秒LocalTime localTime4 = now.minusNanos(1);// 给当前时间减一纳秒
4)修改方法
LocalTime now = LocalTime.now();LocalDate localTime1 = now.withHour(1);// 修改时间对象小时为1LocalDate localTime2 = now.withMinute(1);// 修改时间对象分钟为1LocalDate localTime3 = now.withSecond(1);// 修改时间对象秒钟为1LocalDate localTime4 = now.withNano(1);// 修改时间对象纳秒为1
5)比较方法
LocalTime now = LocalTime.now();LocalTime localTime = LocalTime.of(9, 9, 9);int compare = localTime.compareTo(now);// localTime和当前时间比较--0(相等)正数(大)负数(小)boolean after = localTime.isAfter(now);// localTime是否在当前时间之后boolean before = localTime.isBefore(now);// localTime是否在当前时间之前
6)LocalTime 与 String之间的转换
/** * String转LocalTime * @param timeStr 日期的字符串 * @param pattern 格式示例: HH:mm:ss * @return */public static LocalTime toLocalTime(String timeStr, String pattern) { DateTimeFormatter formatter = DateTimeFormatter.ofPattern(pattern); return LocalTime.parse(timeStr, formatter);}/** * LocalTime转String * @param localTime localTime对象 * @param pattern 格式示例: HH:mm:ss * @return */public static LocalTime localTimeToStr(LocalTime localTime, String pattern) { DateTimeFormatter formatter = DateTimeFormatter.ofPattern(pattern); return localTime.format(formatter);}
LocalTime是无法转换为Date的,因为它值包含了时间部分,而没有日期部分
2.3 LocalDateTime
2.2.1 常用API
方法 | 描述 |
---|---|
static LocalDateTime now() | 获取默认时区的当前日期时间 |
static LocalDateTime now(Clock clock) | 从指定时钟获取当前日期时间 |
static LocalDateTime now(ZoneId zone) | 获取指定时区的当前日期时间 |
static LocalDateTime of(LocalDate date, LocalTime time) | 根据日期和时间对象获取LocalDateTime 对象 |
static LocalDateTime of(int year, Month month, int dayOfMonth, int hour, int minute, int second) | 根据指定的年、月、日、时、分、秒获取LocalDateTime 实例 |
getYear | 获取年份 |
getMonth | 使用月份枚举类获取月份 |
getDayOfMonth | 获取日期在该月是第几天 |
getDayOfWeek | 获取日期是星期几 |
getDayOfYear | 获取日期在该年是第几天 |
getHour | 获取小时 |
getMinute | 获取分钟 |
getSecond | 获取秒 |
getNano | 获取纳秒 |
plusYears | 增加年 |
plusMonths | 增加月 |
plusWeeks | 增加周 |
plusDays | 增加天 |
plusHours | 增加小时 |
plusMinutes | 增加分 |
plusSeconds | 增加秒 |
plusNanos | 增加纳秒 |
minusYears | 减少年 |
minusMonths | 减少月 |
meminusWeeks | 减少周 |
minusDays | 减少天 |
minusHours | 减少小时 |
minusMinutes | 减少分 |
minusSeconds | 减少秒 |
minusNanos | 减少纳秒 |
withYear | 替换年份 |
withMonth | 替换月份 |
withDayOfMonth | 替换月份中的第几天(1-31) |
withDayOfYear | 替换年份中的第几天(1-366) |
withHour | 替换小时 |
withMinute | 替换分钟 |
withSecond | 替换秒钟 |
withNano | 替换纳秒 |
isEqual | 判断日期时间是否相等 |
isBefore | 检查是否在指定日期时间之前 |
isAfter | 检查是否在指定日期时间之后 |
2.2.2 使用示例
1)创建方法
// 1.当前日期LocalDateTime now1 = LocalDateTime.now();// 2.当前日期 (指定时区)LocalDateTime now2 = LocalDateTime.now(ZoneId.of("Asia/Shanghai"));// 3.当前日期 (指定时钟)LocalDateTime now3 = LocalDateTime.now(Clock.systemDefaultZone());// 4.指定日期 2023-01-01 01:01:00LocalDateTime localDateTime1 = LocalDateTime.of(2023, 1, 1, 1, 1);// 4.使用LocalDate和LocalTime对象创建LocalDateTime对象LocalDate localDate = LocalDate.now();LocalTime localTime = LocalTime.now();LocalDateTime localDateTime2 = LocalDateTime.of(localDate, localTime);
2)获取方法
LocalDateTime now = LocalDateTime.now();int year = now.getYear(); // 获取年份Month month = now.getMonth(); // 使用月份枚举值int dayOfMonth = now.getDayOfMonth(); // 获取日期在该月是第几天DayOfWeek dayOfWeek = now.getDayOfWeek(); // 获取日期是星期几int dayOfYear = now.getDayOfYear(); // 获取日期在该年是第几天int hour = now.getHour(); // 获取小时int minute = now.getMinute(); // 获取分钟int second = now.getSecond(); // 获取秒钟int nano = now.getNano(); // 获取纳秒
3)运算方法
LocalDateTime now = LocalDateTime.now();LocalDateTime localDateTime1 = now.plusDays(1);// 给当前时间加一天LocalDateTime localDateTime2 = now.plusDays(1);// 给当前时间加一周LocalDateTime localDateTime3 = now.plusMonths(1);// 给当前时间加一月LocalDateTime localDateTime4 = now.plusYears(1);// 给当前时间加一年LocalDateTime localDateTime5 = now.plusHours(1);// 给当前时间加一小时LocalDateTime localDateTime6 = now.plusMinutes(1);// 给当前时间加一分钟LocalDateTime localDateTime7 = now.plusSeconds(1);// 给当前时间加一秒LocalDateTime localDateTime8 = now.plusNanos(1);// 给当前时间加一纳秒LocalDateTime localDateTime9 = now.minusDays(1);// 给当前时间减一天LocalDateTime localDateTime10 = now.minusWeeks(1);// 给当前时间减一周LocalDateTime localDateTime11 = now.minusMonths(1);// 给当前时间减一月LocalDateTime localDateTime12 = now.minusYears(1);// 给当前时间减一年LocalDateTime localDateTime13 = now.minusHours(1);// 给当前时间减一小时LocalDateTime localDateTime14 = now.minusMinutes(1);// 给当前时间减一分钟LocalDateTime localDateTime15 = now.minusSeconds(1);// 给当前时间减一秒LocalDateTime localDateTime16 = now.minusNanos(1);// 给当前时间减一纳秒
4)修改方法
LocalDateTime now = LocalDateTime.now();LocalDateTime localDate1 = now.withYear(2020); // 修改日期对象年份为2020LocalDateTime localDate2 = now.withMonth(1); // 修改日期对象月份为1LocalDateTime localDate3 = now.withDayOfMonth(1); // 修改日期对象的日期(一月中的第几天)LocalDateTime localDate4 = now.withDayOfYear(1); // 修改日期对象的日期(一年中的第几天)LocalDateTime localTime1 = now.withHour(1); // 修改时间对象小时为1LocalDateTime localTime2 = now.withMinute(1); // 修改时间对象分钟为1LocalDateTime localTime3 = now.withSecond(1); // 修改时间对象秒钟为1LocalDateTime localTime4 = now.withNano(1);// 修改时间对象纳秒为1
5)比较方法
LocalDateTime now = LocalDateTime.now();LocalDateTime localDateTime = LocalDateTime.of(2023, 1, 1, 1, 1);boolean isBefore = localDateTime.isBefore(now);// localDateTime是否在当天之前boolean isAfter = localDateTime.isAfter(now); // localDateTime是否在当天之后boolean isEqual = localDateTime.isEqual(now); // localDateTime是否在当天
6)从LocalDateTime获取LocalDate或者LocalTime
LocalDateTime localDateTime = LocalDateTime.now();LocalDate localDate = localDateTime.toLocalDate(); // 从LocalDateTime获取LocalDate对象LocalTime localTime = localDateTime.toLocalTime(); // 从LocalDateTime获取LocalTime对象
7)LocalDateTime与 String之间的转换
/** * String转LocalDateTime * @param dateTimeStr 日期的字符串 * @param pattern 格式示例: yyyy-MM-dd HH:mm:ss * @return */public static LocalDateTime toLocalDateTime(String dateTimeStr, String pattern) { DateTimeFormatter formatter = DateTimeFormatter.ofPattern(pattern); return LocalDateTime.parse(dateTimeStr, formatter);}/** * LocalDateTime转String * @param localDateTime 日期时间对象 * @param pattern 格式示例: yyyy-MM-dd HH:mm:ss * @return */public static String LocalDateTimetoStr(LocalDateTime localDateTime, String pattern) { DateTimeFormatter formatter = DateTimeFormatter.ofPattern(pattern); return localDateTime.format(formatter);}
8)LocalDateTime与 Date之间的转换
/** * Date转LocalDateTime * @param date jdk6 日期对象 * @param zoneId 时区id * @return */public static LocalDateTime toLocalDateTime(Date date, ZoneId zoneId) { // toInstant():将Date对象转换成为Instant(瞬时)对象 // ofInstant(): 将瞬时对象转换成为LocalDateTime对象 Instant instant = date.toInstant(); if (zoneId == null) { zoneId = ZoneId.systemDefault(); } return LocalDateTime.ofInstant(instant, zoneId);}/** * LocalDateTime转Date * @param localDateTime 日期时间对象 * @return */public static Date LocalDateTimetoDate(LocalDateTime localDateTime, ZoneId zoneId) { if (zoneId == null) { zoneId = ZoneId.systemDefault(); } ZonedDateTime zonedDateTime = localDateTime.atZone(zoneId); Instant instant = zonedDateTime.toInstant(); return Date.from(instant);}