以前Java版本提供的时间API都不是线程安全的,都是可变的。当多个线程同时操作,就会出现线程安全问题。但是,在Java8之后,提供了新的操作时间的API,这些类都是不可变的,是线程安全的。
下面将用简单的代码,为各位读者展示基本的使用方法。
以上类的实例是不可变的对象,分别表示系统日期、时间、日期和时间,采用ISO 8601(国际标准化组织的国际标准)的日期和时间表示方法。提供了简单的日期或时间,并不包含当前的时间信息,也不包含与时区相关的信息。
@Test
public void test1() {
//获取当前系统时间
LocalDateTime nowDateTime = LocalDateTime.now();
System.out.println(nowDateTime);
//指定时分秒
LocalDateTime newDate = LocalDateTime.of(2019, 7, 28, 14, 46, 51);
System.out.println(newDate);
//加上两年
LocalDateTime years = nowDateTime.plusYears(2);
System.out.println(years);
//加一天
LocalDateTime days = nowDateTime.plusDays(1);
System.out.println(days);
//减两个月
LocalDateTime minusMonths = nowDateTime.minusMonths(2L);
System.out.println(minusMonths);
//获取年
int year = nowDateTime.getYear();
//获取月
int monthValue = nowDateTime.getMonthValue();
//获取日
int dayOfMonth = nowDateTime.getDayOfMonth();
//获取时
int hour = nowDateTime.getHour();
//获取分
int minute = nowDateTime.getMinute();
//获取秒
int second = nowDateTime.getSecond();
System.out.println(year + "-" + monthValue + "-" + dayOfMonth + " " + hour + ":" + minute + ":" + second);
}
结果:
C:\android\java\jdk1.8\bin\java.exe ... 2019-08-01T10:56:47.931 2019-07-28T14:46:51 2021-08-01T10:56:47.931 2019-08-02T10:56:47.931 2019-06-01T10:56:47.931 2019-8-1 10:56:47
上面是一些基本操作,还有很多其他的方法,可以对应API文档,进行学习。
这个类用于在程序中记录事件的时间戳(以Unix元年:1970年1月1日00:00:00),该类在时间线上建立单个瞬时点。
@Test
public void test2() {
//获取UTC 时区
Instant now = Instant.now();
System.out.println(now);
//带偏移量的时间
OffsetDateTime offsetDateTime = now.atOffset(ZoneOffset.ofHours(8));
System.out.println(offsetDateTime);
//毫秒
long milli = now.toEpochMilli();
System.out.println(milli);
//改变秒,从(1970年1月1日00:00:00)开始的秒数
Instant instant = Instant.ofEpochSecond(60);
System.out.println(instant);
Instant maxValue = Instant.MAX;
Instant minValue = Instant.MIN;
System.out.println("最大值范围:" + maxValue + "-最小值范围:" + minValue);
}
结果:
C:\android\java\jdk1.8\bin\java.exe ... 2019-08-01T03:09:09.297Z 2019-08-01T11:09:09.297+08:00 1564628949297 1970-01-01T00:01:00Z 最大值范围:+1000000000-12-31T23:59:59.999999999Z-最小值范围:-1000000000-01-01T00:00:00Z
这个类表示秒或纳秒时间间隔,适合处理较短的时间,需要更高的精确性。
@Test
public void test3() throws InterruptedException {
Instant instant1 = Instant.now();
Thread.sleep(1000L);
Instant instant2 = Instant.now();
//时间间隔
Duration duration = Duration.between(instant1, instant2);
System.out.println(duration.getSeconds());
LocalTime localTime1 = LocalTime.now();
Thread.sleep(1000L);
LocalTime localTime2 = LocalTime.now();
System.out.println(Duration.between(localTime1, localTime2).toMillis());
}
结果:
C:\android\java\jdk1.8\bin\java.exe ... 1 1001
一般用于获取两个日期之间的差。
@Test
public void test4() {
LocalDate localDate1 = LocalDate.now();
LocalDate localDate2 = LocalDate.of(2019, 8, 8);
//获取日期差
Period period = Period.between(localDate1, localDate2);
System.out.println(period.getYears() + ":" + period.getMonths() + ":" + period.getDays());
//判断哪个时间大(false localDate1 早于 localDate2;true,localDate1 晚于 localDate2)
System.out.println(period.isNegative());
}
结果:
C:\android\java\jdk1.8\bin\java.exe ... 0:0:7 false
时间校正器:有的时候需要对时间进行复杂的操作,例如,获取当前日期的"下个周日"、"下个工作日"等等…这些都能通过TemporalAdjuster类来实现。TemporalAdjusters这个工具类就像使用Stream API中的Collectors类一样,通过静态方法提供了大量的常用TemporalAdjuster的实现。
@Test
public void test5() {
LocalDateTime localDateTime = LocalDateTime.now();
System.out.println(localDateTime);
//取本月第10天
LocalDateTime localDateTime1 = localDateTime.withDayOfMonth(10);
System.out.println(localDateTime1);
//获取下一个周日
LocalDateTime localDateTime2 = localDateTime.with(TemporalAdjusters.next(DayOfWeek.SUNDAY));
System.out.println(localDateTime2);
//获取本月最后一天
LocalDateTime localDateTime3 = localDateTime.with(TemporalAdjusters.lastDayOfMonth());
System.out.println(localDateTime3);
//自定义:下一个工作日
LocalDateTime localDateTime5 = localDateTime.with((date) -> {
LocalDateTime localDateTime4 = (LocalDateTime) date;
DayOfWeek dayOfWeek = localDateTime4.getDayOfWeek();
if (dayOfWeek.equals(DayOfWeek.FRIDAY)) {
return localDateTime4.plusDays(3);
} else if (dayOfWeek.equals(DayOfWeek.SATURDAY)) {
return localDateTime4.plusDays(2);
} else {
return localDateTime4.plusDays(1);
}
});
System.out.println(localDateTime5);
}
结果:
C:\android\java\jdk1.8\bin\java.exe ... 2019-08-01T13:17:58.707 2019-08-10T13:17:58.707 2019-08-04T13:17:58.707 2019-08-31T13:17:58.707 2019-08-02T13:17:58.707
此类用于解析和格式化日期或时间。
@Test
public void test6() {
//ISO日期格式化:如"2019-08-01"
DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ISO_DATE;
LocalDateTime localDateTime = LocalDateTime.now();
String startDate = localDateTime.format(dateTimeFormatter);
System.out.println(startDate);
//自定义格式化样式
DateTimeFormatter pattern = DateTimeFormatter.ofPattern("yyyy年MM月dd日 HH:mm:ss");
String patternDate1 = localDateTime.format(pattern);
String patternDate2 = pattern.format(localDateTime);
System.out.println(patternDate1);
//将字符串转换为LocalDateTime对象
LocalDateTime parseDate = LocalDateTime.parse(patternDate2, pattern);
System.out.println(parseDate);
}
结果:
C:\android\java\jdk1.8\bin\java.exe ... 2019-08-01 2019年08月01日 13:20:25 2019-08-01T13:20:25
该类用于表示带时区的日期与时间信息的类。
@Test
public void test7() {
//获取所有时区
Set<String> zoneIds = ZoneId.getAvailableZoneIds();
zoneIds.forEach(System.out::println);
//指定时区构建时间
LocalDateTime localDateTime = LocalDateTime.now(ZoneId.of("America/Cuiaba"));
System.out.println(localDateTime);
LocalDateTime localDateTime1 = LocalDateTime.now();
ZonedDateTime zonedDateTime = localDateTime1.atZone(ZoneId.of("Asia/Shanghai"));
System.out.println(zonedDateTime);
}
结果:
C:\android\java\jdk1.8\bin\java.exe ... 2019-08-01T01:35:12.465 2019-08-01T13:35:12.470+08:00[Asia/Shanghai]
@Test
public void test9() {
Date date = new Date();
Instant instant = date.toInstant();
ZoneId zoneId = ZoneId.systemDefault();
ZonedDateTime zonedDateTime = instant.atZone(zoneId);
LocalDateTime localDateTime = zonedDateTime.toLocalDateTime();
LocalDate localDate = zonedDateTime.toLocalDate();
LocalTime localTime = zonedDateTime.toLocalTime();
System.out.println(localDateTime);
System.out.println(localDate);
System.out.println(localTime);
}
结果:
C:\android\java\jdk1.8\bin\java.exe ... 2019-08-01T13:36:48.767 2019-08-01 13:36:48.767
@Test
public void test10() {
ZoneId zoneId = ZoneId.systemDefault();
ZonedDateTime zonedDateTime1 = LocalDateTime.now().atZone(zoneId);
ZonedDateTime zonedDateTime2 = LocalDate.now().atStartOfDay(zoneId);
Date date1 = Date.from(zonedDateTime1.toInstant());
Date date2 = Date.from(zonedDateTime2.toInstant());
System.out.println(date1);
System.out.println(date2);
}
结果:
C:\android\java\jdk1.8\bin\java.exe ... Thu Aug 01 13:39:39 CST 2019 Thu Aug 01 00:00:00 CST 2019
本篇博文主要对Java8提供的新的时间和日期API做了简单的应用。关于其他方法,或者更复杂的操作,读者可查询Java8 官方文档。
Java8中文版 - 在线API中文手册 - 码工具 :http://www.matools.com/api/java8
上面链接是Java8的中文版文档,但是没有搜索功能,如果使用Google浏览器,可以通过Ctrl + f,输入关键字,来对网页全局搜索。
迷茫的时候,一个人静静,想想过往,终能走出迷茫。