本文已参与「新人创作礼」活动,一起开启掘金创作之路。
java8新的java.time包涵盖了所有处理日期,时间,日期/时间,时区,时刻(instants),过程(during)与时钟(clock)的操作。 最后附上时间处理工具类代码DateUtil.java和获取时间戳性能优化代码SystemClock.java
- Local(本地) − 简化了日期时间的处理,没有时区的问题。
- Zoned(时区) − 通过制定的时区处理日期时间。
LocalDate、 LocalTime、 LocalDateTime
提供了简单的日期或时间,并不包含当前的时间信息。也不包含与时区相关的信息
//获取当前时间
LocalTime time = LocalTime.now();
//获取当前日期
LocalDate date = LocalDate.now();
//获取当前日期和时间
LocalDateTime dateTime = LocalDateTime.now();
LocalDateTime dateTime = LocalDateTime.of(2018, 12, 12, 12, 12, 12);
LocalDateTime dateTime = date.plusYears(2);// +两年
System.out.println(dateTime);// 2020-12-12T12:12:12
LocalDateTime dateTime1 = date.minusMonths(10);// -10月
//比较
boolean flag = localDate.isAfter(localDate2);
//闰年
boolean flag = localDate.isLeapYear();
Instant
用于“时间戳”的运算。它是以Unix元年(传统的设定为UTC时区1970年1月1日午夜时分)开始所经历的描述进行运算
//java7之前获取时间戳方式
long time = System.currentTimeMillis();
System.out.println(time);//1561599260726
//java8时间戳获取
Instant instant = Instant.now();//默认是UTC时区
System.out.println(instant);//2019-06-27T01:42:19.578Z
//带偏移量运算
OffsetDateTime odTime=instant.atOffset(ZoneOffset.ofHours(8));
System.out.println(odTime);//2019-06-27T09:42:19.578+08:00
//获取毫秒显示的格式
long time1= instant.toEpochMilli();
System.out.println(time1);//1561599873015
Duration、Period
Duration:用于计算两个“时间”间隔 Period:用于计算两个“日期”间隔
// Duration
LocalTime localTime1 = LocalTime.of(12, 4, 33);
LocalTime localTime2 = LocalTime.of(12, 5, 45);
Duration duration1 = Duration.between(localTime1, localTime2);
System.out.println(duration1.getSeconds());// 72
System.out.println(duration1.toMinutes());// 1
// Period
LocalDate localDate = LocalDate.now();
LocalDate localDate2 = LocalDate.of(2018, 1, 12);
Period period=Period.between(localDate, localDate2);
System.out.println(period.getDays());
DateTimeFormatter
日期时间格式化类
//1.使用DateTimeFormatter默认提供好的格式对时间格式化,如DateTimeFormatter.ISO_DATE;
DateTimeFormatter formatter = DateTimeFormatter.ISO_DATE;
LocalDateTime localDateTime = LocalDateTime.now();
System.out.println(localDateTime.format(formatter));
//2.自定义时间格式
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy年MM月dd");
LocalDateTime localDateTime = LocalDateTime.now();
System.out.println(localDateTime.format(formatter));
ZonedDate、ZonedTime、ZonedDateTime
时区处理
//查看java8中支持的时区有哪些
Set<String> strings = ZoneId.getAvailableZoneIds();
strings.forEach(System.out::println);
//获取一个指定的时区
ZoneId zoneId = ZoneId.of("Asia/Shanghai");
//获取指定时区的当前时间
LocalDateTime localDateTime = LocalDateTime.now(zoneId);
System.out.println(localDateTime);
ZonedDateTime localDateTime2 = localDateTime.atZone(zoneId);
System.err.println(localDateTime2);//2019-06-27T10:44:53.672+08:00[Asia/Shanghai]
DateUtil.java
public class DateUtil {
public static final String YYMMDD = "yyMMdd";
public static final String YYYYMMDD = "yyyy-MM-dd";
public static final String YYYYMMDDHHMMSS = "yyyy-MM-dd HH:mm:ss";
public static final String YYMMDDHHMMSS_SHORT = "yyMMddHHmmss";
public static final String YYYYMMDDTHHMM = "yyyy-MM-dd'T'HH:mm";
public static String date2str(Date date, String format) {
if (date == null) {
return null;
}
LocalDateTime localDateTime = LocalDateTime.ofInstant(date.toInstant(), ZoneId.systemDefault());
return localDateTime.format(DateTimeFormatter.ofPattern(format));
}
public static String date2str(LocalDateTime localDateTime, DateTimeFormatter format) {
if (localDateTime == null) {
return null;
}
return localDateTime.format(format);
}
public static Date str2date(String dateStr, String format) {
if (StringUtils.isBlank(dateStr)) {
return null;
}
if (YYYYMMDD.equals(format)) {
LocalDate localDate = LocalDate.parse(dateStr, DateTimeFormatter.ISO_LOCAL_DATE);
return Date.from(localDate.atStartOfDay(ZoneId.systemDefault()).toInstant());
} else {
LocalDateTime localDateTime = LocalDateTime.parse(dateStr, DateTimeFormatter.ofPattern(format));
return Date.from(localDateTime.atZone(ZoneId.systemDefault()).toInstant());
}
}
public static long dateDifferMinute(Date startDate, Date endDate) {
if (startDate == null) {
startDate = new Date();
}
if (endDate == null) {
endDate = new Date();
}
return (endDate.getTime() - startDate.getTime()) / (1000 * 60);
}
public static long dateDifferDay(Date startDate, Date endDate) {
if (startDate == null) {
startDate = new Date();
}
if (endDate == null) {
endDate = new Date();
}
return (endDate.getTime() - startDate.getTime()) / (1000 * 60 * 60 * 24);
}
public static LocalDateTime getLocalDateTimeOfTimestamp(long timestamp) {
Instant instant = Instant.ofEpochMilli(timestamp);
ZoneId zone = ZoneId.systemDefault();
return LocalDateTime.ofInstant(instant, zone);
}
public static LocalDateTime addDateTime(LocalDateTime baseDateTime, long amountToAdd, ChronoUnit unit) {
return baseDateTime.plus(amountToAdd, unit);
}
SystemClock.java
System.currentTimeMillis()是比较重的调用,调用时候要进行内核态/用户态切换,应该让真正在忙着的那些线程尽量少切换。
SystemClock的时间精度不那么高,所以不能用在要求时间非常精准的场景。
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicLong;
// System.currentTimeMillis()是比较重的调用,调用时候要进行内核态/用户态切换,应该让真正在忙着的那些线程尽量少切换
// SystemClock的时间精度不那么高,所以不能用在要求时间非常精准的场景
public class SystemClock {
private static final String THREAD_NAME = "system-clock-daemon-thread";
private static final SystemClock SYSTEM_CLOCK = new SystemClock(1);
private final long precision;
private final AtomicLong now;
public SystemClock(long precision) {
this.precision = precision;
now = new AtomicLong(System.currentTimeMillis());
scheduleClockUpdating();
}
private void scheduleClockUpdating() {
ScheduledExecutorService scheduler = Executors.newSingleThreadScheduledExecutor(new ThreadFactory() {
@Override
public Thread newThread(Runnable runnable) {
Thread thread = new Thread(runnable, THREAD_NAME);
thread.setDaemon(true);
return thread;
}
});
scheduler.scheduleAtFixedRate(new Runnable() {
@Override
public void run() {
now.set(System.currentTimeMillis());
}
}, precision, precision, TimeUnit.MILLISECONDS);
}
public long now() {
return now.get();
}
public long precision() {
return precision;
}
public static SystemClock instance() {
return SYSTEM_CLOCK;
}
}