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包
- java.time:新的Date Time API的基础包,包含LocalDate LocalDateTime Instant等等。所有的类都是线程安全的,足够满足大多数情况的需求。
- java.time.chrono:定义了通用的非 ISO 日历系统的API
- java.time.format:这个包主要是一些关于解析和格式化的类
- java.time.temporal:用于找到一些特定日期和时间的包,比如本月第一天这种
- 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的总结和拙见,希望能对你有所帮助。