前言
最近公司要对一个老系统进行重构、服务拆分,老系统毕竟是几年前的项目了,在重构的过程中发现代码里对日期的操作还是用的Date、Calendar、SimpleDateFormatter 等API,甚至某些地方还存在线程安全问题。
重构项目采用的是 Java8 的最新版本,所以可以使用其新特性 joda-time 来操作日期,使代码更简洁、优雅、安全。
Joda-Time
在 Java8 之前,日期处理是比较繁琐,令人头疼的部分,不仅是复杂的 API 操作,甚至还有线程安全问题。因此,产生了强大的 Joda-Time,可以替换 Java 日期操作的 API,Java8 吸收了Joda-Time 的精华,包含了所有关于日期、时间、日期时间、时区、Instant(跟 Date 类似但精确到纳秒)、duration(持续时间精确到秒)、Period(持续时间精确到天)和时钟操作的类,而且 Joda-Time 这些类都具有可变性,当我们修改一个时间的时候,会返回一个新的对象,这样也解决了线程安全问题。
Clock
CLock 可以用来获取当前的 Instant 、毫秒数等:
1 2 3 4 5 6
| final Clock clock = Clock.systemUTC(); System.out.println(clock.millis()); System.out.println(clock.instant());
final Clock shanghaiClk = Clock.system(ZoneId.of("Asia/Shanghai"));
|
查看`Clock.systemUTC();注释可以得知,这个可以用来替代System.currentTimeMillis()``来获取当前时间的毫秒数
Instant
1 2 3 4 5 6 7 8 9
| Instant instant = Instant.now();
System.out.println(instant.getEpochSecond());
System.out.println(instant.toEpochMilli());
Date date=Date.from(instant);
Instant instant2 = new Date().toInstant();
|
和 Date 类似,但是可以精确到纳秒。
LocalDate、LocalTime、LocalDateTime
获取当地的日期和时间:
1 2 3 4 5 6 7 8 9 10 11 12
| LocalDate localDate = LocalDate.now(); System.out.println(localDate);
System.out.println(localDate.isLeapYear());
System.out.println(localDate.lengthOfMonth());
LocalTime localTime = LocalTime.now(); System.out.println(localTime);
LocalDateTime localDateTime = LocalDateTime.now(); System.out.println(localDateTime);
|
LocalDate 只保留本地当前时间的年月日部分,LocalTIme 保存本地当前时间的后半段部分,而 LocalDateTime 则是完整的当前时间。
这三个类也可以用 of方法来构造:
1 2
| LocalDateTime of = LocalDateTime.of(2019, 3, 16, 11, 10, 10); System.out.println(of);
|
如果需要获得带时区的时间,可以使用 ZonedDateTime(我平时开发基本用不到)。
Duration
用于计算日期的间隔:
1 2 3 4 5
| LocalDateTime from = LocalDateTime.of( 2019, Month.JANUARY, 1, 0, 0, 0 ); LocalDateTime to = LocalDateTime.of( 2019, Month.JANUARY, 1, 0, 0, 0 ); Duration duration = Duration.between(from, to); System.out.println(duration.toDays()); System.out.println(duration.toHours());
|
Duration 也可以使用of来构造。
日期加减等操作
Joda-Time 把日期的加减操作也变得非常简单、易读:
1 2 3 4 5 6 7 8 9 10 11 12
| LocalDateTime localDateTime =LocalDateTime.now();
LocalDateTime plusDays = localDateTime.plusDays(1);
LocalDateTime minusYears = localDateTime.minusYears(1);
LocalDateTime withYear = localDateTime.withYear(2020);
boolean equal = localDateTime.isEqual(withYear); boolean after = localDateTime.isAfter(withYear); boolean before = localDateTime.isBefore(withYear);
|
LocalDateTime 和 String 互转
1 2 3 4 5 6
| LocalDateTime localDateTime =LocalDateTime.now(); String format = localDateTime.format(DateTimeFormatter.ofPattern("yyyy-MM-dd")); System.out.println(format);
String dateStr = "2019-03-16"; LocalDateTime parse = LocalDateTime.parse(dateStr);
|
获取年、月、日、时、分、秒
1 2 3 4 5 6 7 8 9 10
| LocalDateTime localDateTime =LocalDateTime.now();
int year = localDateTime.getYear();
Month month = localDateTime.getMonth(); int monthValue = month.getValue();
int dayOfMonth = localDateTime.getDayOfMonth(); ......
|
获得本月的第一天和最后一天
1 2 3 4 5
| LocalDate today = LocalDate.now();
LocalDate firstday = LocalDate.of(today.getYear(),today.getMonth(),1);
LocalDate lastDay =today.with(TemporalAdjusters.lastDayOfMonth());
|
判断今天是否是生日
做过电商项目的话,这个需求一定很熟悉:用户生日的当天给用户发贺卡,短信生日祝福、生日促销券等,如何判断今天是不是用户的生日呢?可以使用 MonthDay的 API,非常简单地完成判断:
1 2 3 4 5 6 7 8 9 10 11 12
| LocalDate today = LocalDate.now();
LocalDate birthDay = LocalDate.of(1991, 9, 28);
MonthDay birthMonthday = MonthDay.from(birthDay); MonthDay currentMonthDay = MonthDay.from(today); if(currentMonthDay.equals(birthMonthday)){ System.out.println("祝你生日快乐!!"); }else{ System.out.println("今年不是你的生日"); }
|
更多丰富的 API 操作,等后面遇到了会继续补充,未完待续……