时间类一直是代码开发中经常用到的东西,时间类在JDK中刚出现到国内最常用的1.8版本,一共迭代了三次。分别是Date类、Calendar类和LocalDateTime类。虽然JDK在更新,但是我看到很多的项目还是用着最初的Date类,这期就来讲一下三代时间类的区别。
Date类是JDK1.0时期推出来的第一代时间类,Date类最常用的方式是对获取当前时间,并使用SimpleDateFormat对时间进行格式化,代码如下:
Date date = new Date();
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String stringDate = simpleDateFormat.format(date);
进入Date的构造函数方法中,可以发现目前还未弃用的是传入一个long类型的时间戳,获取到的是这个时间戳对应的Date对象
long timeStamp = 1652619436211L;
Date date = new Date(timeStamp);
另外Date还有一系列已经被废弃的API
如果强制想使用的话也可以用,但是获取当前年份需要+1900,获取当前月份需要+1
date.getYear()+1900
date.getMonth()+1
另外在使用SimpleDateFormat格式化Date类时还需要注意线程安全问题,因为SimpleDateFormat是线程不安全的,一般不要定义为static类型。
JDK1.1推出了Calendar类,用来代替Date类中得到年 月 日 小时等时间元素的api,Calendar提供了一系列获取时间元素的api,并且使用起来也比较简单,通过Calendar.getInstance()获取到Calendar对象,调用一系列API得到时间元素,代码如下:
Calendar calendar = Calendar.getInstance();
System.out.println("年:" + calendar.get(Calendar.YEAR));
// 初始月份是从0开始
System.out.println("月:" + (calendar.get(Calendar.MONTH)+1));
System.out.println("日:" + calendar.get(Calendar.DATE));
System.out.println("小时:" + calendar.get(Calendar.HOUR_OF_DAY));
System.out.println("分钟:" + calendar.get(Calendar.MINUTE));
System.out.println("秒:" + calendar.get(Calendar.SECOND));
System.out.println("毫秒:" + calendar.get(Calendar.MILLISECOND));
System.out.println("今年的第几个星期:" + calendar.get(Calendar.WEEK_OF_YEAR));
System.out.println("这个月的第几个星期:" + calendar.get(Calendar.WEEK_OF_MONTH));
System.out.println("今年的第几天:" + calendar.get(Calendar.DAY_OF_YEAR));
System.out.println("这个月的第几天:" + calendar.get(Calendar.DAY_OF_MONTH));
System.out.println("这个星期的第几天:" + calendar.get(Calendar.DAY_OF_WEEK));
Calendar类的出现并没有替换掉Date类,它更像是对Date类的增强,Date可以作为Calendar设置时间的入参
calendar.setTime(new Date());
可能是Date类并不好用,所以出现了很多第三方的时间库,比如joda time。
一直等到JDK1.8,JDK团队才对时间类做了一次大更新,有意思的是joda time的作者也一起参与了java.time这个包的设计中。这一版的时间类功能强大,并且解决了之前的问题。所以如果你的项目JDK是1.8及以上,可以大方地去使用java.time中提供的类。
java.time包中提供了四个常用的时间类,分别是Instant、LocalDate、LocalTime、LocalDateTime。
Instant中提供了一个更高精度的时间戳,LocalDate获取年-月-日,LocalTime获取时:分:秒.毫秒,LocalDateTime获取年-月-日T时:分:秒.毫秒。下面介绍一下常见的使用方法:
Instant now = Instant.now();
//获取纳秒级别的时间戳
System.out.println(now.toEpochMilli());
LocalDate localDate=LocalDate.now();
LocalTime localTime=LocalTime.now();
LocalDateTime ldt = LocalDateTime.now();
System.out.println(localDate);
System.out.println(localTime);
System.out.println(ldt);
输出的结果如下:
1652621891272
2022-05-15
21:38:11.338
2022-05-15T21:38:11.338
时间格式化类也迎来了更新,DateTimeFormatter是一个线程安全的时间格式化类。
DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
System.out.println(dateTimeFormatter.format(ldt));
另外Calendar中的获取时间元素API,LocalDateTime也同样提供了
System.out.println(ldt.getYear());
System.out.println(ldt.getMonthValue());
System.out.println(ldt.getDayOfMonth());
System.out.println(ldt.getHour());
System.out.println(ldt.getMinute());
System.out.println(ldt.getSecond());
另外还提供了对时间的加减操作,比如加7天和减7天
LocalDateTime plusTime = ldt.plusDays(7);
LocalDateTime minusTime = ldt.minusDays(7);
System.out.println(plusTime);
System.out.println(minusTime);
在数据库中,时间类型有date、datetime、time、timestamp。很多人不知道在Java中如何去接收。我这边的建议是:
date类型使用LocalDate接收;
time类型使用LocalTime接收;
datetime类型使用LocalDateTime接收;
timestamp类型使用LocalDateTime接收;
Calendar
类和LocalDateTime
类都是Java中用于处理日期和时间的类,但它们在设计和功能上有一些不同。以下是它们的一些对比:
优点:
提供了全面的日期和时间管理功能,包括时区、日历系统、节日等。
允许对日期和时间进行复杂的计算,如日期之间的差异、日期的加减等。
支持多种不同的日历系统,如格里高利历、伊斯兰历等。
缺点:
使用相对较为复杂,需要处理时区和日历系统等问题。
不是线程安全的,需要在多线程环境中使用时进行额外的同步处理。
在处理时间时,无法直接获取年、月、日等基本单位,需要先转换为Date对象再进行处理。
优点:
提供了简单的日期和时间表示,易于使用。
支持时区,可以方便地处理不同时区的日期和时间。
是线程安全的,可以在多线程环境中安全使用。
提供了许多实用的方法,如获取年、月、日等基本单位,以及计算日期之间的差异等。
缺点:
不支持日历系统和其他高级功能,如节日管理等。
在处理复杂的日期和时间计算时可能不如Calendar类强大。
总的来说,如果你需要处理复杂的日期和时间计算,或者需要使用不同的日历系统,那么Calendar类可能更适合你。而如果你只需要简单地表示和处理日期和时间,并且希望在多线程环境中安全使用,那么LocalDateTime类可能更适合你。