java8之前时间操作
在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入门
java8新的时间和日期API
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));
时间format、parse
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));
localDateTime与Date转换
新的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);
其他方法
1. adjustInto 调整指定的Temporal和当前LocalDateTime对
2. atOffset 结合LocalDateTime和ZoneOffset创建一个
3. atZone 结合LocalDateTime和指定时区创建一个ZonedD
4. compareTo 比较两个LocalDateTime
5. format 格式化LocalDateTime生成一个字符串
6. from 转换TemporalAccessor为LocalDateTi
7. get 得到LocalDateTime的指定字段的值
8. getDayOfMonth 得到LocalDateTime是月的第几天
9. getDayOfWeek 得到LocalDateTime是星期几
10. getDayOfYear 得到LocalDateTime是年的第几天
11. getHour 得到LocalDateTime的小时
12. getLong 得到LocalDateTime指定字段的值
13. getMinute 得到LocalDateTime的分钟
14. getMonth 得到LocalDateTime的月份
15. getMonthValue 得到LocalDateTime的月份,从1到12
16. getNano 得到LocalDateTime的纳秒数
17. getSecond 得到LocalDateTime的秒数
18. getYear 得到LocalDateTime的年份
19. isAfter 判断LocalDateTime是否在指定LocalDateT
20. isBefore 判断LocalDateTime是否在指定LocalDateT
21. isEqual 判断两个LocalDateTime是否相等
22. isSupported 判断LocalDateTime是否支持指定时间字段或单元
23. minus 返回LocalDateTime减去指定数量的时间得到的值
24. minusDays 返回LocalDateTime减去指定天数得到的值
25. minusHours 返回LocalDateTime减去指定小时数得到的值
26. minusMinutes 返回LocalDateTime减去指定分钟数得到的值
27. minusMonths 返回LocalDateTime减去指定月数得到的值
28. minusNanos 返回LocalDateTime减去指定纳秒数得到的值
29. minusSeconds 返回LocalDateTime减去指定秒数得到的值
30. minusWeeks 返回LocalDateTime减去指定星期数得到的值
31. minusYears 返回LocalDateTime减去指定年数得到的值
32. now 返回指定时钟的当前LocalDateTime
33. of 根据年、月、日、时、分、秒、纳秒等创建LocalDateTi
34. ofEpochSecond 根据秒数(从1970-01-0100:00:00开始)创建L
35. ofInstant 根据Instant和ZoneId创建LocalDateTim
36. parse 解析字符串得到LocalDateTime
37. plus 返回LocalDateTime加上指定数量的时间得到的值
38. plusDays 返回LocalDateTime加上指定天数得到的值
39. plusHours 返回LocalDateTime加上指定小时数得到的值
40. plusMinutes 返回LocalDateTime加上指定分钟数得到的值
41. plusMonths 返回LocalDateTime加上指定月数得到的值
42. plusNanos 返回LocalDateTime加上指定纳秒数得到的值
43. plusSeconds 返回LocalDateTime加上指定秒数得到的值
44. plusWeeks 返回LocalDateTime加上指定星期数得到的值
45. plusYears 返回LocalDateTime加上指定年数得到的值
46. query 查询LocalDateTime
47. range 返回指定时间字段的范围
48. toLocalDate 返回LocalDateTime的LocalDate部分
49. toLocalTime 返回LocalDateTime的LocalTime部分
50. toString 返回LocalDateTime的字符串表示
51. truncatedTo 返回LocalDateTime截取到指定时间单位的拷贝
52. until 计算LocalDateTime和另一个LocalDateTi
53. with 返回LocalDateTime指定字段更改为新值后的拷贝
54. withDayOfMonth 返回LocalDateTime月的第几天更改为新值后的拷贝
55. withDayOfYear 返回LocalDateTime年的第几天更改为新值后的拷贝
56. withHour 返回LocalDateTime的小时数更改为新值后的拷贝
57. withMinute 返回LocalDateTime的分钟数更改为新值后的拷贝
58. withMonth 返回LocalDateTime的月份更改为新值后的拷贝
59. withNano 返回LocalDateTime的纳秒数更改为新值后的拷贝
60. withSecond 返回LocalDateTime的秒数更改为新值后的拷贝
61. withYear 返回LocalDateTime年份更改为新值后的拷贝
以上是常用的一些API,平时工作中需要拿过来查看API,就可以在项目中使用。