Java 8 Date/Time API

163 阅读4分钟

1.为什么需要新的java date api

先看下java8之前的date api有哪些问题?

  • 在 java.util 和 java.sql 包中都有日期类
  • java.util.Date 包含日期和时间值,而 java.sql.Date 仅包含日期值。这两个类具有相同的名称,这本身就是一个非常糟糕的设计
  • 没有明确定义的时间、时间戳、格式和解析类。我们有用于解析和格式化需要的 java.text.DateFormat 抽象类。通常,SimpleDateFormat 类用于解析和格式化。
  • 所有 Date 类都是可变的,因此它们不是线程安全的,这是 Java Date 和 Calendar 类的最大问题之一。
  • Date 类不提供国际化,不支持时区。

2.Java 8 Date Time设计原则

  • 不可变性:新的 Date-Time API 中的所有类都是不可变的,并且适用于多线程环境。
  • 关注点分离:新的 API 清楚地区分了人类可读的日期时间和机器时间(Unix 时间戳)。它为 Date、Time、DateTime、Timestamp、Timezone 等定义了单独的类。
  • 明确性:所有方法被明确定义并在所有类中执行相同的操作。例如,要获取当前实例,我们有 now() 方法。所有这些类中都定义了 format() 和 parse() 方法,而不是为它们创建一个单独的类。
  • 有效的操作:新的Date-Time API 中有诸如plus, minus, format, parsing, getting的有效操作
  • 扩展性:新的日期时间 API 适用于 ISO-8601 日历系统,但我们也可以将其与其他非 ISO 日历一起使用。

3.Java 8 Date Time API包

  1. java.time:新的Date Time API的基础包,包含LocalDate LocalDateTime Instant等等。所有的类都是线程安全的,足够满足大多数情况的需求。
  2. java.time.chrono:定义了通用的非 ISO 日历系统的API
  3. java.time.format:这个包主要是一些关于解析和格式化的类
  4. java.time.temporal:用于找到一些特定日期和时间的包,比如本月第一天这种
  5. java.time.zone Package:时区相关的包

4.Java 8 Date Time API简介和一些例子

1.LocalDate

//今天
LocalDate today = LocalDate.now();

//明天
LocalDate tomorrow = LocalDate.now().plusDays(1);
//上个月的今天 特定枚举
LocalDate previousMonthSameDay = LocalDate.now().minus(1, ChronoUnit.MONTHS);

//DayOfWeek为枚举类,返回周几的枚举值 SATURDAY
DayOfWeek saturday = LocalDate.parse("2022-07-30").getDayOfWeek();

//当月的第几天
int twelve = LocalDate.parse("2022-07-30").getDayOfMonth();

//是否闰年
boolean leapYear = LocalDate.now().isLeapYear();


boolean notBefore = LocalDate.parse("2022-07-30")
                .isBefore(LocalDate.now());

boolean isAfter = LocalDate.parse("2022-07-30")
                .isAfter(LocalDate.now());

//当前天的开头即0点0分0秒
LocalDateTime beginningOfDay = LocalDate.parse("2022-07-30").atStartOfDay();
//月初
LocalDate firstDayOfMonth = LocalDate.parse("2022-07-30")
  .with(TemporalAdjusters.firstDayOfMonth());


//指定年月日
LocalDate specialDay = LocalDate.of(2022, Month.JULY, 9);

LocalDate.parse("2015-02-20");

//1970-01-01之后的时间
LocalDate epochDay = LocalDate.ofEpochDay(1L);

//某年的第几天
LocalDate thisYearDay = LocalDate.ofYearDay(2022, 2);

//相隔时间
LocalDate initialDate = LocalDate.parse("2007-05-10");
LocalDate finalDate = initialDate.plus(Period.ofDays(5));
int five = Period.between(initialDate, finalDate).getDays();
long five = ChronoUnit.DAYS.between(initialDate, finalDate);

2.LocalTime

        //当前的时分秒
        LocalTime now = LocalTime.now();
        //指定时间
        LocalTime sixThirty = LocalTime.parse("06:30");
        LocalTime ofTime = LocalTime.of(14, 9, 20);


        LocalTime sevenThirty = LocalTime.parse("06:30").plus(1, ChronoUnit.HOURS);

        //获取小时
        int six = LocalTime.parse("06:30").getHour();
        
        //比较前后
        boolean isbefore = LocalTime.parse("06:30").isBefore(LocalTime.parse("07:30"));
        //今天的结尾
        LocalTime maxTime = LocalTime.MAX;

        //指定时区的时间
        LocalTime timeKolkata = LocalTime.now(ZoneId.of("Asia/Kolkata"));

        //今天开始的第几秒的时间
        LocalTime secondOfDayTime = LocalTime.ofSecondOfDay(1L);

3.LocalDateTime

        //当前的年月日时分秒 yyyy-MM-ddTHH-mm-ss.zzz
        LocalDateTime now = LocalDateTime.now();
        LocalDateTime nowTime = LocalDateTime.of(LocalDate.now(), LocalTime.now());
        //特定枚举
        LocalDateTime.of(2015, Month.FEBRUARY, 20, 06, 30);
        LocalDateTime.parse("2015-02-20T06:30:00");
        LocalDateTime ofDateTime = LocalDateTime.of(2022, 7, 15, 20, 00);

        //时区
        LocalDateTime todayKolkata = LocalDateTime.now(ZoneId.of("Asia/Kolkata"));
        
        //时间的加减
        LocalDateTime.now().plusDays(1);
        LocalDateTime.now().minusHours(2);
        //月份
        LocalDateTime.now().getMonth();

        //date from BaseTime
        LocalDateTime dateFromBase = LocalDateTime.ofEpochSecond(10000, 0, ZoneOffset.UTC);

4.ZoneId

//时区相关
//所有时区 java.time.ZoneId#SHORT_IDS
ZoneId zoneId = ZoneId.of("Europe/Paris");

Set<String> allZoneIds = ZoneId.getAvailableZoneIds();

//2022-07-26T14:57:50.381+02:00[Europe/Paris]
ZonedDateTime zonedDateTime = ZonedDateTime.of(LocalDateTime.now(), zoneId);

ZonedDateTime parse = ZonedDateTime.parse("2015-05-03T10:15:30+01:00[Europe/Paris]");

5.Instant

        //Instant class is used to work with machine readable time format. 
        //Instant stores date time in unix timestamp.
        Instant now = Instant.now();
        System.out.println(now);

        //Instant from timestamp 
        // epochMilli – the number of milliseconds from 1970-01-01T00:00:00Z
        Instant specificTime = Instant.ofEpochMilli(now.toEpochMilli());
        System.out.println("Specific Time = "+specificTime);

        //Duration:A time-based amount of time, such as '34.5 seconds'.
        Duration thirtyDay = Duration.ofDays(1);
        System.out.println(thirtyDay);

6.转换

项目中用到的代码demo

Date shouldCorrectionDate;
if (AnswerShowTypeEnum.SATURDAY.getCode().equals(publishHomework.getAnswerShowType())) {
    //周推模式 周六才可以订正
    LocalDate specialDay = LocalDateTime.ofInstant(publishHomework.getEndDate().toInstant(), ZoneId.systemDefault()).toLocalDate();
    LocalDate sunday = specialDay.with(TemporalAdjusters.nextOrSame(DayOfWeek.SUNDAY));
    shouldCorrectionDate = Date.from(LocalDateTime.of(sunday, LocalTime.of(23, 59, 59)).atZone(ZoneId.systemDefault()).toInstant());
} else {
    shouldCorrectionDate = AnswerShowTypeEnum.getShouldCorrectionDate(publishHomework.getEndDate(), getLocalTime());
            }

//Date转localDateTime
Date date = new Date();
LocalDateTime nowByDate = LocalDateTime.ofInstant(date.toInstant(), ZoneId.systemDefault());

//LocalDateTime转Date
Date.from(LocalDateTime.now().atZone(ZoneId.systemDefault()).toInstant());

Date.from(LocalDateTime.of(LocalDate.now(), LocalTime.now())
          .atZone(ZoneId.systemDefault()).toInstant());


//Calendar转LocalDateTime
Calendar calendar = Calendar.getInstance();
LocalDateTime nowByCalendar = LocalDateTime.ofInstant(calendar.toInstant(), ZoneId.systemDefault());

//localDateTime转string
String format = localDateTime.format(DateTimeFormatter.ofPattern("YYYY-MM-DD HH:mm:ss"));
String format = localDateTime.format(DateTimeFormatter.ISO_DATE);

取当周

LocalDate today = LocalDate.now();
LocalDate monday = today.with(TemporalAdjusters.previousOrSame( DayOfWeek.MONDAY));
LocalDate sunday = today.with(TemporalAdjusters.nextOrSame(DayOfWeek.SUNDAY ));

localdate转date

public Date convertDate(LocalDate localDate){
        return Date.from(localDate.atStartOfDay(ZoneId.systemDefault()).toInstant());
    }

以上是对java8Date/Time API的总结和拙见,希望能对你有所帮助。