Java8新引入了一个java.time包,该包下包含了Java8中对于日期时间处理的另一种解决方案。
在Java8前的版本中,日期时间处理只能通过Date Calender SimpleDateFormat等原生API处理,这种处理方式一直被人吐槽,在某次Tiago Fernandez 举行的Java最烂API评选中荣获第二名,下图为赛情
图片引用于Tiago Fernandez
仔细一想,Java8前原生日期时间处理API确实有点反人类,例如想使用Date保存今天日期时
public static void main(String[] args) {
Date date = new Date(2020, 6, 12);
System.out.println(date);
}
我们想的应该是创建一个Date对象用来保存2020年6月12日这个日期,但看到输出之后,发现事情并没有我们想的那么简单
Date对象确实建好了,但year我明明给的2020,却变成3920,month明明给的是6,却最后却保存为了7。
当然还有一种原生日期API中还有一种日期保存的解决方案-Calender,其公有静态方法getInstance可以获取一个保存当前日期的日历对象
话不多说,先上代码
public static void main(String[] args) {
Calendar calendar = Calendar.getInstance();
int year = calendar.get(Calendar.YEAR);
int month = calendar.get(Calendar.MONTH);
int day = calendar.get(Calendar.DAY_OF_MONTH);
System.out.println(new StringBuilder("").append(year).append("/").append(month).append("/").append(day));
}
我们来看看它的输出
由于Calender默认的MONTH是从0开始计时的,所以所以6月Calender中用5表示,这不一致有没有让你抓狂?我就想用一个Calender对象保存今天的日期,调用getInstance后居然还需要我手动修改其MONTH值?
当然SimpleDateTimeFormat肯定也跑不了,不知道你们有没有看过其源码,如果看过那你就会发现,这是一个线程不安全的类,所以说在多线程的环境下,使用时还给考虑会不会出现线程安全问题。如果会,还给额外写大量避免线程安全的代码。这个问题让本就不富裕的家庭又是雪上加霜。
而在Java8中这些问题都得到了解决。
上图为Java8中java.time包下的类,该包下的类都有个特点,那就是被final修饰,且线程安全,本篇主要对其中最关键的几个类进行讲解
Clock——用于获取指定时区的当前日期
简单使用
public class Main {
public static void main(String[] args) {
Clock clock = Clock.systemUTC();//获取当前时钟,使用UTC时区转换为日期和时间。同System.currentTimeMillis()
Clock clock2 = Clock.systemDefaultZone(); //获取当前时钟,使用系统默认时区转换为日期和时间
Clock clock3 = Clock.system(ZoneId.of("Asia/Shanghai")); //获取当前时钟,使用参数中自定义的时区转换为日期和时间
Clock clock4 = Clock.fixed(Instant.now(), ZoneId.of("Europe/Paris"));//返回以第一参数作为时间戳,第二参数作为时区的时钟
Clock clock5 = Clock.offset(Clock.systemUTC(), Duration.ofSeconds(2)); //返回距离第一参数时钟对象第二参数持续时间的时钟
System.out.println(clock.millis());
System.out.println(clock2.millis());
System.out.println(clock3.millis());
System.out.println(clock4.millis());
System.out.println(clock5.millis());
}
}
控制台输出
Instant——时间戳,但区别于原生API的Date所维护的fastTime不同,fastTime仅精确到毫秒,而Instant可以精确到纳秒的,其内部是由两个Long字段组成,第一个部分保存的是1970年1月1日开始到现在的秒数,第二部分保存的是纳秒数,值得一提的是第二部分的值永远不会超过999,999,999
简单使用
public class Main {
public static void main(String[] args) {
Instant instant1 = Instant.now();//同Instant.now(Clock.systemUTC())
Instant instant2 = Instant.now(Clock.system(ZoneId.of("Asia/Shanghai")));//获取参数时钟对象时间戳
System.out.println(instant1.getEpochSecond());//精确到秒
System.out.println(instant1.toEpochMilli());//精确到毫秒
System.out.println(instant1.getNano());//获取当前时间戳的纳秒值
System.out.println(instant2.getEpochSecond());//精确到秒
System.out.println(instant2.toEpochMilli());//精确到毫秒
System.out.println(instant2.getNano());//获取当前时间戳的纳秒值
}
}
LocalDate——不含时间的日期
LocalTime——不含日期的时间
LocalDateTime——包含日期和时间
简单使用
public class Main {
public static void main(String[] args) {
//使用系统默认时区创建当前日期时间对象
LocalDateTime localDateTime = LocalDateTime.now();
System.out.println(localDateTime);
//使用自定义时区创建日期时间对象
localDateTime = LocalDateTime.now(ZoneId.of("Asia/Kolkata"));
System.out.println(localDateTime);
//使用LocalDate和LocalTime对象创建日期时间对象
localDateTime = LocalDateTime.of(LocalDate.now(), LocalTime.now());
System.out.println(localDateTime);
//使用自定义时间创建日期时间对象
localDateTime = LocalDateTime.of(2020, 6, 12, 12, 12, 12);
System.out.println(localDateTime);
//通过时间戳获取时间
localDateTime = LocalDateTime.ofEpochSecond(10000, 0, ZoneOffset.UTC);
System.out.println(localDateTime);
//日期时间格式化
String date = localDateTime.format(DateTimeFormatter.ofPattern("yyyy-MM-dd mm:ss"));
System.out.println(date);
//通过日期字符串创建日期时间对象
localDateTime = LocalDateTime.parse("2020-06-12T12:12:12");
System.out.println(localDateTime);
//获取该日期时间对象所对应的年份
System.out.println(localDateTime.getYear());
//获取该日期时间对象所对应的月份
System.out.println(localDateTime.getMonth());
//获取该日期时间对象所相对于年的天数
System.out.println(localDateTime.getDayOfYear());
//获取该日期时间对象所相对于月的天数
System.out.println(localDateTime.getDayOfMonth());
//获取该日期时间对象所相对于星期的天数
System.out.println(localDateTime.getDayOfWeek());
//获取该日期时间对象所对应的时
System.out.println(localDateTime.getHour());
//获取该日期时间对象所对应的分
System.out.println(localDateTime.getMinute());
//获取该日期时间对象所对应的时秒
System.out.println(localDateTime.getSecond());
//获取该日期时间对象所对应的纳秒
System.out.println(localDateTime.getNano());
}
}
ZonedDateTime——包含时区,日期和时间
ZonedDateTime与之前三个类的使用差不多,不过其parse方法可自定义时区
public class Main {
public static void main(String[] args) {
ZonedDateTime zonedDateTime = ZonedDateTime.parse("2020-06-12T12:12:12Z[Europe/Paris]");
System.out.println(zonedDateTime);
}
}