在Java8之前,我们通常使用java.util.Date
和java.util.Calendar
类来处理日期和时间相关的操作,例如:
//创建一个Date对象
Date date = new Date();
//获取当前的年月日时分秒
int year = date.getYear() + 1900;
int month = date.getMonth() + 1;
int day = date.getDate();
int hour = date.getHours();
int minute = date.getMinutes();
int second = date.getSeconds();
//打印当前的日期和时间
System.out.println(year + "-" + month + "-" + day + " " + hour + ":" + minute + ":" + second);
这种方式虽然可以实现功能,但是有一些缺点:
- 可变性:
Date
和Calendar
类都是可变的,这意味着它们的值可以被修改,这可能会导致一些线程安全和逻辑错误的问题。 - 可读性差:
Date
和Calendar
类的方法命名和设计都不够清晰和一致,例如getYear()
方法返回的是从1900年开始的年份,而不是实际的年份;getMonth()
方法返回的是从0开始的月份,而不是从1开始的月份;set(int field, int value)
方法可以设置任意的字段和值,但是可能会导致不合理的结果,例如2月30日等。 - 时区问题:
Date
和Calendar
类都不能很好地处理时区相关的问题,例如在不同的时区下显示或转换日期和时间。
为了解决这些问题,Java8引入了一套全新的日期和时间API,在java.time
包中。这套API基于JSR-310规范设计,提供了一系列不可变且线程安全的类来表示日期、时间、时区、时段等概念。这套API有以下特点:
- 不可变性:所有的日期和时间类都是不可变的,这意味着它们的值不能被修改,只能通过创建新的对象来表示不同的值。这样可以避免线程安全和逻辑错误的问题。
- 可读性好:所有的日期和时间类都有清晰和一致的方法命名和设计,例如
getYear()
方法返回的是实际的年份;getMonth()
方法返回的是一个枚举类型,而不是一个整数;with(TemporalAdjuster adjuster)
方法可以根据指定的规则调整日期或时间,例如获取下一个周一等。 - 时区支持:所有的日期和时间类都可以与时区相关联,例如使用
ZonedDateTime
类可以表示带有时区信息的日期和时间;使用ZoneId
类可以表示时区标识符;使用ZoneOffset
类可以表示时区偏移量。
Java8 Date Time API使用示例
为了方便理解Java8 Date Time API,我们可以将其分为四个层次:
- 本地日期和时间:表示不带有时区信息的日期和时间,主要有以下几个类:
-
LocalDate
:表示年月日,例如2021-10-31。 -
LocalTime
:表示时分秒纳秒,例如23:59:59.999999999。 -
LocalDateTime
:表示年月日时分秒纳秒,例如2021-10-31T23:59:59.999999999。 -
MonthDay
:表示月日,例如10-31。 -
YearMonth
:表示年月,例如2021-10。 -
Year
:表示年,例如2021。
-
- 带时区的日期和时间:表示带有时区信息的日期和时间,主要有以下几个类:
-
ZonedDateTime
:表示带有时区信息的年月日时分秒纳秒,例如2021-10-31T23:59:59.999999999+08:00[Asia/Shanghai]。 -
OffsetDateTime
:表示带有时区偏移量的年月日时分秒纳秒,例如2021-10-31T23:59:59.999999999+08:00。 -
OffsetTime
:表示带有时区偏移量的时分秒纳秒,例如23:59:59.999999999+08:00。 -
ZoneId
:表示时区标识符,例如Asia/Shanghai。 -
ZoneOffset
:表示时区偏移量,例如+08:00。
-
- 机器时间:表示以Unix时间戳的形式表示的日期和时间,主要有以下几个类:
-
Instant
:表示一个瞬时点,以1970-01-01T00:00:00Z为基准,以秒和纳秒为单位,例如2021-10-31T15:59:59.999999999Z。 -
Duration
:表示两个瞬时点之间的时间间隔,以秒和纳秒为单位,例如PT23H59M59.999999999S。
-
- 人类时间:表示以人类可读的方式表示的日期和时间,主要有以下几个类:
-
Period
:表示两个日期之间的时间间隔,以年月日为单位,例如P1Y2M3D。 -
ChronoUnit
:表示时间单位,例如年、月、日、小时、分钟、秒等。 -
ChronoField
:表示时间字段,例如年、月、日、小时、分钟、秒等。 -
DayOfWeek
:表示星期几,例如MONDAY、TUESDAY等。 -
Month
:表示月份,例如JANUARY、FEBRUARY等。
-
下面我们来看一些使用这些类的示例:
//创建一个本地日期
LocalDate date = LocalDate.of(2021, 10, 31);
System.out.println(date); //输出2021-10-31
//获取当前的本地日期
LocalDate today = LocalDate.now();
System.out.println(today); //输出当前的日期
//获取本地日期的年月日
int year = date.getYear();
int month = date.getMonthValue();
int day = date.getDayOfMonth();
System.out.println(year + "-" + month + "-" + day); //输出2021-10-31
//获取本地日期的星期几
DayOfWeek dow = date.getDayOfWeek();
System.out.println(dow); //输出SUNDAY
//获取本地日期的一些属性
boolean isLeapYear = date.isLeapYear(); //是否是闰年
boolean isBefore = date.isBefore(today); //是否在今天之前
boolean isAfter = date.isAfter(today); //是否在今天之后
boolean isEqual = date.isEqual(today); //是否等于今天
System.out.println(isLeapYear); //输出false
System.out.println(isBefore); //输出false或true,取决于当前日期
System.out.println(isAfter); //输出false或true,取决于当前日期
System.out.println(isEqual); //输出false或true,取决于当前日期
//调整本地日期
LocalDate nextDay = date.plusDays(1); //加一天
LocalDate nextWeek = date.plusWeeks(1); //加一周
LocalDate nextMonth = date.plusMonths(1); //加一个月
LocalDate nextYear = date.plusYears(1); //加一年
LocalDate firstDayOfMonth = date.with(TemporalAdjusters.firstDayOfMonth()); //获取当月第一天
LocalDate lastDayOfMonth = date.with(TemporalAdjusters.lastDayOfMonth()); //获取当月最后一天
LocalDate firstDayOfNextMonth = date.with(TemporalAdjusters.firstDayOfNextMonth()); //获取下个月第一天
System.out.println(nextDay); //输出2021-11-01
System.out.println(nextWeek); //输出
System.out.println(nextWeek); //输出2021-11-07 System.out.println(nextMonth); //输出2021-11-30 System.out.println(nextYear); //输出2022-10-31 System.out.println(firstDayOfMonth); //输出2021-10-01 System.out.println(lastDayOfMonth); //输出2021-10-31 System.out.println(firstDayOfNextMonth); //输出2021-11-01
//创建一个本地时间
LocalTime time = LocalTime.of(23, 59, 59);
System.out.println(time); //输出23:59:59
//获取当前的本地时间
LocalTime now = LocalTime.now();
System.out.println(now); //输出当前的时间
//获取本地时间的时分秒纳秒
int hour = time.getHour();
int minute = time.getMinute();
int second = time.getSecond();
int nano = time.getNano();
System.out.println(hour + “:”+minute + “:”+second + “.”+nano); //输出23:59:59.0
//调整本地时间
LocalTime nextSecond = time.plusSeconds(1); //加一秒 LocalTime nextMinute = time.plusMinutes(1); //加一分钟 LocalTime nextHour = time.plusHours(1); //加一小时 LocalTime withNano = time.withNano(999999999); //设置纳秒为999999999 System.out.println(nextSecond); //输出00:00:00 System.out.println(nextMinute); //输出00:00:59 System.out.println(nextHour); //输出00:59:59 System.out.println(withNano); //输出23:59:59.999999999
//创建一个本地日期时间
LocalDateTime dateTime = LocalDateTime.of(2021, 10, 31, 23, 59, 59);
System.out.println(dateTime); //输出2021-10-31T23:59:59
//获取当前的本地日期时间
LocalDateTime nowDateTime = LocalDateTime.now();
System.out.println(nowDateTime); //输出当前的日期时间
//获取本地日期时间的年月日时分秒纳秒
int year = dateTime.getYear();
int month = dateTime.getMonthValue();
int day = dateTime.getDayOfMonth();
int hour = dateTime.getHour();
int minute = dateTime.getMinute();
int second = dateTime.getSecond();
int nano = dateTime.getNano();
System.out.println(year + “ -”+month + “-”+day + " " + hour + “:”+minute + “:”+second + “.”+nano); //输出2021-10-31 23:59:59.0
//调整本地日期时间
LocalDateTime nextSecond = dateTime.plusSeconds(1); //加一秒 LocalDateTime nextMinute = dateTime.plusMinutes(1); //加一分钟 LocalDateTime nextHour = dateTime.plusHours(1); //加一小时 LocalDateTime nextDay = dateTime.plusDays(1); //加一天 LocalDateTime nextWeek = dateTime.plusWeeks(1); //加一周 LocalDateTime nextMonth = dateTime.plusMonths(1); //加一个月 LocalDateTime nextYear = dateTime.plusYears(1); //加一年 LocalDateTime firstDayOfMonth = dateTime.with(TemporalAdjusters.firstDayOfMonth()); //获取当月第一天 LocalDateTime lastDayOfMonth = dateTime.with(TemporalAdjusters.lastDayOfMonth()); //获取当月最后一天 LocalDateTime firstDayOfNextMonth = dateTime.with(TemporalAdjusters.firstDayOfNextMonth()); //获取下个月第一天 System.out.println(nextSecond); //输出2021-11-01T00:00:00 System.out.println(nextMinute); //输出2021-11-01T00:00:59 System.out.println(nextHour); //输出2021-11-01T00:59:59 System.out.println(nextDay); //输出2021-11-01T23:59:59 System.out.println(nextWeek); //输出2021-11-07T23:59:59 System.out.println(nextMonth); //输出2021-11-30T23:59:59 System.out.println(nextYear); //输出2022-10-31T23:59:59 System.out.println(firstDayOfMonth); //输出2021-10-01T23:59:59 System.out.println(lastDayOfMonth); //输出2021-10-31T23:59:59 System.out.println(firstDayOfNextMonth); //输出2021-11-01T23:59:59
//创建一个带时区的日期时间
ZonedDateTime zonedDateTime = ZonedDateTime.of(2021, 10, 31, 23, 59, 59, 0, ZoneId.of(“Asia / Shanghai”));
System.out.println(zonedDateTime); //输出2021-10-31T23:59:59+08:00[Asia/Shanghai]
//获取当前的带时区的日期时间
ZonedDateTime nowZonedDateTime = ZonedDateTime.now();
System.out.println(nowZonedDateTime); //输出当前的带时区的日期时间
//获取带时区的日期时间的年月日时分秒纳秒和时区信息
int year = zonedDateTime.getYear();
int month = zonedDateTime.getMonthValue();
int day = zonedDateTime.getDayOfMonth();
int hour = zonedDateTime.getHour();
int minute = zonedDateTime.getMinute();
int second = zonedDateTime.getSecond();
int nano = zonedDateTime.getNano();
ZoneId zoneId = zonedDateTime.getZone();
ZoneOffset zoneOffset = zonedDateTime.getOffset();
System.out.println(year + “ -”+month + “-”+day + " " + hour + “:”+minute + “:”+second + “.”
+nano + " " + zoneId + " " + zoneOffset); //输出2021-10-31 23:59:59.0 Asia/Shanghai +08:00
//调整带时区的日期时间
ZonedDateTime nextSecond = zonedDateTime.plusSeconds(1); //加一秒 ZonedDateTime nextMinute = zonedDateTime.plusMinutes(1); //加一分钟 ZonedDateTime nextHour = zonedDateTime.plusHours(1); //加一小时 ZonedDateTime nextDay = zonedDateTime.plusDays(1); //加一天 ZonedDateTime nextWeek = zonedDateTime.plusWeeks(1); //加一周 ZonedDateTime nextMonth = zonedDateTime.plusMonths(1); //加一个月 ZonedDateTime nextYear = zonedDateTime.plusYears(1); //加一年 ZonedDateTime firstDayOfMonth = zonedDateTime.with(TemporalAdjusters.firstDayOfMonth()); //获取当月第一天 ZonedDateTime lastDayOfMonth = zonedDateTime.with(TemporalAdjusters.lastDayOfMonth()); //获取当月最后一天 ZonedDateTime firstDayOfNextMonth = zonedDateTime.with(TemporalAdjusters.firstDayOfNextMonth()); //获取下个月第一天 ZonedDateTime withZoneId = zonedDateTime.withZoneSameInstant(ZoneId.of(“Europe/London”)); //转换为另一个时区,保持瞬时点不变 System.out.println(nextSecond); //输出2021-11-01T00:00:00+08:00[Asia/Shanghai] System.out.println(nextMinute); //输出2021-11-01T00:00:59+08:00[Asia/Shanghai] System.out.println(nextHour); //输出2021-11-01T00:59:59+08:00[Asia/Shanghai] System.out.println(nextDay); //输出2021-11-01T23:59:59+08:00[Asia/Shanghai] System.out.println(nextWeek); //输出2021-11-07T23:59:59+08:00[Asia/Shanghai] System.out.println(nextMonth); //输出2021-11-30T23:59:59+08:00[Asia/Shanghai] System.out.println(nextYear); //输出2022-10-31T23:59:59+08:00[Asia/Shanghai] System.out.println(firstDayOfMonth); //输出2021-10-01T23:59:59+08:00[Asia/Shanghai] System.out.println(lastDayOfMonth); //输出2021-10-31T23:59:59+08:00[Asia/Shanghai] System.out.println(firstDayOfNextMonth); //输出2021-11-01T23:59:59+08:00[Asia/Shanghai] System.out.println(withZoneId); //输出2021-10-31T15:59:59+00:00[Europe/London]
//创建一个机器时间
Instant instant = Instant.ofEpochSecond(1635705599);
System.out.println(instant); //输出2021-10-31T15:59:59Z
//获取当前的机器时间
Instant nowInstant = Instant.now();
System.out.println(nowInstant); //输出当前的机器时间
//获取机器时间的秒和纳秒
long epochSecond = instant.getEpochSecond();
int nano = instant.getNano();
System.out.println(epochSecond + “.”+nano); //输出1635705599.0
//调整机器时间
Instant nextSecond = instant.plusSeconds(1);//加一秒
Instant nextMinute = instant.plusMinutes(1);//加一分钟
Instant nextHour = instant.plusHours(1);//加一小时
Instant nextDay = instant.plus(1, ChronoUnit.DAYS);//加一天
Instant nextWeek = instant.plus(1, ChronoUnit.WEEKS);//加一周
Instant nextMonth = instant.plus(1, ChronoUnit.MONTHS);// 加一个月
Instant nextYear = instant.plus(1, ChronoUnit.YEARS);// 加一年
System.out.println(nextSecond);// 输出2021-10-31T16:00:00Z
System.out.println(nextMinute);// 输出2021-10-31T16:00:59Z
System.out.println(nextHour);// 输出2021-10-31T16:59:59Z
System.out.println(nextDay);// 输出2021-11-01T15:59:59Z
System.out.println(nextWeek);// 输出2021-11-07T15:59:59Z
System.out.println(nextMonth);// 输出2021-11-30T15:59:59Z
System.out.println(nextYear);// 输出2022-10-31T15:59:59Z
//创建一个人类时间
Period period = Period.of(1, 2, 3);
System.out.println(period); //输出P1Y2M3D
//获取人类时间的年月日
int years = period.getYears();
int months = period.getMonths();
int days = period.getDays();
System.out.println(years + " years " + months + " months " + days + " days"); //输出1 years 2 months 3 days
// 调整人类时间
Period plusPeriod = period.plus(Period.of(1, 1, 1));//加上另一个时间间隔
Period minusPeriod = period.minus(Period.of(0, 0, 1));//减去另一个时间间隔
Period multipliedPeriod = period.multipliedBy(2);//乘以一个因子
Period normalizedPeriod = period.normalized();//标准化为年和月的形式
System.out.println(plusPeriod);// 输出P2Y3M4D
System.out.println(minusPeriod); //输出P1Y2M2D
System.out.println(multipliedPeriod); //输出P2Y4M6D
System.out.println(normalizedPeriod); //输出P14M3D
Java8 Date Time API的优缺点分析对比
Java8 Date Time API是Java语言发展的一个重要的进步,它们为Java开发者提供了一套全新的日期和时间处理方式,可以使代码更加简洁和清晰,提高了开发效率和可读性。同时,它们也为Java引入了一些新的特性和概念,例如不可变性,时区支持,机器时间,人类时间等,使得Java更加丰富和强大。
但是,Java8 Date Time API也有一些缺点和限制,例如:
- 兼容性问题:Java8 Date Time API只能在Java8或更高版本的环境中运行,如果需要在低版本的环境中运行,就需要使用其他的工具或者框架来支持。
- 性能问题:Java8 Date Time API在运行时会生成一些额外的对象和方法,这可能会影响程序的性能和内存占用。虽然Java虚拟机会进行一些优化和缓存,但是仍然需要注意避免过度使用或者滥用这些特性。
- 复杂性问题:Java8 Date Time API提供了很多不同的类和方法来表示不同的日期和时间概念,这可能会导致一些复杂性和混乱。例如,在不同的场景下需要使用不同的类和方法,例如
LocalDate
,LocalTime
,LocalDateTime
,ZonedDateTime
,Instant
等;在不同的类和方法之间需要进行转换,例如使用toInstant()
,ofInstant()
,withZoneSameInstant()
等方法。
因此,在使用Java8 Date Time API时,需要根据具体的场景和需求来选择合适的方式,避免盲目地追求新特性而忽略了其他方面的影响。
Java8 Date Time API的使用场景和注意事项
Java8 Date Time API可以用来处理很多与日期和时间相关的操作,例如:
- 获取当前的日期和时间
- 解析和格式化日期和时间字符串
- 计算日期和时间的差值和间隔
- 调整日期和时间的值
- 转换日期和时间的时区
- 比较日期和时间的大小
- 验证日期和时间的合法性
在使用Java8 Date Time API时,有一些注意事项,例如:文章来源:https://www.toymoban.com/news/detail-505840.html
- 使用不可变对象:所有的日期和时间类都是不可变的,这意味着它们的值不能被修改,只能通过创建新的对象来表示不同的值。这样可以避免线程安全和逻辑错误的问题。因此,在使用这些类时,不要试图修改它们的值,而是使用返回新对象的方法来进行操作。
- 使用合适的类:Java8 Date Time API提供了很多不同的类来表示不同的日期和时间概念,这可能会导致一些复杂性和混乱。因此,在使用这些类时,要根据具体的场景和需求来选择合适的类。例如,在不需要时区信息的场景下,可以使用
LocalDate
,LocalTime
,LocalDateTime
等类;在需要时区信息的场景下,可以使用ZonedDateTime
,OffsetDateTime
,OffsetTime
等类;在需要以Unix时间戳的形式表示日期和时间的场景下,可以使用Instant
类;在需要以人类可读的方式表示日期和时间的场景下,可以使用Period
,ChronoUnit
等类。 - 使用正确的方法:Java8 Date Time API提供了很多不同的方法来对日期和时间进行操作,这可能会导致一些复杂性和混乱。因此,在使用这些方法时,要根据具体的场景和需求来选择正确的方法。例如,在调整日期和时间时,可以使用
plus()
,minus()
等方法来加减指定的值;可以使用with()
等方法来设置指定的字段或者规则;可以使用truncatedTo()
等方法来截断指定的单位;在转换日期和时间时,可以使用toInstant()
,ofInstant()
等方法来转换为机器时间;可以使用withZoneSameInstant()
等方法来转换为带时区的日期时间;在解析和格式化日期和时间字符串时,可以使用parse()
,format()
等方法,并且指定合适的格式化器。
文章来源地址https://www.toymoban.com/news/detail-505840.html
到了这里,关于Java8 时间处理API(Date Time API)详解的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!