Detailed explanation of Java8 time processing API (Date Time API)

Before Java8, we usually use java.util.Dateand java.util.Calendarclasses to handle date and time related operations, for example:

//创建一个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);

Although this method can realize the function, it has some disadvantages:

  • Mutability: Both classes Dateand Calendarclasses are mutable, which means their values ​​can be modified, which may cause some thread safety and logic error issues.
  • Poor readability: The method naming and design of the class are not clear and consistent. For example, the method returns Datethe year starting from 1900 instead of the actual year; the method returns the month starting from 0 instead of 1 The month; the method can set arbitrary fields and values, but it may lead to unreasonable results, such as February 30th, etc.CalendargetYear()getMonth()set(int field, int value)
  • Timezone issues: Neither the Datenor Calendarclass handles timezone-related issues well, such as displaying or converting dates and times in different timezones.

In order to solve these problems, Java8 introduces a new set of date and time API, in java.timethe package. This set of API is designed based on the JSR-310 specification and provides a series of immutable and thread-safe classes to represent concepts such as date, time, time zone, and time period. This set of API has the following characteristics:

  • Immutability: All date and time classes are immutable, which means their values ​​cannot be modified, only by creating new objects to represent different values. This avoids issues of thread safety and logic errors.
  • Good readability: all date and time classes have clear and consistent method naming and design, for example, getYear()the method returns the actual year; getMonth()the method returns an enumeration type, not an integer; with(TemporalAdjuster adjuster)the method can be based on the specified Rules to adjust the date or time, such as getting the next Monday, etc.
  • Time zone support: All date and time classes can be associated with time zones, for example, use ZonedDateTimeclasses to represent date and time with time zone information; use ZoneIdclasses to represent time zone identifiers; use ZoneOffsetclasses to represent time zone offsets.

Java8 Date Time API usage example

In order to facilitate the understanding of Java8 Date Time API, we can divide it into four levels:

  • Local date and time: Indicates the date and time without time zone information, mainly including the following categories:
    • LocalDate: Indicates the year, month, and day, for example, 2021-10-31.
    • LocalTime: Indicates hours, minutes, seconds and nanoseconds, for example, 23:59:59.999999999.
    • LocalDateTime: Indicates the year, month, day, hour, minute, second, and nanosecond, for example, 2021-10-31T23:59:59.999999999.
    • MonthDay: Indicates the day of the month, such as 10-31.
    • YearMonth: Indicates the year and month, such as 2021-10.
    • Year: Indicates the year, such as 2021.
  • Date and time with time zone: Indicates date and time with time zone information, mainly including the following categories:
    • ZonedDateTime: Indicates the year, month, day, hour, minute, second and nanosecond with time zone information, for example, 2021-10-31T23:59:59.999999999+08:00[Asia/Shanghai].
    • OffsetDateTime: Represents the year, month, day, hour, minute, second and nanosecond with the time zone offset, for example, 2021-10-31T23:59:59.999999999+08:00.
    • OffsetTime: Indicates hours, minutes, seconds and nanoseconds with time zone offset, for example, 23:59:59.999999999+08:00.
    • ZoneId: Indicates a time zone identifier, such as Asia/Shanghai.
    • ZoneOffset: Indicates the time zone offset, such as +08:00.
  • Machine time: Indicates the date and time expressed in the form of Unix timestamp, mainly including the following categories:
    • Instant: Indicates an instantaneous point, based on 1970-01-01T00:00:00Z, in seconds and nanoseconds, for example, 2021-10-31T15:59:59.999999999Z.
    • Duration: Indicates the time interval between two instantaneous points in seconds and nanoseconds, such as PT23H59M59.999999999S.
  • Human time: represents the date and time expressed in a human-readable way, mainly in the following categories:
    • Period: Indicates the time interval between two dates, in units of year, month and day, such as P1Y2M3D.
    • ChronoUnit: Indicates the time unit, such as year, month, day, hour, minute, second, etc.
    • ChronoField: Indicates a time field, such as year, month, day, hour, minute, second, etc.
    • DayOfWeek: Indicates the day of the week, such as MONDAY, TUESDAY, etc.
    • Month: Indicates the month, such as JANUARY, FEBRUARY, etc.

Let's look at some examples of using these classes:

//创建一个本地日期
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

Analysis and comparison of advantages and disadvantages of Java8 Date Time API

The Java8 Date Time API is an important advancement in the development of the Java language. They provide Java developers with a new set of date and time processing methods, which can make the code more concise and clear, and improve development efficiency and readability. At the same time, they also introduce some new features and concepts to Java, such as immutability, time zone support, machine time, human time, etc., making Java richer and more powerful.

However, Java8 Date Time API also has some disadvantages and limitations, such as:

  • Compatibility issues: Java8 Date Time API can only run in the environment of Java8 or higher version. If it needs to run in the environment of lower version, you need to use other tools or frameworks to support it.
  • Performance issues: The Java8 Date Time API generates some extra objects and methods at runtime, which may affect the performance and memory usage of the program. Although the Java Virtual Machine performs some optimizations and caching, care must be taken to avoid overusing or abusing these features.
  • Complexity issues: The Java8 Date Time API provides a lot of different classes and methods to represent different date and time concepts, which can lead to some complexity and confusion. For example, you need to use different classes and methods in different scenarios, such as LocalDate, LocalTime, LocalDateTime, ZonedDateTime, Instantetc.; you need to convert between different classes and methods, such as using toInstant(), ofInstant(), withZoneSameInstant()and other methods.

Therefore, when using the Java8 Date Time API, it is necessary to choose an appropriate method according to specific scenarios and requirements, and avoid blindly pursuing new features while ignoring the impact of other aspects.

Usage Scenarios and Precautions of Java8 Date Time API

Java8 Date Time API can be used to handle many date and time related operations, such as:

  • Get the current date and time
  • Parse and format date and time strings
  • Computing Date and Time Differences and Intervals
  • Adjust date and time values
  • Convert date and time to timezone
  • Compare the size of date and time
  • Verify the legitimacy of date and time

When using Java8 Date Time API, there are some considerations, such as:

  • Use immutable objects: All date and time classes are immutable, which means their values ​​cannot be modified, only by creating new objects to represent different values. This avoids issues of thread safety and logic errors. Therefore, when using these classes, do not attempt to modify their values, but use methods that return new objects to do so.
  • Use the right class: The Java8 Date Time API provides a lot of different classes to represent different date and time concepts, which can lead to some complexity and confusion. Therefore, when using these classes, the appropriate class should be selected according to specific scenarios and needs. For example, in scenarios where time zone information is not required, classes such as , , etc. can be used LocalDate; LocalTimein LocalDateTimescenarios where time zone information is required, classes such as , can be used; in scenarios ZonedDateTimewhere date and time need to be represented in the form of Unix timestamps, you can use Use classes; in scenarios where dates and times need to be represented in a human-readable way, classes such as , etc. can be used.OffsetDateTimeOffsetTimeInstantPeriodChronoUnit
  • Use the right method: The Java8 Date Time API provides a lot of different methods to manipulate dates and times, which can lead to some complexity and confusion. Therefore, when using these methods, the correct method should be selected according to specific scenarios and needs. For example, when adjusting date and time, you can use plus()methods minus()such as to add and subtract specified values; with()methods such as can be used to set specified fields or rules; truncatedTo()methods such as can be used to truncate specified units; when converting dates and times, You can use toInstant(), ofInstant()and other methods to convert to machine time; you can use withZoneSameInstant()and other methods to convert to date and time with time zone; when parsing and formatting date and time strings, you can use parse(), format()and other methods, and specify the appropriate formatter.

 

Guess you like

Origin blog.csdn.net/caicai250/article/details/131413687