Java8——时间类

一套新的时间API,放在java.time包下面

比之前的更加规范,并且解决了线程安全问题(最大区别)

线程安全问题

public class SimpleDateFormatTest {
    public static void main(String[] args) throws Exception {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd");

        Callable<Date> task = new Callable<Date>() {
            @Override
            public Date call() throws Exception {
                return sdf.parse("20190105");
            }
        };
        
        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) {
            System.out.println(future.get());
        }
    }
}

旧版本解决方案

public class DateFormatThreadLocal {

    private static final ThreadLocal<DateFormat> df = new ThreadLocal<DateFormat>(){
        @Override
        protected DateFormat initialValue() {
            return new SimpleDateFormat("yyyyMMdd");
        }
    };

    public static Date convert(String source) throws ParseException {
        return df.get().parse(source);
    }

}
public class SimpleDateFormatTest {
    public static void main(String[] args) throws Exception {

        Callable<Date> task = new Callable<Date>() {
            @Override
            public Date call() throws Exception {
                return DateFormatThreadLocal.convert("20190105");
            }
        };
        
        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) {
            System.out.println(future.get());
        }

        pool.shutdown();
    }
}

Java8 解决方案

使用LocalDate日期处理类

public class SimpleDateFormatTest {
    public static void main(String[] args) throws Exception {
        // Java8:DateTimeFormatter
        DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyyMMdd");
        // Java8:LocaleData
        Callable<LocalDate> task = new Callable<LocalDate>() {
            @Override
            public LocalDate call() throws Exception {
                return LocalDate.parse("20190105", 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) {
            System.out.println(future.get());
        }

        pool.shutdown();
    }
}

人读的时间

LocalDate、LocalTime、LocalDateTime的实例是不可变的的对象,分别表示ISO-8601日历系统(国际化标准组织制定的现代公民的日期和时间的表示法)的日期、时间、日期和时间,它们提供了简单的日期或时间,并不包含当前的时间和信息,和时区相关的信息。

这三者使用方法一样,LocalDateTime涵盖前两个

static void test1(){
        // 使用LocalDateTime获取点前时间
        LocalDateTime ldt = LocalDateTime.now();
        // 输出当前时间
        System.out.println(ldt);

        // 指定时间
        LocalDateTime ldt2 = LocalDateTime.of(2019, 01, 05, 16, 07, 33);
        System.out.println(ldt2);

        // 日期运算,改变都会产生新实例
        // 加两年
        LocalDateTime ldt3 = ldt.plusYears(2);
        System.out.println(ldt3);
        // 减两年
        LocalDateTime ldt4 = ldt.minusMonths(2);
        System.out.println(ldt4);

        // get方法,获取年月日等……
        System.out.println(ldt.getYear());
        System.out.println(ldt.getMonthValue());
        System.out.println(ldt.getMonth().getValue());
    }

机器读的时间

Instant时间戳:以UNIX元年:1970年1月1日00时00分00秒到某个时间之间的毫秒值

默认获取的时间是UTC时区的时间

static void test2(){
        //Instant时间戳:以UNIX元年:1970年1月1日00时00分00秒到某个时间之间的毫秒值
        Instant ins1 = Instant.now();   // 默认获取的是UTC时区
        System.out.println(ins1);

        // 偏移运算
        // ZoneOffset.ofHours(8)   UTC-8相差8个时区
        OffsetDateTime odt = ins1.atOffset(ZoneOffset.ofHours(8));
        System.out.println(odt);

        // 转成毫秒时间
        System.out.println(ins1.toEpochMilli());

        // 偏移60秒
        Instant ins2 = Instant.ofEpochSecond(60);
        System.out.println(ins2);
    }

计算间隔

Duration:计算两个“时间”之间的间隔

static void test3(){
        // Duration:计算两个“时间”之间的间隔
        Instant ins1 = Instant.now();
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        Instant ins2 = Instant.now();
        Duration dration = Duration.between(ins1, ins2);
        // 毫秒输出
        System.out.println(dration.toMillis());

        System.out.println("--------------------");

        LocalTime lt1 = LocalTime.now();
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        LocalTime lt2 = LocalTime.now();
        Duration dration2 = Duration.between(lt1, lt2);
        System.out.println(dration2.toMillis());
    }

Period:计算两个“日期之间的间隔”

static void test4(){
    // Period: 计算两个“日期”之间的间隔
    LocalDate ld1 = LocalDate.of(2015, 1, 1);
    LocalDate ld2 = LocalDate.now();
    Period period = Period.between(ld1, ld2);
    System.out.println(period);
    // 相差几年
    System.out.println(period.getYears());
}

日期操纵

TemporalAdjuster:时间校正器。将时间调整到“下个周日”的操作,支持lambda语法

TemporalAdjusters:为TemporalAdjuster接口产生实例,该类通过静态方法提供了大量的常用TemporalAdjuster实现
static void test5(){
    //TemporalAdjuster:时间校正器
    LocalDateTime ldt = LocalDateTime.now();
    System.out.println(ldt);

    // 当前月中的天指定成10日
    LocalDateTime ldt2 = ldt.withDayOfMonth(10);
    System.out.println(ldt2);

    //下一个周日是什么时间
    LocalDateTime ldt3 = ldt.with(TemporalAdjusters.next(DayOfWeek.SUNDAY));
    System.out.println(ldt3);

    //自定义下一个工作日是什么时候
    LocalDateTime ldt5 = 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 ldt.plusDays(1);
        }
    });
    System.out.println("下个工作日");
    System.out.println(ldt5);
}

格式化时间/日期

DateTimeFormatter:格式化时间/日期

static void test6(){
    // DateTimeFormatter 格式化时间/日期
    DateTimeFormatter dtf = DateTimeFormatter.ISO_DATE;
    LocalDateTime ldt = LocalDateTime.now();

    String strDate = ldt.format(dtf);
    System.out.println(strDate);

    System.out.println("------------------------");
    DateTimeFormatter dtf2 = DateTimeFormatter.ofPattern("yyyy年MM月dd日 HH:mm:ss");
    String strDate2 = dtf2.format(ldt);
    System.out.println(strDate2);

    System.out.println("------------------------");
    // 将字符串解析成时间日期
    LocalDateTime newDate = LocalDateTime.parse(strDate2, dtf2);
    System.out.println(newDate);
}

时区的处理

ZondDate、ZondTime、ZondDateTime其中每个时区都对应着ID,地区ID都为“{区域}/{城市}”的格式,例如:Asia/Shanghai等

ZondId:该类包含了所有的时区信息

getAvailableZondIds():可以获取所有时区信息

of(id):用指定的时区信息获取ZoneId对象

static void test7(){
    // 获取所有时区信息
    Set<String> set = ZoneId.getAvailableZoneIds();
    set.forEach(System.out::println);
}
static void test8(){
    //ZondDate、ZondTime、ZondDateTime
    // 获取指定时区时间
    LocalDateTime ldt = LocalDateTime.now(ZoneId.of("Europe/Podgorica"));
    System.out.println(ldt);

    //带时区的日期时间格式
    LocalDateTime ldt2 = LocalDateTime.now(ZoneId.of("Asia/Shanghai"));
    ZonedDateTime zdt = ldt2.atZone(ZoneId.of("Asia/Shanghai"));
    System.out.println(zdt);
}

 

posted @ 2019-01-09 17:03  时光丶巷陌  阅读(281)  评论(0编辑  收藏  举报