在java8之前处理日期和时间的API通常是个让人头疼的问题。比如如果想指定日期,大多数人会这么做:
Calendar cal=Calendar.getInstance(); cal.set(Calendar.HOUR,0); cal.set(Calendar.MINUTE,0); cal.set(Calendar.SECOND,0); Date date=cal.getTime();而上面设置的小时因为有偏移量12的缘故,打印的时间是当天中午12点那一刻的时间,如下所示: 这样以来设置指定时间很繁琐,而且时间格式化SimpleDateFormat又是线程不安全的类,开发中又不得不付出努力来确保线程安全问题,一般会使用ThreadLocal来解决,就像下面这样:
public class DateUtil1 { private static final ThreadLocal<DateFormat> messageFormat = new ThreadLocal<DateFormat>(); private static final String FULL_FORMAT = "yy-MM-dd HH:mm:ss.ms"; private static final DateFormat getDateFormat() { DateFormat format = messageFormat.get(); if (format == null) { format = new SimpleDateFormat(FULL_FORMAT, Locale.getDefault()); messageFormat.set(format); } return format; } }后来接触到第三方库joda-time,这个库封装的一些时间和日期API操作方便易用。如果你对它还不了解的话,不妨可以看一下这篇文章:joda-time入门
14年java8后,新的时间和日期操作与joda-time很相似,这是因为新的日期和时间操作是Stephen Colebourne这个人领导并书写的,而他正是三方库joda-time的作者之一。新的时间API确保了操作时间的线程安全性,原理是:当java.time包内时间类其值发生改变时,其如同String类,类的实例是不可变的对象,当改变其值的时候就会新生成对象地址,从而改变其对象地址,以保证支持多线程操作,新的时间操作和管理大大简化开发对时间操作的需求。
LocateTime、LocateDate、LocateDateTime是新的时间操作API,下面是代码演示:
// 取当前日期: LocalDate today = LocalDate.now(); // 根据年月日取日期: LocalDate crischristmas = LocalDate.of(2019, 06, 25); // 根据字符串取: LocalDate endOfFeb = LocalDate.parse("2019-02-28"); // 严格按照ISO yyyy-MM-dd验证,02写成2都不行,当然也有一个重载方法允许自己定义格式 LocalDate.parse("2019-2-29"); // 无效日期无法通过:DateTimeParseException: Invalid date // 取本月第1天: LocalDate firstDayOfThisMonth = today.with(TemporalAdjusters.firstDayOfMonth()); // 取本月第2天: LocalDate secondDayOfThisMonth = today.withDayOfMonth(2); // 取本月最后一天,再也不用计算是28,29,30还是31: LocalDate lastDayOfThisMonth = today.with(TemporalAdjusters.lastDayOfMonth()); // 取下一天: LocalDate firstDayOf2015 = lastDayOfThisMonth.plusDays(1); // 取2017年1月第一个周一,用Calendar很麻烦: LocalDate firstMondayOf2015 = LocalDate.parse("2017-01-01").with(TemporalAdjusters.firstInMonth(DayOfWeek.MONDAY)); // 2017-01-02 // LocalDateTime常用方法 LocalDate localDate = LocalDate.now(); LocalTime localTime = LocalTime.now(); LocalDateTime localDateTime = LocalDateTime.now(); System.out.println(localDate + "\n" + localTime + "\r" + "\n" + LocalDateTime.now()); // 指定时间例如创建2018-6-18,下午5点半 LocalDateTime time = LocalDateTime.of(2019, 6, 18, 17, 30); System.out.println(time); // 获取时间,Month底层是用枚举实现的 System.out.println(time.getYear() + "年" + time.getMonthValue() + "月" + time.getDayOfMonth() + time.getHour() + "时" + time.getMinute() + "分" + time.getSecond() + "秒"); // 修改时间,设置月中天为13,小时为4 LocalDateTime localDateTime1 = time.withDayOfMonth(13); LocalDateTime loca = time.withHour(4); System.out.println(localDateTime1 + "\n" + loca); // 时间运算plusXXX方法代表向后添加时间,minusXXX代表向后减少时间 System.out.println(time.plusSeconds(5)); System.out.println(time.minusHours(5)); System.out.println(time.compareTo(localDateTime)); System.out.println(time.isBefore(localDateTime)); System.out.println(time.isAfter(localDateTime));JDK8之前的SimpleDateFormat时间格式化存在线程不安全的问题,所幸新提供的DateTimeFormatter 解决了线程不安全的问题,其使用如下所示:
// 时间format LocalDateTime time = LocalDateTime.of(2019, 6, 18, 17, 30); DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"); String format = time.format(dateTimeFormatter); System.out.println(format); // 时间parse System.out.println(LocalDateTime.parse(format, dateTimeFormatter));新的api提供的LocalDateTime非常有用,但是开发的过程中通常有将LocalDateTime转化为java.util.Date的需求,其相互转换如下所示:
Date 转localDateTime // Date 转localDateTime Date date = new Date(); // 将Date转化为Instant Instant instant = date.toInstant(); // 设置Zone时区 ZoneId zoneId = ZoneId.systemDefault(); System.out.println(zoneId.toString()); ZonedDateTime zonedDateTime = instant.atZone(zoneId); // 转化为localDateTime LocalDateTime localDateTime = zonedDateTime.toLocalDateTime(); System.out.println(localDateTime); localDateTime转Date LocalDateTime now =LocalDateTime.now(); LocalDateTime localDateTime = now.minusDays(5).minusHours(28).plusMinutes(33); // 设置Zone时区 ZoneId zoneId = ZoneId.systemDefault(); ZonedDateTime zonedDateTime = localDateTime.atZone(zoneId); Instant instant = zonedDateTime.toInstant(); Date from = Date.from(instant); System.out.println(from);以上是常用的一些API,平时工作中需要拿过来查看API,就可以在项目中使用。