【小家java】java8新特性之---全新的日期、时间API(JSR 310规范),附SpringMVC、Mybatis中使用JSR310的正确姿势(中)

简介: 【小家java】java8新特性之---全新的日期、时间API(JSR 310规范),附SpringMVC、Mybatis中使用JSR310的正确姿势(中)

新的API 格式化(字符串 -><- 字符串 互转)


  public static void main(String[] args) {
        //字符串转化为日期对象
        String dateStr= "2016年10月25日";
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy年MM月dd日");
        LocalDate date= LocalDate.parse(dateStr, formatter);
        //日期转换为字符串
        LocalDateTime now = LocalDateTime.now();
        DateTimeFormatter format = DateTimeFormatter.ofPattern("yyyy年MM月dd日 hh:mm a");
        String nowStr = now .format(format);
        System.out.println(nowStr); //2018年08月07日 12:15 上午
    }


  • DateTimeFormatter预定义了一些格式,可以直接调用format方法,方便调用者使用


//2017-01-01
DateTimeFormatter.ISO_LOCAL_DATE.format(LocalDate.of(2017, 1, 1))
//20170101
DateTimeFormatter.BASIC_ISO_DATE.format(LocalDate.of(2017, 1, 1));
//2017-01-01T09:10:00
DateTimeFormatter.ISO_LOCAL_DATE_TIME.format(LocalDateTime.of(2017, 1, 1, 9, 10, 0)); 

根据当前操作系统语言环境,有SHORET MEDIUM LONG FULL 四种不同的风格来格式化。


可以通过DateTimeFormatter的静态方法ofLocalizedDate ofLocalizedTime ofLocalizedDateTime


  • 使用自定义模式格式化


//2017-02-27 22:48:52
DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss").format(LocalDateTime.now())

当然也可以这么搞


//使用的ISO_LOCAL_DATE格式解析  2017-01-01
LocalDate.parse("2017-01-01");
//使用自定义格式解析  2017-01-01T08:08:08
LocalDateTime.parse("2017-01-01 08:08:08", DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));


在DateTimeFormatter中还有很多定义好的格式,有兴趣的可以自己去看一下

SimpleDateFormat是线程不安全的,所以在高并发环境下,建议这么搞


 private static ThreadLocal<DateFormat> threadLocal = new ThreadLocal<DateFormat>() {
        @Override
        protected DateFormat initialValue() {
            return new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        }
    };
    //和线程绑定 保证安全
    public static String format(Date date) {
        return threadLocal.get().format(date);


    注意:ofPattern(String pattern)和ofPattern(String pattern, Locale locale)还是有区别的。但绝大多数情况下,我们用ofPattern就够了,因为Locale对象根据用户的国家,地区文化差异格式化,不会改变系统时间,只是表达方式变而已,就是数值表示方法不同而已,也是一样的值,这个方法不常用,因为不能覆盖所有语言环境。并且和格式化模版有关,比如我们的最常用yyyy-MM-dd HH:mm:ss会没有效果。但是这种模版“GGGG yyyy/MMMM/dd HH:mm:ss EEE”,Local不同,展示方式是有很大不同的


Date类型和时间戳 转换成新的时间类型


Date在1.8之后提供了几个方法,可以很方便的转换成新的API


     //时间戳转instant就很简单了
        Instant instant = Instant.ofEpochMilli(System.currentTimeMillis());
        System.out.println(instant); //2018-08-06T16:26:08.539Z(其实已经24点了,所以直接输出是有时区问题的 需要注意)
        //Date直接转Instant
        System.out.println(new Date().toInstant()); //2018-08-06T16:26:08.539Z
        //Instant --> Date
        Date.from(Instant.now());
        //Calendar --> Instant(这个用得很少)
        Calendar.getInstance().toInstant();


理论知识就介绍到这了,接下来看一些有意思的案例实现,可以更好的了解应用场景


根据已经了解的策略模式,我们可以很好的猜到,LocalDate、LocalTime、LocalDateTime他们之前的互相转换,也是可以走from方法的,如下:


LocalDateTime localDateTime = LocalDateTime.now();
        LocalDate localDate = LocalDate.from(localDateTime);
        LocalTime localTime = LocalTime.from(localDateTime);
        System.out.println(localDate); //2018-08-13
        System.out.println(localTime); //16:04:48.356
        ///下面的会报错哟///
        //LocalTime localTime = LocalTime.now();
        //LocalDate localDate = LocalDate.from(localTime); //这样转是会报错的  因为LocalTime不含有Date元素 Unable to obtain LocalDate from TemporalAccessor: 16:01:47.541 of type java.time.LocalTime
        //LocalDateTime localDateTime = LocalDateTime.from(localTime); //这样转也是会报错的 因为不含有date元素
        //System.out.println(localTime);
        //System.out.println(localDateTime);


重要:常用:LocalDate和Date类、时间戳之间转换的坑


Date对象表示特定的日期和时间,而LocalDate(Java8)对象只包含没有任何时间信息的日期。 因此,如果我们只关心日期而不是时间信息,则可以在Date和LocalDate之间进行转换


在JDK8以前,我们经常遇到用Date类型来装载时间。有时候只表示日期,有时候是日期+时间,但是我们的选择都只能是Date类型。因此Date类型到LocalDate、LocalTime、Instant等类型的转换 显得尤为重要了。


这里面需要注意一个坑:他们转换的中间桥梁都是时间戳Instant对象,但是转换的时候如果没有考虑时区,就会报错的。


比如下面这个例子,看起来顺滑,其实异常了:


Date date = new Date();
        Instant instant = date.toInstant();
        //看起来非常顺滑 但其实 异常:Unable to obtain LocalDate from TemporalAccessor: 2018-08-31T02:41:28.076Z of type java.time.Instant
        LocalDate from = LocalDate.from(date.toInstant());


其实这个也好理解。人家Date是带有日期和时间的,然后突然来一个只需要日期的,LocalDate不知道咋处理(或者说JDK8没考虑到这一点,其实不是,因为时区没定,LocalDate自己不好自己做定论),所以不允许直接转换也可以理解。所以各位使用起一定要小心使用了


糗事Date和LocalDate、LocalTime等互相转化的的思想也很简单 借助LocalDateTime对象就万无一失了。


    Date date = new Date();
        Instant instant = date.toInstant();
        //以ZoneId.systemDefault转换成LocalDateTime后,就可以随意转换了
        LocalDateTime localDateTime = LocalDateTime.ofInstant(instant, ZoneId.systemDefault());
        //方式一:使用LocalDate、LocalTime的from
        LocalDate fromLocalDate = LocalDate.from(localDateTime);
        LocalTime fromLocalTime = LocalTime.from(localDateTime);
        System.out.println(fromLocalDate); //2018-08-31
        System.out.println(fromLocalTime); //11:03:19.716
        //方式二:直接to的方式
        LocalDate toLocalDate = localDateTime.toLocalDate();
        LocalTime toLocalTime = localDateTime.toLocalTime();
        System.out.println(toLocalDate); //2018-08-31
        System.out.println(toLocalTime); //11:03:19.716


反向转换:借助的中间变量是Instant即可


 public static void main(String[] args) {
        LocalDateTime localDateTime = LocalDateTime.now();
        LocalDate localDate = LocalDate.now();
        LocalTime localTime = LocalTime.now();
        Instant instant = null;
        ZoneId zone = ZoneId.systemDefault();
        //LocalDateTime转Instant转Date
        instant = localDateTime.atZone(zone).toInstant();
        System.out.println(Date.from(instant));
        //LocalDate转Instant转Date
        instant = localDate.atStartOfDay().atZone(zone).toInstant();
        System.out.println(Date.from(instant));
        //LocalTime转Instant转Date(很麻烦 一般杜绝这样使用吧)
        //必须先借助localDate转换成localDateTime 在转成instant 再转date
        LocalDateTime localDateTimeDate = LocalDateTime.of(localDate, localTime);
        instant = localDateTime.atZone(zone).toInstant();
        System.out.println(Date.from(instant));
    }



时间矫正器(TemporalAdjuster )


Java8推出了时间矫正器的概念。可以辅助我们更精准的定位到一些日期,比如写个周日,下个结婚纪念日等等。


    TemporalAdjuster : 时间校正器。有时我们可能需要获取例如:将日期调整到“下个周日”等操作。不过它是个接口,并且是函数式接口


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

时间矫正,用的都是with语法。可以理解成和set差不多

image.png



public static void main(String[] args) {
        LocalDateTime ldt1 = LocalDateTime.now();
        //本月第一天
        LocalDateTime ldt2 = ldt1.with(TemporalAdjusters.firstDayOfMonth());
        System.out.println(ldt2); //2018-08-01T17:34:42.039
        //本月的第一个周五
        LocalDateTime ldt3 = ldt1.with(TemporalAdjusters.firstInMonth(DayOfWeek.FRIDAY));
        System.out.println(ldt3); //2018-08-03T17:41:07.619
    }


接下来一个场景会比较有意思点:下一个信用卡还款日是什么时候。



时间矫正器,在很多场景下,还是非常有用的。所以希望读者能够大概掌握


Java中处理日期、时间的经典案例场景


检查两个日期是否相等


LocalDate重写了equals方法来进行日期的比较,如下所示:


image.png


在java8中如何检查重复事件,比如生日


这是相对比较常用的一个场景:判断今天是否是某个人的生日。


image.png

通过列子可以看到MonthDay只存储了月日,对比两个日期的月日即可知道是否重复,而且使用了equals方法,非常的方便快捷有木有

相关文章
|
11天前
|
存储 Java 开发者
什么是java的Compact Strings特性,什么情况下使用
Java 9引入了紧凑字符串特性,优化了字符串的内存使用。它通过将字符串从UTF-16字符数组改为字节数组存储,根据内容选择更节省内存的编码方式,通常能节省10%至15%的内存。
|
20天前
|
存储 Java 数据挖掘
Java 8 新特性之 Stream API:函数式编程风格的数据处理范式
Java 8 引入的 Stream API 提供了一种新的数据处理方式,支持函数式编程风格,能够高效、简洁地处理集合数据,实现过滤、映射、聚合等操作。
35 6
|
1月前
|
安全 Java API
告别SimpleDateFormat:Java 8日期时间API的最佳实践
在Java开发中,处理日期和时间是一个基本而重要的任务。传统的`SimpleDateFormat`类因其简单易用而被广泛采用,但它存在一些潜在的问题,尤其是在多线程环境下。本文将探讨`SimpleDateFormat`的局限性,并介绍Java 8引入的新的日期时间API,以及如何使用这些新工具来避免潜在的风险。
34 5
|
1月前
|
分布式计算 Java API
Java 8引入了流处理和函数式编程两大新特性
Java 8引入了流处理和函数式编程两大新特性。流处理提供了一种声明式的数据处理方式,使代码更简洁易读;函数式编程通过Lambda表达式和函数式接口,简化了代码书写,提高了灵活性。此外,Java 8还引入了Optional类、新的日期时间API等,进一步增强了编程能力。这些新特性使开发者能够编写更高效、更清晰的代码。
33 4
|
1月前
|
JavaScript 前端开发 API
Vue 3新特性详解:Composition API的威力
【10月更文挑战第25天】Vue 3 引入的 Composition API 是一组用于组织和复用组件逻辑的新 API。相比 Options API,它提供了更灵活的结构,便于逻辑复用和代码组织,特别适合复杂组件。本文将探讨 Composition API 的优势,并通过示例代码展示其基本用法,帮助开发者更好地理解和应用这一强大工具。
36 2
|
7月前
|
设计模式 前端开发 Java
了解 Spring MVC 架构、Dispatcher Servlet 和 JSP 文件的关键作用
Spring MVC 是 Spring 框架的一部分,是一个 Web 应用程序框架。它旨在使用 Model-View-Controller(MVC) 设计模式轻松构建Web应用程序。
115 0
|
前端开发 Java 程序员
38SpringMVC - SpringMVC架构
38SpringMVC - SpringMVC架构
50 0
|
2月前
|
存储 设计模式 前端开发
什么是SpringMVC?简单好理解!什么是应用分层?SpringMVC与应用分层的关系? 什么是三层架构?SpringMVC与三层架构的关系?
文章解释了SpringMVC的概念和各部分功能,探讨了应用分层的原因和具体实施的三层架构,以及SpringMVC与三层架构之间的关系和联系。
25 1
什么是SpringMVC?简单好理解!什么是应用分层?SpringMVC与应用分层的关系? 什么是三层架构?SpringMVC与三层架构的关系?
|
6月前
|
安全 前端开发 Java
挑战5分钟内基于Springboot+SpringMVC+Mybatis-plus快速构建web后端三层架构
挑战5分钟内基于Springboot+SpringMVC+Mybatis-plus快速构建web后端三层架构
55 1
|
6月前
|
设计模式 前端开发 Java
【Spring MVC】快速学习使用Spring MVC的注解及三层架构
【Spring MVC】快速学习使用Spring MVC的注解及三层架构
95 1
下一篇
DataWorks