Java8
引入全新的日期和时间API
,主要包括LocalDate
、LocalTime
、LocalDateTime
、Instant
、Duration
以及Period
LocalDate
表示日期
创建日期
// 创建指定日期LocalDate date=LocalDate.of(2020,4,1);// 创建当前日期LocalDate date=LocalDate.now();
获取日期属性
LocalDate date=LocalDate.of(2020,4,1);// 年int year= date.getYear();// 月int month= date.getMonthValue();// 日期int day= date.getDayOfMonth();// 星期几DayOfWeek weekDay= date.getDayOfWeek();// 是否润年boolean leapYear= date.isLeapYear();
LocalTime
表示时间
创建时间
// 创建指定时间LocalTime time=LocalTime.of(13,40,50);// 创建当前时间LocalTime time=LocalTime.now();
获取时间属性
LocalTime time=LocalTime.of(13,40,50);// 小时int hour= time.getHour();// 分钟int minute= time.getMinute();// 秒int second= time.getSecond();
LocalDateTime
表示日期 + 时间,即有日期也有时间
创建日期时间
// 创建指定日期时间LocalDateTime time=LocalDateTime.of(2020,4,1,13,40,50);// 使用日期+时间进行创建LocalDateTime time=LocalDateTime.of(date, time);// 创建当前日期时间LocalDateTime time=LocalDateTime.now();
获取属性
LocalDateTime
也可以通过日期或者时间的get
方法,获取年、月、日、时、分、秒属性
LocalDateTime dt=LocalDateTime.of(2020,4,1,13,40,50);// 日期LocalDate date= dt.toLocalDate();// 时间LocalTime time= dt.toLocalTime();
Instant
表示时间戳,记录从1970-01-01 00:00:00
时间以来的毫秒数。
创建时间戳
// 使用毫秒数进行构建Instant ins=Instant.ofEpochMilli(100);// 使用秒数进行构建Instant ins=Instant.ofEpochSecond(600);// 创建当前时间戳Instant ins=Instant.now();
Duration
及Period
都可以表示时间段。
创建Duration
时间段
Duration
以秒和纳秒衡量时间的长短,Duration
的between
方法不支持LocalDate
// 使用两个日期或者时间创建时间段Duration duration=Duration.between(time1, time2);Duration duration=Duration.between(dateTime1, dateTime2);Duration duration=Duration.between(instant1, instant2);// 创建单纯的时间段Duration threeMinutes=Duration.ofMinutes(3);Duration threeMinutes=Duration.of(3,ChronoUnit.MINUTES);
获取Duration
属性
// 获取时间段的总天数long diffDays= duration.toDays()// 获取时间段的总小时数long diffHours= duration.toHours()// 获取时间段的总分钟数long diffMinutes= duration.toMinutes()// 获取时间段的总秒数long diffSeconds= duration.toSeconds()// 获取时间段的总毫秒数long diffMillis= duration.toMillis()
Period
以年-月-日
多个时间单位表示时间段。
创建Period
时间段
// 使用两个日期创建时间段Period period=Period.between(date1, date2);// 使用单纯的时间段Period oneYear=Period.ofYears(1);Period oneYear=Period.of(1,0,0);
获取Period
属性
// 年long diffYears= period.getYears()// 月long diffMonth= duration.getMonths()// 日long diffDays= duration.getDays()
示例
Period period=Period.between(LocalDate.of(2020,10,8),LocalDate.of(2021,10,6));System.out.println(period.getYears());// 1System.out.println(period.getMonths());// 0System.out.println(period.getDays());// -2
Java8
为日期提供了非常方便地操作API
设置属性
可以通过with
方法设置某个属性的值。但如果日期对象不支持设置的属性,则会抛出UnsupportedTemporalTypeException
,比如设置LocalDate
对象的ChronoField.NANO_OF_SECOND
属性。
LocalDate date1=LocalDate.of(2021,4,1);// 2021-04-01LocalDate date2= date1.withYear(2011);// 2011-04-01LocalDate date3= date2.withDayOfMonth(25);// 2011-04-25LocalDate date4= date3.with(ChronoField.MONTH_OF_YEAR,9);// 2011-09-25
日期增减
通过plus
及minus
方法进行日期的增减操作
LocalDate date1=LocalDate.of(2021,4,1);// 增加一个星期LocalDate date2= date1.plusWeeks(1);// 减三年LocalDate date3= date2.minusYears(3);// 增加六个月LocalDate date4= date3.plus(6,ChronoUnit.MONTHS);
使用TemporalAdjuster
目前使用的日期操作方法都是比较直接的,但有时需要一些更复杂的操作,比较:将日期调整为下个周日,调整为当月最后一天,这时可以使用with
方法的重载版本,传入一个TemporalAdjuster
对象,可以更加灵活地处理日期。
LocalDate date1=LocalDate.of(2021,4,1);// 当月最后一天LocalDate date2= date1.with(TemporalAdjusters.lastDayOfMonth());// 当前日期最近的一个星期天LocalDate date3= date1.with(TemporalAdjusters.nextOrSame(DayOfWeek.SUNDAY));
方法名 | 描述 |
---|---|
dayOfWeekInMonth | 同一个月中每一周的第几天 |
firstDayOfMonth | 当月的第一天 |
firstDayOfNextMonth | 下月的第一天 |
firstDayOfNextYear | 明年的第一天 |
firstDayOfYear | 当年的第一天 |
firstInMonth | 同一个月中,第一个符合星期几要求的值 |
lastDayOfMonth | 当月的最后一天 |
lastDayOfNextMonth | 下月的最后一天 |
lastDayOfNextYear | 明年的最后一天 |
lastDayOfYear | 今年的最后一天 |
lastInMonth | 同一个月中,最后一个符合星期几要求的值 |
next/previous | 日期调整后或者调整前,第一个符合指定星期几要求的日期 |
nextOrSame/previousOrSame | 日期调整后或者调整前,第一个符合指定星期几要求的日期,如果该日期已经符合要求,直接返回该对象 |
日期解析以及日期格式化也是日期的一个非常重要的功能。Java8
提供了DateTimeFormatter
类用来辅助格式化。DateTimeFormatter
提供了几个国际化格式,但通常我们更多地使用ofPattern
创建自定义格式。
格式化输出
LocalDate date=LocalDate.of(2021,4,1);String s1= date.format(DateTimeFormatter.BASIC_ISO_DATE);// 20210401String s2= date.format(DateTimeFormatter..ofPattern("yyyy-MM-dd"));// 2021-04-01
解析字符串
LocalDate date1=LocalDate.parse("20210401",DateTimeFormatter.BASIC_ISO_DATE);LocalDate date2=LocalDate.parse("2021-04-01",DateTimeFormatter..ofPattern("yyyy-MM-dd"));
前文中出现的所有日期、时间类型都不包含时区信息,Java8
提供了java.time.ZoneId
类来进行时区处理,用于代替老版的java.util.TimeZone
。时区是按照一定的规则将区域划分成的标准时间相同的区间,每个特定的ZoneId
对象都由一个地区ID
标识
ZoneId romeZone=ZoneId.of("Europe/Rome");
原来的TimeZone
也可以转换为ZoneId
ZoneId zoneId=TimeZone.getDefault().toZoneId();
一旦得到一个ZoneId
对象,你就可以将它与LocalDate
、LocalDateTime
或者Instant
对象整合起来,构造为一个ZonedDateTime
实例,它代表了相对于指定时区的时间点。
LocalDate date=LocalDate.of(2020,Month.MARCH,1);ZonedDateTime zdt1= date.atStartOfDay(romeZone);LocalDateTime dateTime=LocalDateTime.of(2020,Month.MARCH,1,12,30);ZonedDateTime zdt2= dateTime.atZone(romeZone);Instant instant=Instant.now();ZonedDateTime zdt3= instant.atZone(romeZone);
通过ZoneId
也可以实现LocalDateTime
与Instant
间的转换
Instant instant=LocalDateTime.now().toInstant(romeZone);LocalDateTime ldt=LocalDateTime.ofInstant(Instant.now(), romeZone);
日期系统默认使用ISO-8601
日历系统,即世界文明日历系统(阳历),Java8
也提供了 4 种其它的日历系统,每个日历系统都有一个对应的日期类:ThaiBuddhistDate
、MinguoDate
、JapaneseDate
及HijrahDate
。
LocalDate date=LocalDate.of(2020,Month.MARCH,18);JapaneseDate japaneseDate=JapaneseDate.from(date);