资讯专栏INFORMATION COLUMN

Java 8 新特性之新的时间日期 API

JaysonWang / 645人阅读

摘要:概述简介引入了一套全新的时间日期,操作起来更简便。可以使用的锁解决的线程安全问题测试方法使用进行格式化,是线程安全的时区设置带时区的时间本文首发于凌风博客新特性之新的时间日期作者凌风

1. 概述 1.1 简介

Java 8 引入了一套全新的时间日期API,操作起来更简便。简单介绍下,LocalDateLocalTimeLocalDateTime的使用;

java.util.Date月份从0开始,java.time.LocalDate月份从1开始并且提供了枚举。

java.util.DateSimpleDateFormatter都不是线程安全的,而LocalDateLocalTime和最基本的String一样,是不变类型,不但线程安全,而且不能修改,它们分别使用 ISO-8601 日历系统的日期和时间,它们提供了简单的日期或时间,并不包含当前的时间信息,也不包含与时区相关的信息。

注 : ISO-8601 日历系统是国际标准化组织制定的现代公民的日期和时间的表示法
1.3 环境 2. LocalDate、LocalTime、LocalDateTime

LocalDateLocalTimeLocalDateTime 三者的使用方式基本一致,所以我们这里就以 LocalDateTime 为例进行索命

2.1 实例
@Test
public void t1() {
    // 获取当前时间
    LocalDateTime ldt1 = LocalDateTime.now();
    System.out.println(ldt1);

    // 获取指定的时间
    LocalDateTime ldt2 = LocalDateTime.of(2018, 12, 10, 10, 10, 10);
    System.out.println(ldt2);

    // 加两年
    LocalDateTime ldt3 = ldt1.plusYears(2);
    System.out.println(ldt3);

    // 减两个月
    LocalDateTime ldt4 = ldt1.minusYears(2);
    System.out.println(ldt4);

    // 获取年月日时分秒
    System.out.println(ldt1.getYear());
    System.out.println(ldt1.getMonthValue());
    System.out.println(ldt1.getDayOfMonth());
    System.out.println(ldt1.getHour());
    System.out.println(ldt1.getMinute());
    System.out.println(ldt1.getSecond());
}
2.2 Instant : 时间戳

使用 Unix 元年 1970年1月1日 00:00:00 所经历的毫秒值

@Test
public void t2() {
    Instant ins = Instant.now();  //默认使用 UTC 时区
    System.out.println(ins);

    // 时间偏移量
    OffsetDateTime odt = ins.atOffset(ZoneOffset.ofHours(8));
    System.out.println(odt);

    // 获取毫秒值
    System.out.println(ins.getNano());
    
    // 对于元年开始进行运算
    Instant ins2 = Instant.ofEpochSecond(60);
    System.out.println(ins2);
}
2.3 Duration : 用于计算两个“时间”间隔
@Test
public void t3() throws InterruptedException {
    // 时间戳
    Instant ins1 = Instant.now();

    Thread.sleep(1000);

    Instant ins2 = Instant.now();
    Duration duration = Duration.between(ins1, ins2);
    System.out.println("所耗费时间为:" + duration.toMillis());

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

    // LocalTime
    LocalTime lt1 = LocalTime.now();

    Thread.sleep(1000);

    LocalTime lt2 = LocalTime.now();

    System.out.println("所耗费时间为:" + Duration.between(lt1, lt2).toMillis());
}
2.4 Period : 用于计算两个“日期”间隔
@Test
public void t5() {
    LocalDate ld1 = LocalDate.of(2017, 1, 1);
    LocalDate ld2 = LocalDate.now();
    Period period = Period.between(ld1, ld2);
    System.out.println("相差" + period.getYears() + "年" + period.getMonths() + "月" + period.getDays() + "天");
}
2.5 日期的操作

TemporalAdjuster 时间校正器,有时我们可能需要获取例如:将日期调整到下个周日等操作。

TemporalAdjusters 该类通过静态方法提供了大量的常用 TemporalAdjuster 的实现。

@Test
public void t6() {
    LocalDateTime ldt = LocalDateTime.now();

    // 指定这个月的一个固定日期
    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 ldt6 = (LocalDateTime) l;
        DayOfWeek dayOfWeek = ldt6.getDayOfWeek();

        if (dayOfWeek.equals(DayOfWeek.FRIDAY)) {
            return ldt6.plusDays(3);
        } else if (dayOfWeek.equals(DayOfWeek.SATURDAY)) {
            return ldt6.plusDays(2);
        } else {
            return ldt6.plusDays(1);
        }
    });
    System.out.println("获取下个工作日 : " + ldt5);
}
3. DateTimeFormatter 3.1 简介

在 JDK 1.8 中可以使用 DateTimeFormatter 来代替 SimpleDateFormat 进行日期的格式化,而且 DateTimeFormatter 是线程安全的

3.2 实例
@Test
public void t8() {
    DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
    LocalDateTime ldt = LocalDateTime.now();

    // 将日期格式化为字符串,两种方式否可以
    String dtfDate = dtf.format(ldt);
    String ldtDate = ldt.format(dtf);
    System.out.println("dtfDate : " + dtfDate);
    System.out.println("ldtDate : " + ldtDate);

    // 将字符串格式化为 LocalDateTime
    LocalDateTime ldt2 = LocalDateTime.parse(dtfDate, dtf);
    System.out.println("时间为 : " + ldt2);
}
3.3 线程安全

在多线程使用 SimpleDateFormat 进行格式化日期的时候会有线程安全问题。

@Test
public void t1() throws Exception {
    SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");

    Callable task = new Callable() {
        @Override
        public Date call() throws Exception {
            return sdf.parse("2018-12-10");
        }
    };

    ExecutorService executor = Executors.newFixedThreadPool(10);
    List> results = new ArrayList<>();
    for (int i = 0; i < 10; i++) {
        results.add(executor.submit(task));
    }

    for (Future future : results) {
        System.out.println(future.get());
    }
    executor.shutdown();
}

可以使用 ThreadLocal 的锁解决 SimpleDateFormat 的线程安全问题

import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;

public class DateFormatThreadLocal {
    private static final ThreadLocal df = new ThreadLocal() {
        protected DateFormat initialValue() {
            return new SimpleDateFormat("yyyy-MM-dd");
        }
    };

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

测试方法

@Test
public void t2() throws Exception {
    Callable task = new Callable() {
        @Override
        public Date call() throws Exception {
            return DateFormatThreadLocal.convert("2018-12-10");
        }
    };

    ExecutorService executor = Executors.newFixedThreadPool(10);
    List> results = new ArrayList<>();
    for (int i = 0; i < 10; i++) {
        results.add(executor.submit(task));
    }

    for (Future future : results) {
        System.out.println(future.get());
    }
    executor.shutdown();
}

使用 DateTimeFormatter 进行格式化,DateTimeFormatter 是线程安全的

@Test
public void t3() throws Exception {
    DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyy-MM-dd");

    Callable task = new Callable() {
        @Override
        public LocalDate call() throws Exception {
            return LocalDate.parse("2018-12-10",dtf);
        }
    };

    ExecutorService executor = Executors.newFixedThreadPool(10);
    List> results = new ArrayList<>();
    for (int i = 0; i < 10; i++) {
        results.add(executor.submit(task));
    }

    for (Future future : results) {
        System.out.println(future.get());
    }
    executor.shutdown();
}
4. 时区设置
@Test
public void t2() {
    LocalDateTime ldt = LocalDateTime.now(ZoneId.of("Asia/Shanghai"));
    System.out.println(ldt);

    // 带时区的时间
    ZonedDateTime zdt = ldt.atZone(ZoneId.of("Asia/Shanghai"));
    System.out.println(zdt);
}
本文首发于凌风博客:Java 8 新特性之新的时间日期 API
作者:凌风

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/72779.html

相关文章

  • 乐字节-Java8特性之Date API

    摘要:上一篇文章,小乐给大家带来了新特性之,接下来本文将会给大家介绍新特性之前言通过发布新的来进一步加强对日期与时间的处理。 上一篇文章,小乐给大家带来了Java8新特性之Optional,接下来本文将会给大家介绍Java8新特性之Date API 前言: Java 8通过发布新的Date-Time API来进一步加强对日期与时间的处理。 旧版的 Java 中,日期时间 API 存在诸多问题...

    suemi 评论0 收藏0
  • PHP 5.3向更高版本迁移之特性

    摘要:新特性掌握的引入,可以扩展的内容,使在某种形式上实现了多重继承,更加灵活不能被实例化示例代码需要注意的是,的继承顺序来自当前类的成员覆盖了的方法,而则覆盖了被继承的方法当多个被同一个类使用的时候,会出现方法冲突的情况,使用关键词解决示 PHP 5.4新特性 掌握 traits trait的引入,可以扩展class的内容,使class在某种形式上实现了多重继承,更加灵活 t...

    macg0406 评论0 收藏0
  • Java8实战》-第十二章笔记(日期时间API

    摘要:合并日期和时间这个复合类名叫,是和的合体。截至目前,我们介绍的这些日期时间对象都是不可修改的,这是为了更好地支持函数式编程,确保线程安全,保持领域模式一致性而做出的重大设计决定。 新的日期和时间API Java的API提供了很多有用的组件,能帮助你构建复杂的应用。不过,Java API也不总是完美的。我们相信大多数有经验的程序员都会赞同Java 8之前的库对日期和时间的支持就非常不理想...

    khlbat 评论0 收藏0
  • Java8特性日期处理

    摘要:处理日期日历和时间的不足之处将设定为可变类型,以及的非线程安全使其应用非常受限。最完整的日期时间,包含时区和相对或格林威治的时差。获取当前的日期中的用于表示当天日期。 简介 伴随 lambda表达式、streams 以及一系列小优化,Java 8 推出了全新的日期时间API。 Java处理日期、日历和时间的不足之处:将 java.util.Date 设定为可变类型,以及 SimpleD...

    Airy 评论0 收藏0
  • 聊聊 Java8 以后各个版本的特性

    摘要:于是抽时间看了看以后各个版本的特性,做了一个总结。年和公开版本发布,取名为。此后对应版本就是,。发布,是一个重大版本更新。在此之后,就是每六个月发布一次新版本。以上和参考资料聊了一些关于的历史,下面我们看看各个版本有那些新特性。 【这是 ZY 第 11 篇原创技术文章】 某天在网上闲逛,突然看到有篇介绍 Java 11 新特性的文章,顿时心里一惊,毕竟我对于 Java 的版本认识...

    K_B_Z 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<