0、前言
由于传统的日期格式API存在线程安全问题,例如使用线程池去执行SimpleDateFormat的parse方法时,就容易出现线程安全问题
java.util.concurrent.ExecutionException: java.lang.NumberFormatException: For input string: “”
或
java.util.concurrent.ExecutionException: java.lang.NumberFormatException: multiple points
由此JDK8出现了线程安全的时间日期API
1、LocalDate、LocalTime、LocalDateTime
⑴ 概念
由LocalDate、LocalTime、LocalDateTime所创建的实例是不可变的对象,分别代表使用ISO-8601日历系统的日期、时间和日期时间
ISO-8601日期系统是国际化标准组织制定的现代公民的日期和时间的表示法
⑵ API
⒈ now
可以创建LocalDate、LocalTime或LocalDateTime的当前日期或时间的实例
⒉ of
LocalDate of(int year, int month, int dayOfMonth) {}
LocalTime of(int hour, int minute) {}
LocalDateTime of(int year, int month, int dayOfMonth, int hour, int minute, int second) {}
可以创建指定的日期、时间对象
⒊ plusDays
LocalDate plusDays(long daysToAdd) {}
在当前日期(LocalDate)基础上增加几天
⒋ minusDays
LocalDate minusDays(long daysToSubtract) {}
在当前日期(LocalDate)基础上减少几天
⒌ plusMonths
LocalDate plusMonths(long monthsToAdd) {}
在当前日期(LocalDate)基础上增加几个月【输入负数就是减少几个月】
⒍ plusYears
LocalDate plusYears(long yearsToAdd) {}
在当前日期(LocalDate)基础上增加几年
⒎ plusHours
LocalTime plusHours(long hoursToAdd) {}
在当前时间(LocalTime)基础上增加几小时
⒏ plusMinutes
LocalTime plusMinutes(long minutesToAdd) {}
在当前时间(LocalTime)基础上增加几分钟
⒐ plusSeconds
LocalTime plusSeconds(long secondstoAdd) {}
在当前时间(LocalTime)基础上增加几秒
⒑ getYear
int getYear() {}
获取年份
⒒ getMonthValue
int getMonthValue() {}
获取月份(int类型)
⒓ getDayOfMonth
int getDayOfMonth() {}
获取日期【一个月中的】
⒔ getDayOfYear
int getDayOfYear() {}
获取日期【一年中的】
⒕ getHour
int getHour() {}
获取小时数
⒖ getMinute
int getMinute() {}
获取分钟数
⒗ getSecond
int getSecond() {}
获取秒
⒘ isLeapYear
boolean isLeapYear() {}
是否是闰年。注意:该方法只能由LocalDate对象调用
【判断方法(ISO国际日期系统)】
public boolean isLeapYear(long prolepticYear) {
return ((prolepticYear & 3) == 0) && ((prolepticYear % 100) != 0 || (prolepticYear % 400) == 0);
}
⒙ isAfter
boolean isAfter(ChronoLocalDate other) {}
boolean isAfter(LocalTime other) {}
boolean isAfter(ChronoLocalDateTime<?> other) {}
比较当前日期时间是否在指定日期时间之前
⒚ isBefore
比较当前日期时间是否在指定日期时间之后
2、Instant
⑴ 概念
用于“时间戳”的计算,以Unix元年,即UTC时区1970-01-01 00:00:00开始所经历的时间进行计算
⑵ API
⒈ now
public static Instant now() {}
获取当前UTC时区的时间
⒉ atOffset
OffsetDateTime atOffset(ZoneOffset offset) {}
获取指定时区的时间,需要传递一个ZoneOffset对象,可以通过ZoneOffset的静态方法ofHours来获取ZoneOffset实例
public static ZoneOffset ofHours(int hours) {}
传入距UTC时区的时间间隔
注意:时区小时间隔范围是-18~18,如果超过了这个范围会报错
java.time.DateTimeException: Zone offset hours not in valid range: value ?? is not in the range -18 to 18
⒊ getEpochSecond
long getEpochSecond() {}
获取当前时间的秒数
⒋ toEpochMilli
long toEpochMilli() {}
获取当前时间的毫秒数
⒌ ofEpochSecond
public static Instant ofEpochSecond(long epochSecond) {}
获取自1970-01-01T00:00:00Z向后推迟指定秒数的Instant实例
3、Duration、Period
⑴ Duration
⒈ 概念
用于计算两个时间的间隔
⒉ API
between
public static Duration between(Temporal startInclusive, Temporal endExclusive) {}
获取两个时间(Instant或LocalTime或LocalDateTime)的间隔
注意:两个参数的类型要一致,即第一个参数类型是Instant,则第二个参数的类型也必须是Instant,否则会报错
toMillis
public long toMillis() {}
获取时间间隔的毫秒格式
⑵ Period
⒈ 概念
用于计算连个日期的间隔
⒉ API
between
public static Period between(LocalDate startDateInclusive, LocalDate endDateExclusive) {}
获取两个日期(LocalDate)的间隔
getYears
int getYears() {}
获取日期间隔的年的数量
getMonths
int getMonths() {}
获取日期间隔的月的数量
getDays
int getDays() {}
获取日期间隔的天的数量
4、TemporalAdjuster
⑴ 概念
时间校正器,可以对日期时间进行调整操作
⑵ API
⒈ withYear
public LocalDate withYear(int year) {}
指定当前日期对象的年份
public LocalDateTime withYear(int year) {}
指定当前日期时间对象的年份
⒉ withMonth
⒊ withDayOfMonth
⒋ withHour
⒌ withMinute
⒍ withSecond
⒎ with
public LocalDate with(TemporalAdjuster adjuster) {}
public LocalTime with(TemporalAdjuster adjuster) {}
public LocalDateTime with(TemporalAdjuster adjuster) {}
传入时间校正器,返回指定规则的日期时间对象
@FunctionalInterface
public interface TemporalAdjuster {
Temporal adjustInto(Temporal temporal);
}
由于TemporalAdjuster是一个函数式接口,所以可以使用Lambda表达式
同时TemporalAdjusters提供了一些静态方法,可以获取一些常用的匹配规则的日期时间
⑶ 示例
【获取下一个周日,通过TemporalAdjusters】
LocalDateTime.with(TemporalAdjusters.next(DayOfWeek.SUNDAY));
【获取下一个工作日,通过自定规则】
LocalDate localDate = LocalDate.now();
localDate = localDate.with((l) -> {
LocalDate ld = (LocalDate) l; // 强转
switch (ld.getDayOfWeek().getValue()) {
case 5: // 周五
return ld.plusDays(3); // 加3天到周一
case 6: // 周六
return ld.plusDays(2); // 加2天到周一
default:
return ld.plusDays(1);
}
});
System.out.println(localDate);
5、DateTimeFormatter
⑴ 概念
用于对日期时间进行格式化操作
⑵ 常量
⒈ ISO_DATE
DateTimeFormatter.ISO_DATE
获取ISO日期格式转换器对象
⒉ ISO_TIME
DateTimeFormatter.ISO_TIME
获取ISO时间格式转换器对象
⑶ API
⒈ ofPattern
static DateTimeFormatter ofPattern(String pattern) {}
获取日期时间格式转换对象的实例,传递指定格式的字符串。例如:yyyy-MM-dd HH:mm:ss E
⒉ format
public String format(TemporalAccessor temporal) {}
格式化传递的日期时间对象为字符串。传递LocalDate、LocalTime或LocalDateTime
注意:传入的日期时间对象需要和要转换的规则字符串一致,否则会报错
⒊ parse
public static LocalDateTime parse(CharSequence text, DateTimeFormatter formatter) {}
转换为日期时间对象,传入日期时间字符串,以及日期时间转换器对象。通过LocalDateTime来调用
注意:日期时间字符串和转换器对象的格式要对应,否则转换时会报错
public static LocalDate parse(CharSequence text, DateTimeFormatter formatter) {}
转换为日期对象,传入日期字符串,以及日期时间转换器对象。通过LocalDate来调用
注意:日期字符串和转换器对象的格式要对应,否则转换时会报错
public static LocalTime parse(CharSequence text, DateTimeFormatter formatter) {}
转换为时间对象,传入时间字符串,以及日期时间转换器对象。通过LocalTime来调用
注意:时间字符串和转换器对象的格式要对应,否则转换时会报错
6、ZoneId、ZonedDateTime
⑴ 概念
用于处理时区的API
每个时区都对应着ID,格式为 区域/城市
例如:Asia/Shanghai
⑵ ZoneId
⒈ getAvailableZoneIds
public static Set<String> getAvailableZoneIds() {}
获取系统支持的时区ID集合
⒉ of
public static ZoneId of(String zoneId) {}
获取时区ID实例,需要传入时区ID字符串,例如:Asia/Shanghai
⒊ now
public static LocalDate now(ZoneId zone) {}
获取在指定时区的日期时间,传入指定的时区ID对象。通过LocalDate来调用
public static LocalTime now(ZoneId zone) {}
获取在指定时区的日期时间,传入指定的时区ID对象。通过LocalTime来调用
public static LocalDateTime now(ZoneId zone) {}
获取在指定时区的日期时间,传入指定的时区ID对象。通过LocalDateTime来调用
⑶ ZonedDateTime
atZone
public ZonedDateTime atZone(ZoneId zone) {}
获取在指定时区的日期时间,传入指定的时区ID对象。通过LocalDateTime来调用
⑷ 示例
LocalDateTime localDateTime = LocalDateTime.now(ZoneId.of("Asia/Shanghai"));
System.out.println(localDateTime);
ZonedDateTime zonedDateTime = localDateTime.atZone(ZoneId.of("America/New_York"));
System.out.println(zonedDateTime);