[置顶] Java8 时间处理

时间:2022-04-30 00:55:45

1. 时间日期概述

Java8引入了一套全新的时间日期API,关于这个新的时间日期库的最大优点在于它清楚地定义了时间日期相关的一些概念,比如说,时间戳(Instant),持续时间(Duration),时区(ZoneId)等。java.time包中的类是不可变且线程安全的。下面是一些关键的类:

  • Instant,该类代表具体的时刻
  • LocalDate,该类代表日期,例如2014-09-08
  • LocalTime,该类代表时间,例如13:14:21
  • LocalDateTime,该类代表日期和时间,例如2014-09-08T13:14:21
  • ZonedDateTime:该类代表一个时区化的日期,时间

该包的API提供了大量相关的方法,这些方法一般有一致的方法前缀:

of:静态工厂方法。
parse:静态工厂方法,关注于解析。
get:获取某些field的值。
is:检查某些东西的是否是true。
with:不可变的setter等价物,返回一个新的拷贝对象。
plus:加一些量到某个对象。
minus:从某个对象减去一些量。
to:转换到另一个类型。
at:把这个对象与另一个对象组合起来,例如: date.atTime(time)。

与旧的API对应关系
[置顶]        Java8 时间处理

2. 实例解析

  1. 提供了ZoneId,ZoneOffset用来处理时区
  2. 提供了LocalDateTime, LocalDate, LocalTime处理时间和日期
  3. 在新的日期和时间类中所有的类都是不可变且线程安全的
  4. 提供了DateTimeFormatter类对时间和日期进行格式化
//1. 获得当天的日期
LocalDate date = LocalDate.now();
System.out.println("今天的日期为:" + date);

//2. 获取当前日期的年月日
int year = date.getYear();
int month = date.getMonthValue();
int day = date.getDayOfMonth();
System.out.println("年:" + year + " 月:" + month + " 日:" + day);

//3. 获取特定的日期
LocalDate birthDate = LocalDate.of(2016, 7, 27);
System.out.println("你的出生日期为:" + birthDate);

//4. 比较两个日期是否相等
//LocalDate requestDate = LocalDate.of(2016, 7, 27);
LocalDate requestDate = LocalDate.of(2015, 12, 23);
if(requestDate.equals(birthDate)) {
System.out.println("两个日期相等, 都是" + requestDate);
}else {
System.out.println("两个日期不相等,First :" + birthDate + " Second :" + requestDate);
}

//5. 比较MonthDay是否相同
MonthDay birthday = MonthDay.of(birthDate.getMonthValue(), birthDate.getDayOfMonth());
MonthDay currentMonthDay = MonthDay.from(date);
if(currentMonthDay.equals(birthday)) {
System.out.println("今天是你的生日,祝你快乐");
}else {
System.out.println("平常的一天,但是不平凡");
}

//6. 获取当前时间
LocalTime currentTime = LocalTime.now();
System.out.println("局部当前时间为:" + currentTime);

//7. 增加小时
LocalTime newTime = currentTime.plusHours(2);
System.out.println("两个小时后:" + newTime);

//8. 获取1周后的日期
LocalDate nextWeek = date.plus(1, ChronoUnit.WEEKS);
System.out.println("今天是:" + date);
System.out.println("一个星期后是:" + nextWeek);

//9. 一年前后的日期
LocalDate previousYear = date.minus(1, ChronoUnit.YEARS);
LocalDate nextYear = date.plus(1, ChronoUnit.YEARS);
System.out.println("去年:" + previousYear);
System.out.println("今年:" + date);
System.out.println("明年:" + nextYear);

//10. 使用时钟Clock 获取某个时区下当前的瞬时时间,时间或日期
Clock clock1 = Clock.systemUTC();
Clock clock2 = Clock.systemDefaultZone();
System.out.println("clock1: " + clock1.instant());
System.out.println("clock2: " + clock2.instant());
System.out.println("clock1的时区为:" + clock1.getZone());
System.out.println("clock2的时区为:" + clock2.getZone());


//11. 判断某个日期是在另一的日期的前面还是后面
LocalDate tomorrow = LocalDate.of(2016,7,28);
LocalDate yesterday = date.minusDays(1);
if(tomorrow.isAfter(date)) {
System.out.println(tomorrow);
System.out.println("明天快要到了");
}

if(yesterday.isBefore(date)){
System.out.println(yesterday);
System.out.println("昨天已经过去");
}

//12. 处理不同的时区
LocalDateTime localDateTime = LocalDateTime.now();
System.out.println("当地时间为:" + localDateTime);
ZoneId americaZone = ZoneId.of("America/Los_Angeles");
ZonedDateTime zonedDateTime = ZonedDateTime.of(localDateTime, americaZone);
//相对于UTC的时区,本地的时区恢复到UTC时间,再进行计算
System.out.println("洛杉矶时区为:" + zonedDateTime);

//13. YearMontn 年月
YearMonth currentYearMonth = YearMonth.now();
System.out.println("年月:" + currentYearMonth + " 这个月有" + currentYearMonth.lengthOfMonth() +"天");


//date = LocalDate.of(2001, 1, 2);
//14. 检查闰年
/*两个条件同时满足:
1、年份能被4整除;
2、年份若是100的整数倍的话,需被400整除。
*/

if(date.isLeapYear()) {
System.out.println("今年是闰年");
}else{
System.out.println("今年不是闰年");
}

//15. 当前时间戳
Instant timeStamp = Instant.now();
System.out.println("当前时间戳为:" + timeStamp); //标准时间 +8 为北京时间


//16.日期进行格式解析 1)内部解析 parse 2)自定义解析
String goodDay = "04 18 2014";
try {
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("MM dd yyyy");
LocalDate holiday = LocalDate.parse(goodDay, formatter);
System.out.println("好日子为:" + holiday);
}catch (DateTimeParseException e) {
e.printStackTrace();
}

//17. 将日期格式化转为字符串
LocalDateTime arriveDate = LocalDateTime.of(2014, Month.APRIL, 21, 0, 12, 20);
try {
DateTimeFormatter format = DateTimeFormatter.ofPattern("MMM dd yyyy HH:mm:ss a");
String loading = arriveDate.format(format);
System.out.println("今天是:" + loading);
}catch (DateTimeParseException e) {
e.printStackTrace();
}

3. 再解析

/**
* 测试LocalDateTime
*/

public static void testLocalDateTime() {
//根据相应时区显示时间
LocalDateTime now = LocalDateTime.now();
System.out.println(now);

System.out.println(LocalDateTime.now(Clock.systemUTC()));
System.out.println(LocalDateTime.now(Clock.systemDefaultZone()));

LocalDateTime now2 = LocalDateTime.now(ZoneId.of("Europe/Paris"));
System.out.println(now2);//会以相应的时区显示日期
Instant instant = Instant.now(); //默认是标准时区
System.out.println(instant);
LocalDateTime d3 = LocalDateTime.ofInstant(Instant.now(), ZoneId.systemDefault());
System.out.println(d3);

//使用DateTimeFormatter API 解析 和 格式化
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy/MM/dd HH:mm:ss");
LocalDateTime d6 = LocalDateTime.parse("2013/12/31 23:59:59", formatter);
System.out.println(formatter.format(d6));
//时间获取
System.out.println(d6.getYear());
System.out.println(d6.getMonth());
System.out.println(d6.getDayOfYear());
System.out.println(d6.getDayOfMonth());
System.out.println(d6.getDayOfWeek());
System.out.println(d6.getHour());
System.out.println(d6.getMinute());
System.out.println(d6.getSecond());
}

/***
* 测试ZonedDateTime
*/

public static void testZonedDateTime() {
//即带有时区的date-time 存储纳秒、时区和时差(避免与本地date-time歧义)。
ZonedDateTime now = ZonedDateTime.now(); //默认是本地时区
System.out.println(now);
ZonedDateTime now2 = ZonedDateTime.now(ZoneId.of("Europe/Paris"));
System.out.println(now2);
ZonedDateTime now3 = ZonedDateTime.now(Clock.systemUTC().getZone()); //标准时区
System.out.println(now3);
}

/**
* 测试Date和Instant相互转换
*/

public static void testNewOldDateConversion(){
//instant默认是标准时区
//date 默认是系统默认时区
Instant instant = new Date().toInstant();
Date date = Date.from(instant);
System.out.println(instant);
System.out.println(date);
}
/**
* 测试LocalDate的Adjuster
*/

public static void testAdjustDate() {
LocalDate today = LocalDate.now();
// 取本月第1天:
LocalDate firstDayOfThisMonth = today.with(TemporalAdjusters.firstDayOfMonth());
System.out.println(firstDayOfThisMonth);
// 取本月第2天:
LocalDate secondDayOfThisMonth = today.withDayOfMonth(2);
System.out.println(secondDayOfThisMonth);
// 取本月最后一天,再也不用计算是282930还是31
LocalDate lastDayOfThisMonth = today.with(TemporalAdjusters.lastDayOfMonth());
System.out.println(lastDayOfThisMonth);
// 取下一天:
LocalDate firstDayOf2015 = lastDayOfThisMonth.plusDays(1);
System.out.println(firstDayOf2015);
// 取20151月第一个周一
// ISO yyyy-MMM-dd 验证
LocalDate firstMondayOf2015 = LocalDate.parse("2015-01-01").with(TemporalAdjusters.firstInMonth(DayOfWeek.MONDAY));
System.out.println(firstMondayOf2015);
}
//计算天数之差
LocalDate date2 = LocalDate.now();
LocalDate date1 = LocalDate.of(2016,7,1);

//date1起始,date2结束
long between = ChronoUnit.DAYS.between(date1, date2);
System.out.println(between);