JAVA8 常用日期处理

mgs2002 2020年05月14日 143次浏览

由于项目里开始使用Java8的日期处理方法,下面简单总结一下。

新的日期类

JAVA8推出了新的日期API类ZoneId、ZoneOffset、LocalDateTime、ZonedDateTime 和 DateTimeFormatter,通过这些全新的类使得操作时间变得更加简单和清晰。

Instant:时间戳,相当于java.util的Date
LocalDate:只包含日期,比如:2016-10-20
LocalTime:只包含时间,比如:23:12:10
LocalDateTime:包含日期和时间,比如:2016-10-20 23:14:21
Duration:计算两个“时间”的间隔
Period:用于计算两个“日期”的间隔
ZoneId: 时区ID,用来确定Instant和LocalDateTime互相转换的规则
ZoneOffset:时区偏移量,比如:+8:00(北京时间)
ZonedDateTime:可以得到特定时区的日期/时间,相当于LocalDateTime+ZoneId
Clock:时钟,比如获取目前美国纽约的时间
DateTimeFormatter:格式化器,用于对时间进行格式化

常用方法总结

1. 当前时间

System.out.println("当前时间:"+LocalDate.now());

输出:

当前时间:2020-05-15

2. 时间戳

System.out.println("当前时间:"+Instant.now());
System.out.println("当前时间:"+Instant.now().atZone(ZoneId.systemDefault()));

输出:

当前时间:2020-05-15T06:59:57.825Z
当前时间:2020-05-15T14:59:57.842+08:00[Asia/Shanghai]

可以看到直接使用Instant.now()返回时间跟北京时间相差8小时,这是因为Instant.now()使用了UTC时间(格林威治时间) Clock.systemUTC().instant()
UTC_TIME.png
解决方法是设置Instant.now()的时区为系统默认时区ZoneId.systemDefault()(上面代码第二行)或者直接加8小时

Instant now = Instant.now().plusMillis(TimeUnit.HOURS.toMillis(8));
System.out.println("当前时间:"+now);

输出:

当前时间:2020-05-15T15:24:16.406Z

如果想获取秒级或者毫秒级别时间戳看如下代码

System.out.println("毫秒:"+Instant.now().toEpochMilli());
System.out.println("秒:"+Instant.now().getEpochSecond());

输出:

毫秒:1589531324749
秒:1589531324

3. 某月的开始日期和结束日期

/**
* 获取某月的开始日期
 *
* @param offset 0本月,1下个月,-1上个月,依次类推
* @return
*/
public static LocalDate monthStart(int offset) {
	return LocalDate.now().plusMonths(offset).with(TemporalAdjusters.firstDayOfMonth());
}

/**
 * 获取某月的结束日期
 *
 * @param offset 0本月,1下个月,-1上个月,依次类推
 * @return
*/
public static LocalDate monthEnd(int offset) {
	return LocalDate.now().plusMonths(offset).with(TemporalAdjusters.lastDayOfMonth());
}

System.out.println("当月开始时间:"+monthStart(0));
System.out.println("当月结束时间:"+monthEnd(0));

输出:

当月开始时间:2020-05-01
当月结束时间:2020-05-31

offset为0表示当月,如果想查询两个月前的开始和结束日期可将其设置为-2,如下所示:

System.out.println("第一天:"+monthStart(-2));
System.out.println("最后一天:"+monthEnd(-2));

输出:

第一天:2020-03-01
最后一天:2020-03-31

4. 时间转换为时间戳

public static Long convertTimeToLong(String time) {

	DateTimeFormatter ftf = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
	LocalDateTime parse = LocalDateTime.parse(time, ftf);
	return LocalDateTime.from(parse).atZone(ZoneId.systemDefault()).toInstant().toEpochMilli();
}	
System.out.println(DateUtil.convertTimeToLong("2020-04-01 00:00:00"));
System.out.println(DateUtil.convertTimeToLong("2020-04-30 23:00:00"));

输出:

1585670400000
1588258800000

注意源码里面的时间格式为yyyy-MM-dd HH:mm:s,如果改为yyyy-MM-dd会报错,如图所示
exception.png
这是因为转换时间戳方法里面使用了DateTimeFormatter,所以时间格式必须包含时分秒

5. 时间戳转时间

public static String convertTimeToString(Long time){
	DateTimeFormatter ftf = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
	return ftf.format(LocalDateTime.ofInstant(Instant.ofEpochMilli(time),ZoneId.systemDefault()));
}
System.out.println("时间戳转时间:"+DateUtil.convertTimeToString(1588258800000L));

输出:

时间戳转时间:2020-04-30 23:00:00

注意:时间格式需为yyyy-MM-dd HH:mm:s,原因见第4点

6. 获取两个时间的相隔天数

public static long getDaysBetweenTwoTimes(String startTime,String endTime){
	DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
	LocalDate startDate = LocalDate.parse(startTime, formatter);
	LocalDate endDate = LocalDate.parse(endTime, formatter);
	long days = ChronoUnit.DAYS.between(startDate, endDate);
	return days>=0?days+1:days;
}
System.out.println(DateUtil.getDaysBetweenTwoTimes("2020-03-01 00:00:00","2020-03-31 00:00:00"));

输出:

31

7. 根据日期加/减天数

LocalDate date = LocalDate.parse("2020-05-18");
LocalDate tomorrow = date.plusDays(1);
LocalDate yesterday = date.minusDays(1);
System.out.println(tomorrow);
System.out.println(yesterday);

输出:

tomorrow:2020-05-19
yesterday:2020-05-17

plusDaysminusDays获取的是传入的具体天数,如果想一次性添加一周或者几周的天数可以使用plusWeeks

LocalDate date = LocalDate.parse("2020-05-18");
LocalDate tomorrow = date.plusWeeks(1);
LocalDate nextWeek= date.minusDays(1);
System.out.println(nextWeek);

输出:

nextWeek:2020-05-25

还可以添加月、年的天数,如图
other.png

minus_other.png
....待补充