20191227 Java8 日期时间API
背景
Java 8通过发布新的Date-Time API (JSR 310)来进一步加强对日期与时间的处理。
在旧版的 Java 中,日期时间 API 存在诸多问题,其中有:
- 非线程安全 ? java.util.Date 是非线程安全的,所有的日期类都是可变的,这是Java日期类最大的问题之一。
- 设计很差 ? Java的日期/时间类的定义并不一致,在java.util和java.sql的包中都有日期类,此外用于格式化和解析的类在java.text包中定义。java.util.Date同时包含日期和时间,而java.sql.Date仅包含日期,将其纳入java.sql包并不合理。另外这两个类都有相同的名字,这本身就是一个非常糟糕的设计。
- 时区处理麻烦 ? 日期类并不提供国际化,没有时区支持,因此Java引入了java.util.Calendar和java.util.TimeZone类,但他们同样存在上述所有的问题。
Java 8 在 java.time
包下提供了很多新的 API。以下为两个比较重要的 API:
- Local(本地) ? 简化了日期时间的处理,没有时区的问题。
- Zoned(时区) ? 通过制定的时区处理日期时间。
新的java.time包涵盖了所有处理日期,时间,日期/时间,时区,时刻(instants),过程(during)与时钟(clock)的操作。
LocalDateTime, LocalDate, LocalTime
这三者是本地化日期时间API
- LocalDateTime 包含日期和时间,比如:2018-09-24 10:32:10
- LocalDate 只包含日期,比如:2018-09-24
- LocalTime 只包含时间,比如:10:32:10
private void testLocalDateTime() { System.out.println("=================== testLocalDateTime ============================"); // 获取当前的日期时间 LocalDateTime localDateTime = LocalDateTime.now(); System.out.println("当前日期时间: " + localDateTime); System.out.println("当前日期: " + localDateTime.toLocalDate()); System.out.println("当前时间: " + localDateTime.toLocalTime()); System.out.println(",================== get ============================="); // get // 获取日期时间的单项值 int year = localDateTime.get(ChronoField.YEAR); Month month = localDateTime.getMonth(); int monthValue = localDateTime.getMonthValue(); int dayOfYear = localDateTime.getDayOfYear(); int dayOfMonth = localDateTime.getDayOfMonth(); DayOfWeek dayOfWeek = localDateTime.getDayOfWeek(); int hour = localDateTime.getHour(); int minute = localDateTime.getMinute(); int seconds = localDateTime.getSecond(); int nano = localDateTime.getNano(); System.out.println("year:" + year); System.out.println("month:" + month); System.out.println("monthValue:" + monthValue); System.out.println("dayOfYear:" + dayOfYear); System.out.println("dayOfMonth:" + dayOfMonth); System.out.println("dayOfWeek:" + dayOfWeek); System.out.println("hour:" + hour); System.out.println("minute:" + minute); System.out.println("seconds:" + seconds); System.out.println("nano:" + nano); System.out.println(",================== with, plus, minus ============================="); LocalDateTime withDateTime = localDateTime.with(ChronoField.YEAR, 2000).withMonth(10); System.out.println("withDateTime: " + withDateTime); LocalDateTime plusLocalDateTime = localDateTime.plus(1, ChronoUnit.MONTHS); System.out.println("plusLocalDateTime: " + plusLocalDateTime); LocalDateTime minusLocalDateTime = localDateTime.minusDays(1); System.out.println("minusLocalDateTime: " + minusLocalDateTime); System.out.println(",================== of ============================="); // of // 通过指定值获取指定日期 LocalDateTime ofLocalDateTime = LocalDateTime.of(2019, 12, 27, 15, 8, 7); System.out.println("ofLocalDateTime:" + ofLocalDateTime); LocalDate ofLocalDate = LocalDate.of(2014, Month.DECEMBER, 12); System.out.println("ofLocalDate: " + ofLocalDate); LocalTime ofLocalTime = LocalTime.of(22, 15); System.out.println("ofLocalTime: " + ofLocalTime); System.out.println(",================== parse ============================="); // parse // 将字符串解析为日期、时间 LocalDateTime parseDateTime = LocalDateTime.parse("2019-11-01T20:15:30.001"); System.out.println("parseDateTime: " + parseDateTime); LocalDate parseDate = LocalDate.parse("2019-11-01"); System.out.println("parseDate: " + parseDate); LocalTime parseTime = LocalTime.parse("20:15:30"); System.out.println("parseTime: " + parseTime); System.out.println(",================== isAfter, isBefore ============================="); boolean isAfter = localDateTime.isAfter(localDateTime.minusDays(1)); System.out.println("isAfter: " + isAfter); boolean isBefore = localDateTime.isBefore(localDateTime.minusDays(1)); System.out.println("isBefore: " + isBefore); System.out.println("================== LocalDate ============================="); LocalDate localDate = LocalDate.now(); System.out.println("localDate:" + localDate); int lengthOfMonth = localDate.lengthOfMonth(); System.out.println("该月天数:" + lengthOfMonth); boolean isLeapYear = localDate.isLeapYear(); // false System.out.println("是否闰年:" + isLeapYear); LocalDateTime dateTime = localDate.atTime(5, 6); System.out.println("转为LocalDateTime:" + dateTime); System.out.println("================== LocalTime ============================="); LocalTime localTime = LocalTime.now(); System.out.println("localTime:" + localTime); LocalDateTime localDateTime1 = localTime.atDate(localDate); System.out.println("转为LocalDateTime:" + localDateTime1); }
ZonedDateTime
带时区的日期时间
private void testZonedDateTime() { System.out.println("=================== testZonedDateTime ============================"); // 获取当前时间日期 ZonedDateTime date1 = ZonedDateTime.parse("2015-12-03T10:15:30+05:30[Asia/Shanghai]"); System.out.println("date1: " + date1); ZoneId id = ZoneId.of("Europe/Paris"); System.out.println("ZoneId: " + id); ZoneId currentZone = ZoneId.systemDefault(); System.out.println("当期时区: " + currentZone); }
MonthDay
MonthDay只包含月日信息,可以用于存放类似于生日,结婚纪念日等信息。
private void testMonthDay() { System.out.println("=================== testMonthDay ============================"); LocalDate birthday = LocalDate.of(1999, 12, 27); MonthDay monthDay = MonthDay.of(birthday.getMonth(), birthday.getDayOfMonth()); System.out.println("monthDay:" + monthDay); MonthDay fromMonthDay = MonthDay.from(LocalDate.now()); System.out.println("MonthDay.from(LocalDate.now()):" + fromMonthDay); if (fromMonthDay.equals(monthDay)) { System.out.println("happy birthday!"); } else { System.out.println("not birthday!"); } }
Period
Period用于计算两个LocalDate之间的时长。
private void testPeriod() { System.out.println("=================== testPeriod ============================"); LocalDate date1 = LocalDate.of(2018, 9, 30); LocalDate date2 = LocalDate.of(2018, 10, 31); Period period = Period.between(date1, date2); System.out.println("period:" + period); List<TemporalUnit> units = period.getUnits(); System.out.println("units:" + units); int months = period.getMonths(); int days = period.getDays(); System.out.println("months:" + months); System.out.println("days:" + days); }
Duration
Duration用于计算两个LocalTime或者LocalDateTime的时间差。
private void testDuration() { System.out.println("=================== testDuration ============================"); LocalDateTime dateTime1 = LocalDateTime.now(); LocalDateTime dateTime2 = LocalDateTime.now().plusSeconds(60 * 60 * 2 + 1).minusNanos(1000000); Duration duration = Duration.between(dateTime1, dateTime2); System.out.println("duration:" + duration); List<TemporalUnit> units = duration.getUnits(); System.out.println("duration.getUnits():" + units); long seconds = duration.getSeconds(); System.out.println("duration.getSeconds():" + seconds); long nano = duration.getNano(); System.out.println("duration.getNano():" + nano); boolean isZero = duration.isZero(); System.out.println("duration.isZero():" + isZero); long hours = duration.toHours(); System.out.println("duration.toHours():" + hours); Duration abs = duration.abs(); System.out.println("duration.abs():" + abs); boolean isNegative = duration.isNegative(); System.out.println("duration.isNegative():" + isNegative); Duration withDuration = duration.withSeconds(5); System.out.println("duration.withSeconds(5):" + withDuration); Duration plusNanos = duration.plusNanos(1000000); System.out.println("duration.plusNanos(1000000):" + plusNanos); }
Instant
时间戳。
private void testInstant() { System.out.println("=================== testInstant ============================"); Instant instant = Instant.now(); System.out.println("instant:" + instant); // 获取毫秒数 long toEpochMilli = instant.toEpochMilli(); System.out.println("toEpochMilli:" + toEpochMilli); }
Clock
Clock 通过指定一个时区,然后就可以获取到当前的时刻,日期与时间。可以替代 System.currentTimeMillis() 与 TimeZone.getDefault() 。
private void testClock() { System.out.println("=================== testClock ============================"); Clock clock = Clock.systemDefaultZone(); System.out.println("Clock.systemDefaultZone():" + clock); Instant instant = clock.instant(); System.out.println("clock.instant():" + instant); }
ZoneId, ZoneOffset, ZoneRegion
对时区的操作。
ZoneId是抽象类,是ZoneOffset和ZoneRegion的父类。
private void testZone() { System.out.println("=================== testZone ============================"); System.out.println(",=================== ZoneId ============================"); Set<String> set = ZoneId.getAvailableZoneIds(); System.out.println("ZoneId.getAvailableZoneIds():" + Arrays.toString(set.toArray())); System.out.println(",,=================== ZoneOffset ============================"); ZoneId systemDefaultZoneId = ZoneId.systemDefault(); System.out.println("ZoneId.systemDefault():" + systemDefaultZoneId); ZoneId ofZoneId = ZoneId.of("Asia/Aden"); System.out.println("ofZoneId.getClass():" + ofZoneId.getClass()); System.out.println("ZoneId.of(\"Asia/Aden\"):" + ofZoneId); System.out.println(",,=================== ZoneRegion ============================"); ZoneId ofZoneRegion = ZoneId.of("+8"); System.out.println("ofZoneRegion.getClass():" + ofZoneRegion.getClass()); System.out.println("ZoneId.of(\"+8\"):" + ofZoneRegion); }
TemporalAdjuster, TemporalAdjusters
用于调整日期时间。
TemporalAdjuster 是函数式接口,TemporalAdjusters 是工具类。
private void testTemporalAdjusters() { System.out.println("=================== testTemporalAdjusters ============================"); LocalDateTime localDateTime = LocalDateTime.now(); System.out.println("当前时间:" + localDateTime); TemporalAdjuster temporalAdjuster = null; System.out.println("=================== first, last ============================"); temporalAdjuster = TemporalAdjusters.firstInMonth(DayOfWeek.FRIDAY); this.adjustDateTime("当月的第一个星期五", temporalAdjuster); temporalAdjuster = TemporalAdjusters.firstDayOfMonth(); this.adjustDateTime("当月的第一天", temporalAdjuster); temporalAdjuster = TemporalAdjusters.firstDayOfNextMonth(); this.adjustDateTime("下个月的第一天", temporalAdjuster); temporalAdjuster = TemporalAdjusters.lastInMonth(DayOfWeek.FRIDAY); this.adjustDateTime("当月的最后一个星期五", temporalAdjuster); temporalAdjuster = TemporalAdjusters.lastDayOfMonth(); this.adjustDateTime("当月的最后一天", temporalAdjuster); temporalAdjuster = TemporalAdjusters.lastDayOfYear(); this.adjustDateTime("当年的最后一天", temporalAdjuster); System.out.println("=================== next, previous ============================"); // next:如果当天是周五,返回下一个周五 // nextOrSame:如果当天是周五,返回当天 temporalAdjuster = TemporalAdjusters.next(DayOfWeek.FRIDAY); this.adjustDateTime("下一个周五", temporalAdjuster); temporalAdjuster = TemporalAdjusters.nextOrSame(DayOfWeek.FRIDAY); this.adjustDateTime("下一个周五", temporalAdjuster); // previous:如果当天是周五,返回上一个周五 // previousOrSame:如果当天是周五,返回当天 temporalAdjuster = TemporalAdjusters.previous(DayOfWeek.FRIDAY); this.adjustDateTime("上一个周五", temporalAdjuster); temporalAdjuster = TemporalAdjusters.previousOrSame(DayOfWeek.FRIDAY); this.adjustDateTime("上一个周五", temporalAdjuster); System.out.println("=================== dayOfWeekInMonth ============================"); temporalAdjuster = TemporalAdjusters.dayOfWeekInMonth(3, DayOfWeek.SUNDAY); this.adjustDateTime("当月的第三个星期日", temporalAdjuster); System.out.println("=================== ofDateAdjuster ============================"); temporalAdjuster = TemporalAdjusters.ofDateAdjuster(localDate -> localDate.minusDays(1)); this.adjustDateTime("昨天", temporalAdjuster); } private void adjustDateTime(String desc, TemporalAdjuster temporalAdjuster) { LocalDateTime localDateTime = LocalDateTime.now(); LocalDateTime with = localDateTime.with(temporalAdjuster); System.out.println(desc + ":" + with); }
DateTimeFormatter
用于格式化日期时间
private void testDateTimeFormatter() { System.out.println("=================== testDateTimeFormatter ============================"); DateTimeFormatter dateTimeFormatter = null; System.out.println(",=================== ofLocalizedDateTime ============================"); // FormatStyle.FULL 带时区信息,不能用于 LocalDateTime dateTimeFormatter = DateTimeFormatter.ofLocalizedDateTime(FormatStyle.FULL); this.formatDateTime("ofLocalizedDateTime(FormatStyle.FULL):", dateTimeFormatter); dateTimeFormatter = DateTimeFormatter.ofLocalizedDateTime(FormatStyle.LONG); this.formatDateTime("ofLocalizedDateTime(FormatStyle.LONG):", dateTimeFormatter); dateTimeFormatter = DateTimeFormatter.ofLocalizedDateTime(FormatStyle.MEDIUM); this.formatDateTime("ofLocalizedDateTime(FormatStyle.MEDIUM):", dateTimeFormatter); dateTimeFormatter = DateTimeFormatter.ofLocalizedDateTime(FormatStyle.SHORT); this.formatDateTime("ofLocalizedDateTime(FormatStyle.SHORT):", dateTimeFormatter); System.out.println(",=================== ofPattern ============================"); dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy MM dd"); this.formatDateTime("ofPattern(\"yyyy MM dd\"):", dateTimeFormatter); System.out.println(",=================== 静态常量 DateTimeFormatter ============================"); dateTimeFormatter = DateTimeFormatter.BASIC_ISO_DATE; this.formatDateTime("BASIC_ISO_DATE:", dateTimeFormatter); dateTimeFormatter = DateTimeFormatter.ISO_DATE_TIME; this.formatDateTime("ISO_DATE_TIME:", dateTimeFormatter); } private void formatDateTime(String desc, DateTimeFormatter dateTimeFormatter) { ZonedDateTime zonedDateTime = ZonedDateTime.now(); String format = zonedDateTime.format(dateTimeFormatter); System.out.println(desc + ":" + format); }
与 java.util.Date 的相互转换
private void testConvert() { System.out.println("=================== testConvert ============================"); System.out.println(",=================== LocalDateTime 转 java.util.Date ============================"); LocalDateTime localDateTime = LocalDateTime.now(); System.out.println("localDateTime:" + localDateTime); Instant instant = localDateTime.atZone(ZoneId.systemDefault()).toInstant(); Date fromDate = Date.from(instant); System.out.println("fromDate:" + fromDate); System.out.println(",=================== java.util.Date 转 LocalDateTime ============================"); Date date = new Date(); System.out.println("date:" + date); Instant toInstant = date.toInstant(); LocalDateTime ofLocalDateTime = LocalDateTime.ofInstant(toInstant, ZoneId.systemDefault()); System.out.println("ofLocalDateTime:" + ofLocalDateTime); }
参考资料
相关推荐
xiaouncle 2020-07-31
染血白衣 2020-11-16
SAMXIE 2020-11-04
一个智障 2020-11-15
学习web前端 2020-11-09
yiranpiaoluo 2020-11-04
lxhuang 2020-11-03
88274956 2020-11-03
82387067 2020-11-03
huangliuyu00 2020-10-29
sichenglain 2020-10-27
Dayer 2020-10-27
小马的学习笔记 2020-10-23
liuweiITlove 2020-10-14
kjyiyi 2020-10-10
fanjunjaden 2020-10-09
zhyue 2020-09-28
huangliuyu00 2020-09-24
88397813 2020-09-23