Java 8 日期时间 API
Java 8通过发布新的Date-Time API (JSR 310)来进一步加强对日期与时间的处理。 旧版的java.util.Date
是非线程安全的。
1. java8日期时间
LocalDate
(本地日期)− 简化了日期处理,不带时间。
LocalTime
(本地时间)− 简化了时间处理,不带日期且没有偏移信息、无时区的时间。
LocalDateTime
(本地日期时间)− 日期+时间的处理。
上面的三个类的实例是不可变的对象,分布表示使用ISO-8601
日历系统的日期、时间、日期时间。无时区相关信息。
方法 | 说明 |
---|---|
now() | 静态方法,根据当前时间创建对象 |
of() | 静态方法,根据当前时间或日期创建对象 |
plusDays, plusWeeks, plusMonths, plusYears | 向当前LocalDate 对象添加几天、几周、几个月、几年的运算 |
minisDays, minisWeeks, minisMonths, minisYears | 从当前LocalDate 对象减去几天、几周、几个月、几年的运算 |
withDayOfMonth, withDayOfYear, withMonth, withYear | 将月份天数、年份天数、月份年份修改为指定的值并返回新的LocalDate对象 |
getDayOfMonth | 获取月份天数(1-31) |
getDayOfYear | 获取年份天数(1-366) |
getDayOfWeek | 获取星期几,返回一个DayOfWeek的枚举值 |
getMonth | 获取月份,返回一个Month的枚举值 |
getMonthValue | 获取月份数值(1-12) |
getYear | 获取年份 |
unitl | 获取两个日期之间的 Period 对象,或者指定 ChronoUnits 的数字 |
isBefore,isAfter | 比较两个LocalDate |
isLeapYear | 判断是否是闰年 |
```java
package com.zxc.jdk8;
import java.time.*;
import java.util.Date;
import static java.lang.System.out;
public class DateTimeTest {
public static void main(String[] args) {
LocalDate ldt = LocalDate.now();//日期
out.println(" ldt = " + ldt);
LocalTime time = LocalTime.now();//时间
out.println(" time = " + time);
LocalDateTime dttm = LocalDateTime.now();
out.println(" dttm = " + dttm);
LocalDate date2 = LocalDate.of(2020, 07,11);//日期
out.println(" date2 = " + date2);
LocalTime time2 = LocalTime.of(10,22,33);//时间
out.println(" time2 = " + time2);
LocalDateTime dttm2 = LocalDateTime.of(2020,07,11,10,22,33);
out.println(" dttm2 = " + dttm2);
LocalDateTime ldt3 = ld2.plusYears(20);
System.out.println(ldt3);
LocalDateTime ldt4 = ld2.minusMonths(2);
System.out.println(ldt4);
System.out.println(ldt.getYear());
System.out.println(ldt.getMonthValue());
System.out.println(ldt.getDayOfMonth());
System.out.println(ldt.getHour());
System.out.println(ldt.getMinute());
System.out.println(ldt.getSecond());
// 日期比较
LocalDate date1 = LocalDate.of(2020, 1, 15);
LocalDate date2 = LocalDate.of(2020, 3, 10);
// isBefore
boolean b1 = date1.isBefore(date2);
out.println(" date1 在date2的前面 :" + b1);
// isAfter
boolean b2 = date1.isAfter(date2);
out.println(" date1 在date2的后面 :" + b2);
boolean b3 = date1.equals(date2);
out.println(" date1 equals date2 ? " + b3);
// 日期时间比较
LocalDateTime dttm1 = LocalDateTime.now();
out.println(" dttm1 = " + dttm1);
LocalDateTime dttm2 = dttm1.plusDays(1);
out.println(" dttm2 = " + dttm2);
boolean b4 = dttm1.isBefore(dttm2);
out.println(" dttm1 在 dttm2 的前面 :" + b4);
}
2. java8 时间戳
Instant
(时间戳)-精确到纳秒的的某个时间点,不包含时区,允许加减运算。该方法默认使用的是UTC(协调世界时——由原子钟提供)时间(Unix元年开始经历描述进行运算),可以使用equeal
和 compareTo
来比较两个时间点的值。支持旧版时间转换新版时间戳。
@Test
public void test2(){
Instant ins = Instant.now(); //默认使用 UTC 时区
System.out.println(ins);
OffsetDateTime odt = ins.atOffset(ZoneOffset.ofHours(8));
System.out.println(odt);
System.out.println(ins.getNano());
Instant ins2 = Instant.ofEpochSecond(5);
System.out.println(ins2);
// 时间戳
Instant now = Instant.now();
out.println(" now = " + now);
// 将java.util.Date转换为Instant
Instant instant1 = Instant.ofEpochMilli(new Date().getTime());
out.println(instant1);
// 从字符串类型中创建Instant类型的时间
Instant instant2 = Instant.parse("1995-10-23T10:12:35Z");
}
3. Duration 和 Period。
@Test
public void caculteTest(){
Instant instant3 = Instant.now();
// 将现在的时间加上2个小时10分钟
Instant changeIns = instant3.plus(Duration.ofHours(2).plusMinutes(10));
out.println(changeIns);
System.out.println("--------------------");
// 使用instant计算7天前
instant3.minus(7, ChronoUnit.DAYS); // 方法1
instant3.minus(Duration.ofDays(7)); // 方法2
// 计算两个Instant之间的分钟数
Instant instant4 = Instant.now();
// long diffAsMinutes = instant.periodUntil(instant3, ChronoUnit.MINUTES); //
// 方法1
long diffAsMinutes1 = ChronoUnit.MINUTES.between(instant1, instant4); // 方法2
out.println(diffAsMinutes1 / 60 );
System.out.println("--------------------");
Instant ins1 = Instant.now();
System.out.println("--------------------");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
}
Instant ins2 = Instant.now();
System.out.println("所耗费时间为:" + Duration.between(ins1, ins2));
System.out.println("----------------------------------");
LocalDate ld1 = LocalDate.now();
LocalDate ld2 = LocalDate.of(2011, 1, 1);
Period pe = Period.between(ld2, ld1);
System.out.println(pe.getYears());
System.out.println(pe.getMonths());
System.out.println(pe.getDays());
// 一周从周日开始
WeekFields weekFields = WeekFields.of(DayOfWeek.SUNDAY, 7);
LocalDate today = LocalDate.now();
out.println("今天是今年第" + today.get(weekFields.weekOfYear()) + "周");
// 计算date的相差天数
out.println(LocalDate.now().toEpochDay() - LocalDate.now().minusDays(5).toEpochDay());
// 计算date的相差月数
out.println(LocalDate.now().until(LocalDate.now().minusDays(5), ChronoUnit.MONTHS));
// 计算date的相差月天,(相差0年1月24天)
LocalDate date1 = LocalDate.of(2020, 1, 15);
LocalDate date2 = LocalDate.of(2020, 3, 10);
Period period = Period.between(date1, date2);
out.println(period.getYears() + "-" + period.getMonths() + "-" + period.getDays());
}
4. 时区处理
Zoned
(时区) − 通过制定的时区处理日期时间。
ZoneDate
(时区日期)- 包含时区的日期。
ZoneTime
(时区时间)- 包含时区的时间。
ZoneDateTime
(时区日期时间)- 包含时区的完整的日期时间,偏移量是以UTC/格林威治时间
为基准的。ZonedDateTime代表带时区的时间,等同于以前的GregorianCalendar
类。使用该类,可以将本地时间转换成另一个时区中的对应时间。
ZonId
代表的是某个特定时区,里面的getAvailableZoneIds()
方法可以获取所有时区信息。里面的of()
方法是用指定的时区信息获取ZoneId对象
package com.zxc.jdk8;
import static java.lang.System.out;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.ZonedDateTime;
public class TimeZoneTest {
public static void main(String[] args) {
// 获取全部时区列表
Set<String> set = ZoneId.getAvailableZoneIds();
set.forEach(System.out::println);
LocalDateTime localDateTime = LocalDateTime.now();
out.println(" localDateTime = " + localDateTime);
ZoneId zone = ZoneId.of(ZoneId.SHORT_IDS.get("CTT"));//取定义好的时区
out.println(" zone = " + zone);
//包含时区的时间
ZonedDateTime dtWithZone = ZonedDateTime.of(localDateTime, zone);
out.println(" dtWithZone = " + dtWithZone);
}
}
输出
localDateTime = 2020-05-31T23:54:42.831
zone = Asia/Shanghai
dtWithZone = 2020-05-31T23:54:42.831+08:00[Asia/Shanghai]
注意:对应时区的文本可以直接手动填写,也可以调用系统默认定义的。
5. 格式化处理
java.time.format.DateTimeFormatter
提供格式化和解析功能。有三种格式化方法:
(1)预定义的标准格式,在DateTimeFormatter
类中。
(2)语言环境相关的格式
(3)自定义格式,如带中文。
//5. DateTimeFormatter : 解析和格式化日期或时间
@Test
public void formatterTest(){
DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyy年MM月dd日 HH:mm:ss E");
LocalDateTime ldt = LocalDateTime.now();
String strDate = ldt.format(dtf);
System.out.println(strDate);
LocalDateTime newLdt = ldt.parse(strDate, dtf);
System.out.println(newLdt);
}
6. 时间校正器
TemporalAdjuster
是时间校正器。有时候需要获取”下个周日”这种操作。
TemporalAdjusters
该类是通过静态方法提供大量常用的TemporalAdjuster
的实现。
@Test
public void test4(){
//取下个周末
LocalDateTime ldt1 = ldt.with(TemporalAdjusters.next(DayOfWeek.SUNDAY));
System.out.println(ldt1);
LocalDateTime ldt2 = ldt.withDayOfMonth(10);
System.out.println(ldt2);
//自定义:下一个工作日
LocalDateTime ldt5 = ldt.with((l) -> {
LocalDateTime ldt4 = (LocalDateTime) l;
DayOfWeek dow = ldt4.getDayOfWeek();
if(dow.equals(DayOfWeek.FRIDAY)){
return ldt4.plusDays(3);
}else if(dow.equals(DayOfWeek.SATURDAY)){
return ldt4.plusDays(2);
}else{
return ldt4.plusDays(1);
}
});
System.out.println(ldt5);
}
7. 其他相关
Locale
(本地) − 简化了日期时间的处理,没有时区的问题。
MonthDay
- 月日组合。它是一个值类(value class),由,不包含年信息,可以用来代表每年重复出现的一些日期或其他组合。
YearMonth
- 年月组合。
WeekFields
(周) - 处理周的计算。
Clock
- 时钟。可以获取某个时区下(对时区是敏感的)当前的瞬时时间、日期。用来代替System.currentTimelnMillis()与TimeZone.getDefault()方法。
package com.zxc.jdk8;
import java.time.*;
import java.util.Date;
import static java.lang.System.out;
public class DateTimeTest {
public static void main(String[] args) {
Locale l = Locale.getDefault();
out.println(l);
MonthDay md = MonthDay.now();
out.println(" md :"+md);
YearMonth ym = YearMonth.of(2020, 07);
out.println(" ym :"+ym);
Clock utc_cl = Clock.systemUTC();
out.println(" utc_cl :" +utc_cl);
Clock def_cl = Clock.systemDefaultZone();
out.println(" def_cl :" +def_cl);
}
}
8 与传统日期转换
类 | To 遗留类 | From 遗留类 |
---|---|---|
java.time.Instant java.util.Date | Date.from(Instant it) | date.toInstant() |
java.time.Instant java.util.Timestamp | Timestamp.from(Instant it) | tmestamp.toInstant() |
java.time.ZonedDateTime java.util.GregorianCalendar | GregorianCalendar.from(ZonedDateTime zd) | cal.toZonedDateTime() |
java.time.LocalDate java.sql.Time | Date.valueOf(LocalDate ld) | date.toLocalDate() |
java.time.LocalTime java.sql.Time | Date.valueOf(LocalTime lt) | date.toLocalTime() |
java.time.LocalDateTime java.sql.Timestamp | Timestamp.valueOf(LocalDateTime ldt) | tmestamp.toLocalDateTime() |
java.time.ZoneId java.sql.TimeZone | TimeZone.getTimeZone(ZoneId ldt) | tmeZone.toZoneId() |
java.time.format.DateTimeFormatter java.text.DateFormat | formatter.toFormat() | - |
部分示例如下。其他同理:
package com.zhangxiaocai.cn.java8.datetime;
import java.sql.Timestamp;
import java.time.Instant;
import java.util.Date;
import java.util.Locale;
import org.junit.Test;
public class TestOtherDateTime {
@Test
public void test(){
Locale l = Locale.getDefault();
System.out.println(l);
Instant it = Instant.now();
Date date = Date.from(it);
System.out.println(" date :"+date);
Instant it2 = date.toInstant();
System.out.println(" it2 : "+it2);
Timestamp ts = Timestamp.from(it);
System.out.println(" ts : "+ts);
Instant ts2 = ts.toInstant();
System.out.println(" ts2 : "+ts2);
}
}
9 其他
可以参考java 8 API,在实际遇到再补充。