旧的日期/时间API的缺点
- Java日期与时间类定义不一致,java.util和java.sql包都有日期类,java.util.Date包含时间和日期,java.sql.Date只包含日期,将其纳入java.sql包并不合理,同时两个类有相同的名字,这本身就是个糟糕的设计。
- 日期类都是可变类,是线程不安全的。
- 日期类不提供国际化功能,没有时区的支持,因此Java后续引入java.util.Calendar和java.util.TimeZone,但他们同样存在上面的问题。
以上问题表明Java需要一个健壮的日期类型
Java8日期API设计原则
- 不变性:新的日期API中,所有类都是不可变类
- 关注点分离:将人类可读的日期时间与机器时间分离,为日期(Dat)e、时间(Time)、日期时间(DateTime)、时间戳(unix timestamp)以及时区定义了不同的类
- 清晰:所有的类中都定义了用以完成相同动作的方法,比如过去当前实例的now(),格式装换的format()和parse()方法
- 实用操作:所有日期API都实现了常用的操作,如加、减、格式化等
Java8时间/日期API相关包
- java.time:java8时间/日期API基础包,常用的如LocalDate、LocalTime、LocalDateTime、Instant、Period、Duration类都在这个包下,这些类都是不可变且线程安全的
- java.time.chrono:这个包为非ISO标准日历系统提供泛化API,可以通过扩展AbstractChronology类自定义日历系统
- java.time.format:提供格式化与解析功能的类,java.time包下的类已经提供了相应的功能,所以一般不直接使用它们
- java.time.temporal:这个包包含一些时态对象,可以用来找出相对于某个特定时间的日期,如某月的第一天或者最后一天,这些方法一般都是"withXXX"的格式
- java.time.zone:包含时区规则的类
Java8常用日期/时间API示例
// 只包含日期,默认格式为(yyyy-MM-dd)
LocalDate nowDate = LocalDate.now();
// 只包含时间,默认格式为(hh:mm:ss.zzz)
LocalTime nowTime = LocalTime.now();
// 既包含日期也包含时间,默认格式为(yyyy-MM-dd-HH-mm-ss.zzz)
LocalDateTime nowDateTime = LocalDateTime.now();
// 用在机器可读的时间格式上的,它以Unix时间戳的形式存储日期时间
Instant instant = Instant.now();
// 可以在参数中传递ZonId指定时区
LocalDate nowDate = LocalDate.now(ZoneId.of("Asia/Shanghai"));
LocalTime nowTime = LocalTime.now(ZoneId.of("Asia/Shanghai"));
LocalDateTime nowDateTime = LocalDateTime.now(ZoneId.of("Asia/Shanghai"));
LocalDateTime date = LocalDateTime.of(2011,8,6,15,23,12);
// 可以通过parse方法以指定的模式将字符串转换为日期类型
LocalDateTime time = LocalDateTime.parse("2016-05-07 13:00:00", DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
int year = date.getYear();
Month month = date.getMonth();
int day = date.getDayOfMonth();
System.out.println(date);
System.out.println("year: "+year+" month: "+ month.getValue()+" day: "+day);
- 在指定时间上加n年、n个月、n周、n天......
LocalDateTime now = LocalDateTime.now();
LocalDateTime newTime = now.plusYears(2).plusMonths(3).plusHours(1).plusMinutes(2);
// 通过format方法可以获得格式化的日期字符串
// 格式化类型可以通过DateTimeFormatter.ofPattern(str)方法获得
System.out.println(now.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
System.out.println(newTime.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
- LocalDateTime、LocalDate、LocalTime互转
LocalDateTime now = LocalDateTime.now();
LocalDate localDate = now.toLocalDate();
LocalTime localTime = now.toLocalTime();
LocalDateTime other = LocalDateTime.of(localDate, localTime);
public void localDateTime2Date() {
LocalDateTime now = LocalDateTime.now();
ZoneId zoneId = ZoneId.systemDefault();
Instant instant = now.atZone(zoneId).toInstant();
Date date = Date.from(instant);
}
public void date2LocalDateTime() {
Date date = new Date();
Instant instant = date.toInstant();
ZoneId zoneId = ZoneId.systemDefault();
LocalDateTime localDateTime = LocalDateTime.ofInstant(instant, zoneId);
}
public static void main(String[] args) {
LocalDateTime now = LocalDateTime.now();
LocalDateTime today = now.minusDays(1);
System.out.println(now.equals(today));
System.out.println(now.isBefore(today));
System.out.println(now.isAfter(today));
}