Java8新特性——新时间日期API
在Java8之前,时间日期API存在线程安全的问题,多线程情况下需要加锁,并且使用起来也比较不方便。Java8为我们提供了新的时间日期API。这篇文章,我们一起来使用下。
1. 使用LocalDate、LocalTime、LocalDateTime
LocalDate
、 LocalTime
、 LocalDateTime
类的实例是不可变的对象,分别表示使用ISO-8601日历系统的日期、时间、日期和时间。它们提供了简单的日期或时间,并不包含当前的时间信息。也不包含与时区相关的信息。
注: ISO-8601日历系统是国际标准化组织制定的现代公民的日期和时间的表示法
接下来,我们就以LocalDateTime
为例,其它2个类使用方法一样,这里不再赘述。
- 获取当前时间:
/**
* 获取当前时间
*/
@Test
public void test1() {
LocalDateTime now = LocalDateTime.now();
System.out.println(now);
}
Output:
2019-05-30T21:36:49.269
- 根据字符串创建指定日期对象
/**
* 创建指定日期
*/
@Test
public void test2(){
LocalDateTime dateTime = LocalDateTime.of(2019, 5, 30, 21, 41, 10);
System.out.println(dateTime);
}
Output:
2019-05-30T21:41:10
- 日期加减运算
/**
* 日期加减运算
*/
@Test
public void test3(){
LocalDateTime now = LocalDateTime.of(2019, 5, 30, 21, 45, 10);
LocalDateTime plusTime = now.plusYears(1) // 加一年
.plusMonths(2) // 加2月
.plusDays(3) // 加三天
.plusHours(4) // 加4小时
.plusMinutes(5) // 加5分钟
.plusSeconds(6); // 加6秒
System.out.println(plusTime);
LocalDateTime minusTime = now.minusYears(1) // 减一年
.minusMonths(2) // 减2月
.minusDays(3) // 减 3天
.minusHours(4) // 减4小时
.minusMinutes(5) // 减5分钟
.minusSeconds(6); // 减6秒
System.out.println(minusTime);
}
Output:
2020-08-03T01:50:16
2018-03-27T17:40:04
- 指定年份、月份、天数返回新的日期
/**
* 修改月份天数、月份、年份为指定值返回新的LocalDate对象
*/
@Test
public void test4(){
LocalDate today = LocalDate.of(2019, 5, 30);
LocalDate date = today.withYear(2020) // 将年份修改为2010年
.withMonth(10) // 修改月份为10月
.withDayOfMonth(24); // 修改月份天数为24号
System.out.println(date);
}
Output:
2020-10-24
- 获取日期年月日等
/**
* 获取日期年月日等
*/
@Test
public void test5(){
LocalDate today = LocalDate.of(2019, 5, 30);
System.out.println(today.getDayOfMonth()); // 月份天数(1-31)
System.out.println(today.getDayOfYear()); // 年份天数(1-366)
System.out.println(today.getDayOfWeek()); // 星期几(返回一个DayOfWeek枚举值)
System.out.println(today.getMonth()); // 月份,返回一个Month枚举值
System.out.println(today.getMonthValue()); // 返回具体的月份值(1-12)
System.out.println(today.getYear()); // 返回年份的具体值,如2019
}
Output:
30
150
THURSDAY
MAY
5
2019
- until获取2个日期间的Period对象或者指定的ChronoUnit的数字
/**
* until获取2个日期间的Period对象或者指定的ChronoUnit的数字
*/
@Test
public void test6(){
LocalDate date = LocalDate.of(2018, 10, 24);
LocalDate today = LocalDate.of(2019, 5, 30);
Period period = date.until(today);
System.out.println(period);
long until = date.until(LocalDate.of(2018, 5, 21), ChronoUnit.MONTHS); // 2个日期间,按月相差多少
System.out.println(until);
}
Output:
P7M6D // 相差7个月6天
-5 // 小5个月
- 比较2个LocalDate前后
/**
* 比较2个LocalDate前后
*/
@Test
public void test7(){
LocalDate date1 = LocalDate.of(2018, 5, 21);
LocalDate date2 = LocalDate.of(2018, 10, 24);
System.out.println(date1.isBefore(date2)); // date1在date2之前?返回true
System.out.println(date2.isAfter(date1)); // date2在date1之后?返回true
}
- 判断是否闰年
/**
* 判断是否闰年
*/
@Test
public void test8(){
LocalDate date1 = LocalDate.of(2020, 5, 21);
LocalDate date2 = LocalDate.of(2019, 5, 30);
System.out.println(date1.isLeapYear()); // true
System.out.println(date2.isLeapYear()); // false
}
2. Instant 时间戳
用于“时间戳”的运算。它是以Unix元年(传统的设定为UTC时区1970年1月1日午夜时分)开始所经历的描述进行运算
- 获取当前时间戳
/**
* Instant获取当前时间戳
*/
@Test
public void test9(){
long milli = Instant.now().toEpochMilli();
System.out.println(milli);
System.out.println(System.currentTimeMillis());
}
Output:
1559226655246
1559226655246
3. Duration 和 Period
- Duration:用于计算两个“时间”间隔
/**
* Duration计算2个时间差
*/
@Test
public void test10(){
LocalDateTime now = LocalDateTime.of(2019, 5, 30, 22, 32, 10);
LocalDateTime time = LocalDateTime.of(2019, 5, 30, 10, 20, 11);
Duration duration = Duration.between(time, now);
System.out.println(duration);
}
Output:
PT12H11M59S // 相差12小时11分钟59秒
- Period:用于计算两个“日期”间隔
/**
* 计算2个LocalDate之间差
*/
@Test
public void test11(){
LocalDate today = LocalDate.of(2019, 5, 30);
LocalDate date = LocalDate.of(2018, 3, 27);
Period period = Period.between(date, today);
System.out.println(period);
}
Output:
P1Y2M3D // 相差1年2月3天
4. 日期的操纵
TemporalAdjuster : 时间校正器。有时我们可能需要获取例如:将日期调整到“下个周日”等操作。
TemporalAdjusters : 该类通过静态方法提供了大量的常用 TemporalAdjuster 的实现。
/**
* 下一个周五
*/
@Test
public void test12(){
LocalDate nextFri = LocalDate.now().with(TemporalAdjusters.next(DayOfWeek.FRIDAY));
System.out.println(nextFri);
}
5. 解析与格式化
ava.time.format.DateTimeFormatter 类:该类提供了三种格式化方法:
- 预定义的标准格式
/**
* The printer and/or parser to use, not null.
*/
private final CompositePrinterParser printerParser;
/**
* The locale to use for formatting, not null.
*/
private final Locale locale;
/**
* The symbols to use for formatting, not null.
*/
private final DecimalStyle decimalStyle;
/**
* The resolver style to use, not null.
*/
private final ResolverStyle resolverStyle;
/**
* The fields to use in resolving, null for all fields.
*/
private final Set<TemporalField> resolverFields;
/**
* The chronology to use for formatting, null for no override.
*/
private final Chronology chrono;
/**
* The zone to use for formatting, null for no override.
*/
private final ZoneId zone;
- 语言环境相关的格式
- 自定义的格式
/**
* 自定义格式化日期
*/
@Test
public void test13(){
LocalDateTime now = LocalDateTime.now();
DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyyMMdd HH:mm:ss");
String time = now.format(dtf);
System.out.println(time);
LocalDateTime dateTime = LocalDateTime.parse("20181024 20:21:22", dtf);
System.out.println(dateTime);
}
Output:
20190530 22:49:48
2018-10-24T20:21:22
6. 时区的处理
Java8 中加入了对时区的支持,带时区的时间为分别为:
ZonedDate、 ZonedTime、 ZonedDateTime
其中每个时区都对应着 ID,地区ID都为 “{区域}/{城市}”的格式
例如 : Asia/Shanghai 等
ZoneId:该类中包含了所有的时区信息
getAvailableZoneIds() : 可以获取所有时区时区信息
of(id) : 用指定的时区信息获取 ZoneId 对象
7. 与传统日期处理的转换
类 | To 遗留类 | From 遗留类 |
---|---|---|
java.time.Instant java.util.Date | Date.from(instant) | date.toInstant() |
java.time.Instant java.sql.Timestamp | Timestamp.from(instant) | timestamp.toInstant() |
java.time.ZonedDateTime java.util.GregorianCalendar | GregorianCalendar.from(zonedDateTim e) | cal.toZonedDateTime() |
java.time.LocalDate java.sql.Time | Date.valueOf(localDate) | date.toLocalDate() |
java.time.LocalTime java.sql.Time | Date.valueOf(localDate) | date.toLocalTime() |
java.time.LocalDateTime java.sql.Timestamp | Timestamp.valueOf(localDateTime) | timestamp.toLocalDateTime() |
java.time.ZoneId java.util.TimeZone | Timezone.getTimeZone(id) | timeZone.toZoneId() |
java.time.format.DateTimeFormatter java.text.DateFormat | formatter.toFormat() | 无 |