java8日期

由于传统的Date,Caleandar,SimpleDateFormat都是可变的,线程不安全的,多线程环境下需要考虑线程安全问题。而java8推出的新的日期API很好的解决了线程安全问题,而且操作简单,绝对优雅。

一、常用API

1.LocalDateTime

java8中将时间和日期进行了区分,用LocalDateTime表示日期和时间,LocalDate表示日期,LocalTime表示时间。从命名也可以看出:LocalDateTime = LocalDate + LocalTime。LocalDateTime类似于 Calendar

式例:

// 获取当前时间
LocalDateTime localDateTime = LocalDateTime.now();
System.out.println(localDateTime);  //打印:2019-12-05T16:31:06.153

// 获取指定时间
LocalDateTime localDateTime2 = LocalDateTime.of(2019, 12, 5, 16, 28, 59);
System.out.println(localDateTime2); //打印:2019-12-05T16:28:59

// 日期加减
LocalDateTime localDateTime3 = localDateTime2.plusDays(1).plusSeconds(1);
System.out.println(localDateTime3); //打印:2019-12-06T16:29

// 获取具体的年、月、日、时、分、秒  //打印:现在是: 2019 年中的第 339 天
System.out.println("现在是: " + localDateTime.getYear() + " 年中的第 " + localDateTime.getDayOfYear() +" 天");
2.LocalDate

LocalDate是日期的API,不包含时间,用法基本上同LocalDateTime一样(都实现了Temporal接口)。

式例:

// 获取当前日期
LocalDate localDate = LocalDate.now();
System.out.println(localDate);  //打印:2019-12-05

// 获取指定时间
LocalDate localDate2 = LocalDate.of(2019, 12, 5);
System.out.println(localDate2); //打印:2019-12-05

// 日期加减
LocalDate localDate3 = localDate2.plusDays(1);
System.out.println(localDate3); //打印:2019-12-06

// 获取具体的年、月、日  //打印:现在是: 2019 年中的第 339 天
System.out.println("现在是: " + localDate.getYear() + " 年中的第 " + localDate.getDayOfYear() +" 天");
3.LocalTime

LocalTime是时间的API,不包含日期,用法基本上同LocalDateTime一样(都实现了Temporal接口)。

式例:

// 获取当前时间
LocalTime localTime = LocalTime.now();
System.out.println(localTime);  //打印:16:40:58.014

// 获取指定时间
LocalTime localTime2 = LocalTime.of(16, 12, 45);
System.out.println(localTime2); //打印:16:12:45

// 时间加减
LocalTime localTime3 = localTime2.plusHours(1);
System.out.println(localTime3); //打印:17:12:45

// 获取具体的时、分、秒  //打印:现在是: 16 点 40 分
System.out.println("现在是: " + localTime.getHour() + " 点 " + localDateTime.getMinute() +" 分");
4.Instant

Instant代表的是时间戳,类似于Date,在java.util.Date类与LocalDate、LocalDateTime类之间转换中 均可以通过Instant作为中间类完成转换,Instant的使用还是比较方便的。

tip:地球上不同地区经度不同会划分时区,以零度经线上为准(格林尼治天文台旧址,UTC时区)为准,将地球上各个部分分为了24个时区。向西走,每过一个时区,就要把表拨慢1个小时;同理每向东走一个时区,就要把表拨快1个小时。最后,中国处于东8区。

式例:

// 获取UTC时间(格林尼治时间)
Instant instant = Instant.now();
System.out.println(instant);   // 打印结果: 2019-12-05T09:05:16.641Z

// 获取北京时间(东8区) OffsetTime表示有时差的时间,除了UTC时间,都是OffsetTime
OffsetDateTime offsetDateTime = instant.atOffset(ZoneOffset.ofHours(8));
System.out.println(offsetDateTime);   // 打印结果: 2019-12-05T17:05:16.641+08:00

// 获取毫秒数
instant.plusSeconds(10).plusMillis(1000);
System.out.println(instant.toEpochMilli());  // 打印:1575536872052
5.Period

Period是用来计算日期间隔的函数,式例:

LocalDate localDate1 = LocalDate.now();
LocalDate localDate2 = localDate1.plusDays(1);
Period period = Period.between(localDate1, localDate2);   //打印:间隔:0年,0月,1天
System.out.println("间隔:" + period.getYears() + "年," + period.getMonths() +"月,"+ period.getDays() +"天");
6.Duration

Duration是用来计算间隔时间间隔的,式例:

LocalDateTime localDateTime1 = LocalDateTime.now();
LocalDateTime localDateTime2 = localDateTime1.plusDays(1);
Duration duration = Duration.between(localDateTime1, localDateTime2); 
System.out.println("间隔:" + duration.getSeconds() + "秒");  //间隔:86400秒

LocalTime localTime1 = LocalTime.now();
LocalTime localTime2 = localTime1.plusHours(1);
Duration duration1 = Duration.between(localTime1, localTime2);  
System.out.println("间隔:" + duration1.getSeconds() + "秒");  //间隔:3600秒

Instant instant1 = Instant.now();
Instant instant2 = instant1.plusSeconds(100);
Duration duration2 = Duration.between(instant1, instant2); 
System.out.println("间隔:" + duration2.getSeconds() + "秒");  //间隔:100秒
7.DateTimeFormatter

DateTimeFormatter是日期格式化工具,类似于SimpleDateFormat,但是DateTimeFormatter是线程安全的,式例:

DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
LocalDateTime localDateTime = LocalDateTime.now();
String dateStr =dateTimeFormatter.format(localDateTime);
System.out.println(dateStr);    // 打印结果: 2019-12-05 17:10:39

LocalDateTime localDateTime = LocalDateTime.parse(dateStr, dateTimeFormatter);
System.out.println(localDateTime);   // 打印结果: 2019-12-05T17:10:39

LocalDate localDate = LocalDate.parse(dateStr, dateTimeFormatter);
System.out.println(localDate);   // 打印结果: 2019-12-05

二、应用场景

1.求时间差
Date startTime = new Date();
long seconds = Duration.between(startTime.toInstant(), Instant.now()).getSeconds();
2.date 与 LocalDateTime的转换
// date 转化为LocalDateTime
Date date = new Date();
Instant instant = date.toInstant();
ZoneId zoneId = ZoneId.systemDefault();
LocalDateTime localDateTime = instant.atZone(zoneId).toLocalDateTime();
System.out.println(localDateTime);  // 打印: 2019-12-05T17:37:27.459

// LocalDateTime 转化为date
LocalDateTime localDateTime = LocalDateTime.now();
ZoneId zoneId = ZoneId.systemDefault();
ZonedDateTime zdt = localDateTime.atZone(zoneId);
Date date = Date.from(zdt.toInstant());
System.out.println(date);  // 打印:Thu Dec 05 17:38:37 CST 2019
3.LocalDateTime与LocalDate、LocalTime互转
LocalDateTime localDateTime = LocalDateTime.now();
System.out.println(localDateTime.toLocalDate());  //打印:2019-12-05
System.out.println(localDateTime.toLocalTime());  //打印:17:36:16.927
4.LocalDateTime、LocalDate、LocalTime与字符串的相互转换
String nowDateStr = LocalDate.now().toString();
System.out.println(nowDateStr);//2019-12-05

LocalDate nowDate = LocalDate.parse("2019-12-05");
System.out.println(nowDate.toString());//2019-12-05


String nowTimeStr = LocalTime.now().toString();
System.out.println(nowTimeStr);//17:40:52.823

LocalTime nowTime = LocalTime.parse("12:10:13");
System.out.println(nowTime.toString());//12:10:13

System.out.println(LocalDateTime.now().toString());//2019-12-05T17:40:52.824
System.out.println(LocalDateTime.now().toLocalDate().toString());//2019-12-05
System.out.println(LocalDateTime.now().toLocalTime().toString());//17:40:52.824

三、DateUtil工具类

import java.text.SimpleDateFormat;
import java.time.*;
import java.time.format.DateTimeFormatter;
import java.time.temporal.ChronoUnit;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * @description:
 * @author: zhangcb
 * @create: 2019-12-20 10:11
 **/
public class DateUtil {


    /**
     * 求两个日期时间差
     * @param startTime 开始时间
     * @param endTime 结束时间
     * @return 相隔秒
     */
    public static long between(Date startTime, Date endTime){
        return Duration.between(startTime.toInstant(), endTime.toInstant()).getSeconds();
    }

    /**
     * 求两个日期时间差
     * @param startTime 开始时间
     * @param endTime 结束时间
     * @return 相隔秒
     */
    public static long between(LocalDateTime startTime, LocalDateTime endTime){
        return Duration.between(startTime, endTime).getSeconds();
    }

    /**
     * 格式化日期
     * @param date 待格式化的日期
     * @param pattern 格式化正则
     * @return 格式化结果串
     */
    public static String format(Date date, String pattern){
        return new SimpleDateFormat(pattern).format(date);
    }

    /**
     * 格式化日期
     * @param localDateTime 待格式化的日期
     * @param pattern 格式化正式
     * @return 格式化结果串
     */
    public static String format(LocalDateTime localDateTime, String pattern){
        return localDateTime.format(DateTimeFormatter.ofPattern(pattern));
    }

    /**
     * 格式化日期
     * @param localDate 待格式化的日期
     * @param pattern 格式化正则, 这里使用的类型 {@link LocalDate}, 所以正则只能设定到天
     * @return 格式化结果串
     */
    public static String format(LocalDate localDate, String pattern){
        return localDate.format(DateTimeFormatter.ofPattern(pattern));
    }


    /**
     * 将 {@link LocalDateTime} 转换成 {@link Date}
     * @param localDateTime {@link LocalDateTime} 待转换的日期
     * @return 转换成Date结果
     */
    public static Date from(LocalDateTime localDateTime){
        Instant instant = localDateTime.atZone(ZoneId.systemDefault()).toInstant();
        return Date.from(instant);
    }

    /**
     * 将 {@link Date} 转换成 {@link LocalDateTime}
     * @param date {@link Date} 待转换的日期
     * @return 转换成 {@link LocalDateTime} 结果
     */
    public static LocalDateTime from(Date date){
        return LocalDateTime.ofInstant(date.toInstant(), ZoneId.systemDefault());
    }


    /**
     * 获取{@link Date}在开始时间和结束时间内的日期时间段{@link Date}集合
     * @param start 开始时间
     * @param end 结束时间
     * @return 时间天数集合
     */
    public static List<Date> dateZones(Date start, Date end){
        return dateZones(from(start), from(end));
    }


    /**
     * 获取 {@link LocalDate} 在开始时间和结束时间内的日期时间段 {@link LocalDate} 集合
     * @param start 开始时间
     * @param end 结束时间
     * @return 时间集合
     */
    public static List<Date> dateZones(LocalDate start, LocalDate end){
        return Stream.iterate(start, x -> x.plusDays(1))
                .limit(ChronoUnit.DAYS.between(start, end) + 1)
                .map(e -> Date.from(e.atStartOfDay().atZone(ZoneId.systemDefault()).toInstant()))
                .collect(Collectors.toList());
    }


    /**
     * 获取{@link LocalDateTime} 在开始时间和结束时间内的日期时间段{@link Date}集合
     * @param start 开始时间
     * @param end 结束时间
     * @return 时间天数集合
     */
    public static List<Date> dateZones(LocalDateTime start, LocalDateTime end){
        // 用起始时间作为流的源头,按照每次加一天的方式创建一个无限流
        return Stream.iterate(start.toLocalDate(), x -> x.plusDays(1))
                // 截断无限流,长度为起始时间和结束时间的差+1个
                .limit(ChronoUnit.DAYS.between(start, end) + 1)
                // 由于最后要的是字符串,所以map转换一下
                .map(e -> Date.from(e.atStartOfDay().atZone(ZoneId.systemDefault()).toInstant()))
                // 把流收集为List
                .collect(Collectors.toList());
    }


    /**
     * 获取{@link Date}在开始时间和结束时间内的日期时间段{@link LocalDate}集合
     * @param start 开始时间
     * @param end 结束时间
     * @return 时间集合
     */
    public static List<LocalDate> localDateZones(Date start, Date end){
        return localDateZones(from(start), from(end));
    }


    /**
     * 获取 {@link LocalDate} 在开始时间和结束时间内的日期时间段 {@link LocalDate} 集合
     * @param start 开始时间
     * @param end 结束时间
     * @return 时间集合
     */
    public static List<LocalDate> localDateZones(LocalDate start, LocalDate end){
        return Stream.iterate(start, x -> x.plusDays(1))
                .limit(ChronoUnit.DAYS.between(start, end) + 1)
                .collect(Collectors.toList());
    }

    /**
     * 获取 {@link LocalDateTime} 在开始时间和结束时间内的日期时间段 {@link LocalDate} 集合
     * @param start 开始时间
     * @param end 结束时间
     * @return 时间集合
     */
    public static List<LocalDate> localDateZones(LocalDateTime start, LocalDateTime end){
        // 用起始时间作为流的源头,按照每次加一天的方式创建一个无限流
        return Stream.iterate(start.toLocalDate(), x -> x.plusDays(1))
                // 截断无限流,长度为起始时间和结束时间的差+1个
                .limit(ChronoUnit.DAYS.between(start, end) + 1)
                .map(e -> e.atStartOfDay().toLocalDate())
                // 把流收集为List
                .collect(Collectors.toList());
    }


}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值