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 3Duration 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。
操作、解析、格式化日期
操作日期
通过
withAttributewith方法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
1ZoneId zoneId = TimeZone.getDefault().toZoneId();
Instant –> LocalDateTime
1LocalDateTime 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