java8 新时间日期API

传统时间格式化的线程安全问题

public class TestSimpleDateFormat {
    @Test
    public void test01(){
        SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd");

        Callable<Date> task = new Callable<Date>() {
            @Override
            public Date call() throws Exception {
                return sdf.parse("20161218");
            }
        };

        ExecutorService pool = Executors.newFixedThreadPool(10);

        List<Future<Date>> results = new ArrayList<>();
        for (int i = 0; i < 10; i++) {
            results.add(pool.submit(task));
        }
        for (Future<Date> future : results) {
            try {
                System.out.println(future.get());
            } catch (InterruptedException e) {
                e.printStackTrace();
            } catch (ExecutionException e) {
                e.printStackTrace();
            }
        }
        pool.shutdown();
    }

}

加锁:

public class DateFormatThreadLocal {
    private static final ThreadLocal<DateFormat> df = ThreadLocal.withInitial(() -> new SimpleDateFormat("yyyyMMdd"));

    public static Date convert(String source) throws ParseException {
        return df.get().parse(source);
    }
}
 @Test
    public void test02(){
        Callable<Date> task = () -> DateFormatThreadLocal.convert("20161218");

        ExecutorService pool = Executors.newFixedThreadPool(10);

        ArrayList<Future<Date>> result = new ArrayList<>();
        for (int i = 0; i < 10; i++) {
            result.add(pool.submit(task));
        }

        for (Future<Date> future : result) {
            try {
                System.out.println(future.get());
            } catch (InterruptedException | ExecutionException e) {
                e.printStackTrace();
            }
        }
        pool.shutdown();
    }

java8:localDate DateTimeFormatter----线程安全

 @Test
    public void test03(){
        DateTimeFormatter dtf =DateTimeFormatter.ofPattern("yyyyMMdd");
        Callable<LocalDate> task = new Callable<LocalDate>() {
            @Override
            public LocalDate call() throws Exception {
                return LocalDate.parse("20161218",dtf);
            }
        };

        ExecutorService pool = Executors.newFixedThreadPool(10);

        List<Future<LocalDate>> results = new ArrayList<>();
        for (int i = 0; i < 10; i++) {
            results.add(pool.submit(task));
        }
        for (Future<LocalDate> future : results) {
            try {
                System.out.println(future.get());
            } catch (InterruptedException e) {
                e.printStackTrace();
            } catch (ExecutionException e) {
                e.printStackTrace();
            }
        }

        pool.shutdown();
    }

一、本地时间

使用LocalDate(表示日期) LocalTime(表示时间) LocalDateTime(时间日期)

  • 这三个类的实例是不可变的对象,分别表示使用ISO-8601日历系统的日期\时间\日期和时间.他们提供了简单的日期或时间,并不包含当前的时间信息,也不包含与时区相关的信息
  • ISO-8601日历系统是国际标准化组织指定的现代公民的日期和时间的表示法

常用方法:

方法名返回值类型解释
now( )LocalDateTime从默认时区的系统时钟获取当前日期
of(int year, int month, int dayOfMonth, int hour, int minute, int second)LocalDateTime从年,月,日,小时,分钟和秒获得 LocalDateTime的实例,将纳秒设置为零
plus(long amountToAdd, TemporalUnit unit)LocalDateTime返回此日期时间的副本,并添加指定的数量
get(TemporalField field)int从此日期时间获取指定字段的值为 int
public class TestLocalDateTime {
    // 1:LocalDate  LocalTime  LocalDateTime
    @Test
    public void test1(){
        // 获取当前系统时间 now
        LocalDateTime localDateTime = LocalDateTime.now();
        System.out.println(localDateTime);// 2022-06-15T16:02:03.464

        // 指定时间 of
        LocalDateTime of = LocalDateTime.of(2015, 10, 10, 13, 22, 33);
        System.out.println(of);// 2015-10-10T13:22:33

        // 加时间 plus
        LocalDateTime time = localDateTime.plusYears(2);
        System.out.println(time);// 2024-06-15T16:02:03.464

        // 减时间 minus
        LocalDateTime time1 = localDateTime.minusMonths(2);

        // 获取指定的你年月日时分秒... get
        System.out.println(localDateTime.getYear());//2022
        System.out.println(localDateTime.getMonthValue());// 6
        System.out.println(localDateTime.getDayOfMonth());// 15
        System.out.println(localDateTime.getHour());// 16
        System.out.println(localDateTime.getMinute()); // 2
        System.out.println(localDateTime.getSecond());// 3
    }
}

二、Instant 时间戳

Instant:以 Unix 元年 1970-01-01 00:00:00 到某个时间之间的毫秒值

// 2:Instant 时间戳 (以Unix元年 1970/1/1 00:00:00 到某个时间之间的毫秒值)
    @Test
    public void test2(){
        // 获取当前时间戳 默认获取 UTC 时区 (UTC:世界协调时间)
        Instant now = Instant.now();
        System.out.println(now);// 2022-06-15T08:04:42.444Z(默认获取的UTC时区)

        // 带偏移量的时间日期 (如:UTC + 8)
        OffsetDateTime odt = now.atOffset(ZoneOffset.ofHours(8));
        System.out.println(odt);// 2022-06-15T16:04:42.444+08:00

        //转换成对应的毫秒值
        long epochMilli = now.toEpochMilli();
        System.out.println(epochMilli);// 1655280282444

        //构建时间戳(相较于元年进行的运算)
        Instant instant = Instant.ofEpochSecond(60);
        System.out.println(instant);// 1970-01-01T00:01:00Z
    }

三、计算时间之间的间隔

Duration:计算两个时间之间的间隔
Period:计算两个日期之间的间隔

@Test
    public void test3(){
        Instant ins1= Instant.now();
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        Instant ins2= Instant.now();
        Duration duration = Duration.between(ins1, ins2);
        System.out.println(duration);//PT1.012S
        System.out.println(duration.getSeconds());// 秒 1
        System.out.println(duration.toMillis());// 毫秒 1001

    }
    @Test
    public void test4() {
        LocalTime localTime = LocalTime.now();
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        LocalTime localTime2 = LocalTime.now();
        System.out.println(Duration.between(localTime,localTime2).toMillis());//1006
    }
@Test
    public void test5(){
        LocalDate ld1 = LocalDate.of(2020,1,1);
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        LocalDate ld2 = LocalDate.now();
        Period period = Period.between(ld1, ld2);
        System.out.println(period);//P1Y3M9D
        System.out.println(period.getYears());//1
        System.out.println(period.getMonths());//3
        System.out.println(period.getDays());//9
    }

四、时间校正器

日期的操纵:

  • TemporalAdjuster:时间校正器(例如:将日期调整到下个周日等操作)
  • TemporalAdjusters:该类通过静态方法提供了大量用TemporalAdjuster的实现
 // TemporalAdjuster 时间校正器
    @Test
    public void test6(){
        LocalDateTime ldt = LocalDateTime.now();
        System.out.println(ldt);//2022-06-15T16:12:20.108

        // //指定日期时间中的 年 月 日 ... .withXXX
        LocalDateTime ldt2 = ldt.withDayOfMonth(5);
        System.out.println(ldt2);//2022-06-05T16:12:20.108

        //指定时间校正器 (指定为下一个周日)
        LocalDateTime ldt3 = ldt.with(TemporalAdjusters.next(DayOfWeek.SUNDAY));
        System.out.println(ldt3);// 2022-06-19T16:12:20.108

        //自定义时间校正器 (指定下一个工作日)
        LocalDateTime time = 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(time);//2022-06-16T16:12:20.108

    }

五、时间格式化和时区的处理

DateTimeFormatter:格式化时间 / 日期

@Test
    public void test7(){
        //默认格式化
        DateTimeFormatter dtf =DateTimeFormatter.ISO_DATE;
        LocalDateTime ldt = LocalDateTime.now();

        String strDate = ldt.format(dtf);
        System.out.println(strDate);//2022-06-15

        // 自定义格式化
        DateTimeFormatter dtf2= DateTimeFormatter.ofPattern("yyyy年MM月dd日 HH:mm:ss");
        String strDate2 = dtf2.format(ldt);
        System.out.println(strDate2);//2022年06月15日 16:19:02

        //解析
        LocalDateTime newDate = ldt.parse(strDate2,dtf2);
        System.out.println(newDate);// 2022-06-15T16:19:02
    }

时区的处理

ZonedDate、ZonedTime、ZonedDateTime
其中每个时区都对应着ID,地区ID都为"{区域}/{城市}"的格式 [ 例如:Asia/Shanghai ]

  • ZoneId:该类包含了所有的时区信息
  • getAvailableZoneIds:可以获取所有时区的信息
  • of(id):用指定的时区信息获取ZoneId对象
 // 时区的处理
    @Test
    public void test8(){
        // 获取所有的时区
        Set<String> ids = ZoneId.getAvailableZoneIds();
        ids.forEach(System.out::println);

        // 指定时区
        LocalDateTime ldt = LocalDateTime.now(ZoneId.of("Europe/Tallinn"));
        System.out.println(ldt);//2022-06-15T11:22:49.753

        // 在已构建好的日期时间上指定时区
        LocalDateTime now = LocalDateTime.now(ZoneId.of("Asia/Shanghai"));
        ZonedDateTime zdt = now.atZone(ZoneId.of("Asia/Shanghai"));
        System.out.println(zdt);// 2022-06-15T16:22:49.757+08:00[Asia/Shanghai]
    }

 JAVA 8 时间工具类 

import java.time.*;
import java.time.format.DateTimeFormatter;
import java.time.temporal.Temporal;
import java.time.temporal.TemporalAdjuster;
import java.time.temporal.TemporalAdjusters;
import java.util.Date;

/**
 * JAVA 8 时间工具类
 *
 * @author bood
 * @since 2020/9/25
 */
public class DateTimeUtils {

    /**
     * 格式:yyyy-MM-dd HH:mm:ss
     */
    public static final DateTimeFormatter DATETIME_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
    /**
     * 格式:yyyy-MM-dd
     */
    public static final DateTimeFormatter DATE_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd");
    /**
     * 格式:HH:mm:ss
     */
    public static final DateTimeFormatter TIME_FORMATTER = DateTimeFormatter.ofPattern("HH:mm:ss");


    private DateTimeUtils() {
    }


    // ------------------------------------------- 获取时间 -------------------------------------------

    /**
     * 返回 当前时间的(yyyy-MM-dd HH:mm:ss)
     *
     * @return yyyy-MM-dd HH:mm:ss
     */
    public static LocalDateTime get() {
        return LocalDateTime.now();
    }

    /**
     * 返回 当前时间的(yyyy-MM-dd)
     *
     * @return yyyy-MM-dd
     */
    public static LocalDate getCurrentLocalDate() {
        return LocalDate.now();
    }

    /**
     * 返回 当前时间的(HH:mm:ss)
     *
     * @return HH:mm:ss
     */
    public static LocalTime getCurrentLocalTime() {
        return LocalTime.now();
    }

    // ------------------------------------------- 时间格式化 -------------------------------------------

    /**
     * <p>
     * yyyy-MM-dd HH:mm:ss 转 LocalDateTime 类型
     * </p>
     *
     * @param dateTimeStr: yyyy-MM-dd HH:mm:ss
     * @return:java.time.LocalDateTime
     * @author:bood
     * @date:2020/9/25
     */
    public static LocalDateTime parseLocalDateTime(String dateTimeStr) {
        return LocalDateTime.parse(dateTimeStr, DATETIME_FORMATTER);
    }

    /**
     * <p>
     * yyyy-MM-dd 转 LocalDate 类型
     * </p>
     *
     * @param dateStr: yyyy-MM-dd
     * @return:java.time.LocalDate
     * @author:bood
     * @date:2020/9/25
     */
    public static LocalDate parseLocalDate(String dateStr) {
        return LocalDate.parse(dateStr, DATE_FORMATTER);
    }

    /**
     * <p>
     * HH:mm:ss 转 LocalTime 类型
     * </p>
     *
     * @param timeStr: HH:mm:ss
     * @return:java.time.LocalTime
     * @author:bood
     * @date:2020/9/25
     */
    public static LocalTime parseLocalTime(String timeStr) {
        return LocalTime.parse(timeStr, TIME_FORMATTER);
    }

    /**
     * <p>
     * LocalDateTime 转 yyyy-MM-dd HH:mm:ss
     * </p>
     *
     * @param datetime: LocalDateTime
     * @return:java.lang.String
     * @author:bood
     * @date:2020/9/25
     */
    public static String formatLocalDateTime(LocalDateTime datetime) {
        return datetime.format(DATETIME_FORMATTER);
    }

    /**
     * <p>
     * LocalDate 转 yyyy-MM-dd
     * </p>
     *
     * @param date: LocalDate
     * @return:java.lang.String
     * @author:bood
     * @date:2020/9/25
     */
    public static String formatLocalDate(LocalDate date) {
        return date.format(DATE_FORMATTER);
    }

    /**
     * <p>
     * LocalTime 转 HH:mm:ss
     * </p>
     *
     * @param time: LocalTime
     * @return:java.lang.String
     * @author:bood
     * @date:2020/9/25
     */
    public static String formatLocalTime(LocalTime time) {
        return time.format(TIME_FORMATTER);
    }

    // ------------------------------------------- 时间计算 -------------------------------------------

    /**
     * <p>
     * 当前时间延期几天
     * </p>
     *
     * @param days: 天数
     * @return:java.time.LocalDateTime
     * @author:bood
     * @date:2020/9/25
     */
    public static LocalDateTime plusDays(int days) {
        return get().plusDays(days);
    }

    /**
     * <p>
     * 日期相隔天数
     * </p>
     *
     * @param startDateInclusive: 开始时间
     * @param endDateExclusive:   结束时间
     * @return:int
     * @author:bood
     * @date:2020/9/25
     */
    public static int periodDays(LocalDate startDateInclusive, LocalDate endDateExclusive) {
        return Period.between(startDateInclusive, endDateExclusive).getDays();
    }

    /**
     * <p>
     * 日期相隔小时
     * </p>
     *
     * @param startInclusive: 开始时间
     * @param endExclusive:   结束时间
     * @return:long
     * @author:bood
     * @date:2020/9/25
     */
    public static long durationHours(Temporal startInclusive, Temporal endExclusive) {
        return Duration.between(startInclusive, endExclusive).toHours();
    }

    /**
     * <p>
     * 日期相隔分钟
     * </p>
     *
     * @param startInclusive: 开始时间
     * @param endExclusive:   结束时间
     * @return:long
     * @author:bood
     * @date:2020/9/25
     */
    public static long durationMinutes(Temporal startInclusive, Temporal endExclusive) {
        return Duration.between(startInclusive, endExclusive).toMinutes();
    }

    /**
     * <p>
     * 日期相隔毫秒数
     * </p>
     *
     * @param startInclusive: 开始时间
     * @param endExclusive:   结束时间
     * @return:long
     * @author:bood
     * @date:2020/9/25
     */
    public static long durationMillis(Temporal startInclusive, Temporal endExclusive) {
        return Duration.between(startInclusive, endExclusive).toMillis();
    }

    /**
     * <p>
     * 返回 指定年份的(yyyy-MM-dd HH:mm:ss)
     * </p>
     *
     * @param year: 年份
     * @return:java.time.LocalDateTime
     * @author:bood
     * @date:2020/9/25
     */
    public static LocalDateTime withYear(int year) {
        return get().withYear(year);
    }

    /**
     * <p>
     * 返回 指定年份的 第一天时间
     * </p>
     *
     * @param year: 年份
     * @return:java.time.LocalDateTime
     * @author:bood
     * @date:2020/9/25
     */
    public static LocalDateTime firstDayOfThisYear(int year) {
        return withYear(year).with(TemporalAdjusters.firstDayOfYear()).with(LocalTime.MIN);
    }

    /**
     * <p>
     * 返回 指定年份的 最末天时间
     * </p>
     *
     * @param year: 年份
     * @return:java.time.LocalDateTime
     * @author:bood
     * @date:2020/9/25
     */
    public static LocalDateTime lastDayOfThisYear(int year) {
        return withYear(year).with(TemporalAdjusters.lastDayOfYear()).with(LocalTime.MAX);
    }

    /**
     * <p>
     * 返回 指定年份的 第一天时间
     * </p>
     *
     * @param year: 年份
     * @return:java.lang.String
     * @author:bood
     * @date:2020/9/25
     */
    public static String getFirstDayOfThisDate(int year) {
        LocalDateTime firstDayOfThisYear = firstDayOfThisYear(year);
        return DATETIME_FORMATTER.format(firstDayOfThisYear);
    }

    /**
     * <p>
     * 返回 指定年份的 最末天时间
     * </p>
     *
     * @param year: 年份
     * @return:java.lang.String
     * @author:bood
     * @date:2020/9/25
     */
    public static String getLastDayOfThisDate(int year) {
        LocalDateTime lastDayOfThisYear = lastDayOfThisYear(year);
        return DATETIME_FORMATTER.format(lastDayOfThisYear);
    }

    /**
     * <p>
     * 获取本月的第一天(当前时间)
     * </p>
     *
     * @return:java.lang.String
     * @author:bood
     * @date:2020/9/25
     */
    public static String getFirstDayOfThisMonth() {
        LocalDateTime firstDayOfThisYear = get().with(TemporalAdjusters.firstDayOfMonth());
        return DATETIME_FORMATTER.format(firstDayOfThisYear);
    }

    /**
     * <p>
     * 获取本月的最末天(当前时间)
     * </p>
     *
     * @return:java.lang.String
     * @author:bood
     * @date:2020/9/25
     */
    public static String getLastDayOfThisMonth() {
        LocalDateTime firstDayOfThisYear = get().with(TemporalAdjusters.lastDayOfMonth());
        return DATETIME_FORMATTER.format(firstDayOfThisYear);
    }

    /**
     * <p>
     * 当天开始时间
     * </p>
     *
     * @return:java.time.LocalDateTime
     * @author:bood
     * @date:2020/9/25
     */
    public static LocalDateTime todayStart() {
        return LocalDateTime.of(getCurrentLocalDate(), LocalTime.MIN);
    }

    /**
     * <p>
     * 当天结束时间
     * </p>
     *
     * @return:java.time.LocalDateTime
     * @author:bood
     * @date:2020/9/25
     */
    public static LocalDateTime todayEnd() {
        return LocalDateTime.of(getCurrentLocalDate(), LocalTime.MAX);
    }

    /**
     * <p>
     * 获取 指定年月的 第一个周一
     * </p>
     *
     * @param year:  年份
     * @param month: 月份
     * @return:java.time.LocalDateTime
     * @author:bood
     * @date:2020/9/25
     */
    public static LocalDateTime firstDayOfWeekInYearMonth(int year, int month) {
        return get().withYear(year).withMonth(month).with(TemporalAdjusters.firstInMonth(DayOfWeek.MONDAY));
    }

    /**
     * <p>
     * 获取 本周 第一天
     * </p>
     *
     * @return:java.lang.String
     * @author:bood
     * @date:2020/9/25
     */
    public static String getStartDayOfWeekToString() {
        return formatLocalDate(getStartDayOfWeek());
    }

    /**
     * <p>
     * 获取 本周 第一天
     * </p>
     *
     * @return:java.time.LocalDate
     * @author:bood
     * @date:2020/9/25
     */
    public static LocalDate getStartDayOfWeek() {
        TemporalAdjuster first_of_week = TemporalAdjusters.ofDateAdjuster(localDate -> localDate.minusDays(localDate
                .getDayOfWeek().getValue() - DayOfWeek.MONDAY.getValue()));
        return getCurrentLocalDate().with(first_of_week);
    }

    /**
     * <p>
     * 获取 本周 第末天
     * </p>
     *
     * @return:java.lang.String
     * @author:bood
     * @date:2020/9/25
     */
    public static String getEndDayOfWeekToString() {
        return formatLocalDate(getEndDayOfWeek());
    }

    /**
     * <p>
     * 获取 本周 第末天
     * </p>
     *
     * @return:java.time.LocalDate
     * @author:bood
     * @date:2020/9/25
     */
    public static LocalDate getEndDayOfWeek() {
        TemporalAdjuster last_of_week = TemporalAdjusters.ofDateAdjuster(localDate -> localDate.plusDays(
                DayOfWeek.SUNDAY.getValue() - localDate.getDayOfWeek().getValue()));
        return getCurrentLocalDate().with(last_of_week);
    }

    /**
     * <p>
     * LocalDateTime 转 Date
     * </p>
     *
     * @param localDateTime: LocalDate 类型
     * @return:java.util.Date
     * @author:bood
     * @date:2020/9/25
     */
    public static Date asDate(LocalDateTime localDateTime) {
        return Date.from(localDateTime.atZone(ZoneId.systemDefault()).toInstant());
    }

    /**
     * <p>
     * Date 转 LocalDateTime
     * </p>
     *
     * @param date: Date 类型
     * @return:java.time.LocalDateTime
     * @author:bood
     * @date:2020/9/25
     */
    public static LocalDateTime asLocalDateTime(Date date) {
        return Instant.ofEpochMilli(date.getTime()).atZone(ZoneId.systemDefault()).toLocalDateTime();
    }

    /**
     * <p>
     * LocalDate 转 Date
     * </p>
     *
     * @param localDate: LocalDate 类型
     * @return:java.util.Date
     * @author:bood
     * @date:2020/9/25
     */
    public static Date asDate(LocalDate localDate) {
        return Date.from(localDate.atStartOfDay().atZone(ZoneId.systemDefault()).toInstant());
    }

    /**
     * <p>
     * Date 转 LocalDate
     * </p>
     *
     * @param date: Date 类型
     * @return:java.time.LocalDate
     * @author:bood
     * @date:2020/9/25
     */
    public static LocalDate asLocalDate(Date date) {
        return Instant.ofEpochMilli(date.getTime()).atZone(ZoneId.systemDefault()).toLocalDate();
    }

}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值