Java8学习六 新的日期和时间API
文章目录
现有API存在问题
Date类
Java 1.0版本,
java.util.Date
。
- 无法表示日期,只能以毫秒的精度表示
- 年份起始为1900,月份起始为0
Calendar类
Java 1.1版本,
java.util.Date
中的很多方法被废弃,取而代之的是java.util.Calendar
。
- 同时存在
Date
和Calendar
两个类,使用比较困惑 DateFormat
中方法有问题(不是线程安全的)
Java8中引入了新的日期时间API
java.time
包,整合了很多Joda-Time的特性。
LocalDate和LocalTime
LocalDate
该类提供日期处理(不包含时间,时区等信息),是一个不可变对象,通过静态工厂方法of创建LocalDate实例。
代码示例
|
|
LocalDate#get()
方法接收一个TemporalField
接口参数,ChronoField
实现了该接口。
LocalTime
时间处理类,通过of
静态工厂方法创建实例。
|
|
LocalDateTime合并日期和时间
LocalDateTime
是LocalDate
和LocalTime
的合体,表示日期和时间,但不包含时区信息。
|
|
机器的日期和时间 Instant
新的java.time.Instant
类对时间建模的方式,是以Unix元年时间(UTC时区1970年1月1日午夜时分)开始所经历的秒数进行计算。可通过ofEpochSecond
静态工厂方法创建实例。
|
|
Duration或Period
Duration
主要用于以秒和纳秒衡量时间的长短。1 2 3
Duration d1 = Duration.between(localDate1, localDate2); Duration d2 = Duration.between(localTime1, localTime2); Duration d3 = Duration.between(localDateTime1, localDateTime2);
1 2 3
// 3分钟 Duration threeMinutes = Duration.ofMinutes(3); threeMinutes = Duration.of(3, ChronoUnit.MINUTES);
Period
以年、月或者日的方式对多个时间单位建模。1 2 3 4 5 6 7 8 9
// 3周 Period threeWeeks = Period.ofWeeks(3); // 9天 Period nineDays = Period.ofDays(9); // 2年6个月1天 Period twoYearsSixMonthsOneDay = Period.of(2, 6, 1); // 10天 Period tenDays = Period.between(LocalDate.of(2018, 9, 11), LocalDate.of(2018, 9, 21));
还包括
from
,parse
,get
等,更多方法查看API。
操作、解析、格式化日期
操作日期
通过
withAttribute
with
方法1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
// 创建日期实例 LocalDate date = LocalDate.of(2013, 3, 8); System.out.println(date); //2013-03-08 //修改年 LocalDate date2 = date.withYear(2018); System.out.println(date2); // 2018-03-08 //修改日 LocalDate date3 = date.withDayOfMonth(9); System.out.println(date3); //2013-03-09 //修改月 LocalDate date4 = date.with(ChronoField.MONTH_OF_YEAR, 10); System.out.println(date4); //2013-10-08 //修改为10月,加2年,减10天 LocalDate date5 = date.with(ChronoField.MONTH_OF_YEAR, 10); date5 = date5.plusYears(2).minusDays(10); System.out.println(date5); //2015-09-28
LocalTime, LocalDateTime也提供了同样类似的方法。
注意: 每次方法调用都会产生一个新对象,对原有对象没有任何影响。
通过
TemporalAdjuster
类1 2 3 4 5 6 7 8 9 10
// 创建日期实例 LocalDate date = LocalDate.of(2013, 3, 8); System.out.println(date); //2013-03-08 System.out.println(date.getDayOfWeek()); //FRIDAY //同一周的星期天 LocalDate date6 = date.with(TemporalAdjusters.nextOrSame(DayOfWeek.SUNDAY)); System.out.println(date6); //2013-03-10 //本月最后一天 LocalDate date7 = date.with(TemporalAdjusters.lastDayOfMonth()); System.out.println(date7); //2013-03-31
可定制实现
TemporalAdjuster
接口1 2 3 4 5 6
@FunctionalInterface public interface TemporalAdjuster { Temporal adjustInto(Temporal temporal); }
解析及格式化日期-时间
日期-时间 -》 字符串,
format
实例方法1 2 3 4
String dateStr1 = date.format(DateTimeFormatter.BASIC_ISO_DATE); System.out.println(dateStr1); //20130308 String dateStr2 = date.format(DateTimeFormatter.ISO_LOCAL_DATE) System.out.println(dateStr2); //2013-03-08
字符串 -》 日期-时间,
parse
静态方法1 2 3 4 5 6
LocalDate date8 = LocalDate.parse("20130308", DateTimeFormatter.BASIC_ISO_DATE); System.out.println(date8); //2013-03-08 LocalDate date9 = LocalDate.parse("2013-03-08", DateTimeFormatter.ISO_LOCAL_DATE); System.out.println(date9); //2013-03-08
自定义格式
1 2 3 4 5
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("dd/MM/yyyy"); String dateStr3 = date.format(formatter); System.out.println(dateStr3); // 08/03/2013 LocalDate date10 = LocalDate.parse(dateStr3, formatter); System.out.println(date10); // 2013-03-08
使用
DateTimeFormatterBuilder
创建复杂的自定义格式1 2 3 4 5 6 7 8
DateTimeFormatter italianFormatter = newDateTimeFormatterBuilder() .appendText(ChronoField.DAY_OF_MONTH) .appendLiteral(". ") .appendText(ChronoField. MONTH_OF_YEAR) .appendLiteral(" ") .appendText(ChronoField. YEAR) .parseCaseInsensitive() .toFormatter(Locale. ITALIAN); String dateStr4 = date.format(italianFormatter); System.out.println(dateStr4); //8. marzo 2013
时区和历法
时区
新的java.time.ZoneId
类替代java.util.TimeZone
1 2 3 4 5 6 7 8 9 10 11 |
ZoneId romeZone = ZoneId.of("Europe/Rome"); LocalDate date = LocalDate.of(2013, 3, 8); ZonedDateTime zdt = date.atStartOfDay(romeZone); System.out.println(zdt); //2013-03-08T00:00+01:00[Europe/Rome] LocalDateTime dateTime = LocalDateTime.of(2018, 9, 21, 15, 23, 29); ZonedDateTime zdt2 = dateTime.atZone(romeZone); System.out.println(zdt2); //2018-09-21T15:23:29+02:00[Europe/Rome] Instant instant = Instant.now(); ZonedDateTime zdt3 = instant.atZone(romeZone); System.out.println(zdt3); //2018-09-21T11:59:59.936+02:00[Europe/Rome] |
TimeZone –> ZoneId
1
ZoneId zoneId = TimeZone.getDefault().toZoneId();
Instant –> LocalDateTime
1
LocalDateTime dateTime1 = LocalDateTime.ofInstant(instant, romeZone);
LocalDateTime –> Instant
1 2
ZoneOffset zoneOffset = ZoneOffset.of("-05:00"); Instant instant1 = dateTime.toInstant(zoneOffset);
ZoneOffset
是ZoneId
的子类,当前时区和UTC/格林尼治的固定偏差。
其它的日历系统
ISO-8601日历系统是世界文明日历系统的事实标准。 但是,Java8中另外还提供了4种其他的日历系统。 分别是ThaiBuddhistDate、MinguoDate、JapaneseDate以及HijrahDate。
文章作者 binbin wen
上次更新 2018-09-22