【小家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方法,非常的方便快捷有木有

相关文章
|
1月前
|
前端开发 Java 微服务
《深入理解Spring》:Spring、Spring MVC与Spring Boot的深度解析
Spring Framework是Java生态的基石,提供IoC、AOP等核心功能;Spring MVC基于其构建,实现Web层MVC架构;Spring Boot则通过自动配置和内嵌服务器,极大简化了开发与部署。三者层层演进,Spring Boot并非替代,而是对前者的高效封装与增强,适用于微服务与快速开发,而深入理解Spring Framework有助于更好驾驭整体技术栈。
|
1月前
|
存储 Java 程序员
【Java】(6)全方面带你了解Java里的日期与时间内容,介绍 Calendar、GregorianCalendar、Date类
java.util 包提供了 Date 类来封装当前的日期和时间。Date 类提供两个构造函数来实例化 Date 对象。第一个构造函数使用当前日期和时间来初始化对象。Date( )第二个构造函数接收一个参数,该参数是从1970年1月1日起的毫秒数。
140 1
|
3月前
|
前端开发 Java 开发者
Java新手指南:在Spring MVC中使用查询字符串与参数
通过结合实际的需求和业务逻辑,开发者可以灵活地利用这些机制,为用户提供更丰富而高效的Web应用体验。
150 15
|
8月前
|
前端开发 Java 测试技术
微服务——SpringBoot使用归纳——Spring Boot中的MVC支持——@RequestParam
本文介绍了 `@RequestParam` 注解的使用方法及其与 `@PathVariable` 的区别。`@RequestParam` 用于从请求中获取参数值(如 GET 请求的 URL 参数或 POST 请求的表单数据),而 `@PathVariable` 用于从 URL 模板中提取参数。文章通过示例代码详细说明了 `@RequestParam` 的常用属性,如 `required` 和 `defaultValue`,并展示了如何用实体类封装大量表单参数以简化处理流程。最后,结合 Postman 测试工具验证了接口的功能。
475 0
微服务——SpringBoot使用归纳——Spring Boot中的MVC支持——@RequestParam
|
4月前
|
JSON 前端开发 Java
Java新手指南:如何在Spring MVC中处理请求参数
处理Spring MVC中的请求参数是通过控制器方法中的注解来完成的。这些注解包括 `@RequestParam`, `@PathVariable`, `@ModelAttribute`, `@RequestBody`, `@RequestHeader`, `@Valid`, 和 `@RequestMapping`。使用这些注解可以轻松从HTTP请求中提取所需信息,例如URL参数、表单数据或者JSON请求体,并将其转换成Java对象以供进一步处理。
469 17
|
3月前
|
安全 Java API
Java日期时间API:从Date到Java.time
本文深入解析了Java 8中引入的全新日期时间API,涵盖LocalDate、LocalTime、LocalDateTime、ZonedDateTime等核心类的使用,以及时间调整、格式化、时区处理和与旧API的互操作。通过实例对比,展示了新API在可变性、线程安全与易用性方面的显著优势,并提供迁移方案与实战技巧,助你掌握现代Java时间处理的最佳实践。
|
8月前
|
JSON 前端开发 Java
微服务——SpringBoot使用归纳——Spring Boot中的MVC支持——@RequestBody
`@RequestBody` 是 Spring 框架中的注解,用于将 HTTP 请求体中的 JSON 数据自动映射为 Java 对象。例如,前端通过 POST 请求发送包含 `username` 和 `password` 的 JSON 数据,后端可通过带有 `@RequestBody` 注解的方法参数接收并处理。此注解适用于传递复杂对象的场景,简化了数据解析过程。与表单提交不同,它主要用于接收 JSON 格式的实体数据。
725 0
|
8月前
|
前端开发 Java 微服务
微服务——SpringBoot使用归纳——Spring Boot中的MVC支持——@PathVariable
`@PathVariable` 是 Spring Boot 中用于从 URL 中提取参数的注解,支持 RESTful 风格接口开发。例如,通过 `@GetMapping(&quot;/user/{id}&quot;)` 可以将 URL 中的 `{id}` 参数自动映射到方法参数中。若参数名不一致,可通过 `@PathVariable(&quot;自定义名&quot;)` 指定绑定关系。此外,还支持多参数占位符,如 `/user/{id}/{name}`,分别映射到方法中的多个参数。运行项目后,访问指定 URL 即可验证参数是否正确接收。
472 0
|
8月前
|
JSON 前端开发 Java
微服务——SpringBoot使用归纳——Spring Boot中的MVC支持——@RequestMapping
@RequestMapping 是 Spring MVC 中用于请求地址映射的注解,可作用于类或方法上。类级别定义控制器父路径,方法级别进一步指定处理逻辑。常用属性包括 value(请求地址)、method(请求类型,如 GET/POST 等,默认 GET)和 produces(返回内容类型)。例如:`@RequestMapping(value = &quot;/test&quot;, produces = &quot;application/json; charset=UTF-8&quot;)`。此外,针对不同请求方式还有简化注解,如 @GetMapping、@PostMapping 等。
417 0
|
8月前
|
JSON 前端开发 Java
微服务——SpringBoot使用归纳——Spring Boot中的MVC支持——@RestController
本文主要介绍 Spring Boot 中 MVC 开发常用的几个注解及其使用方式,包括 `@RestController`、`@RequestMapping`、`@PathVariable`、`@RequestParam` 和 `@RequestBody`。其中重点讲解了 `@RestController` 注解的构成与特点:它是 `@Controller` 和 `@ResponseBody` 的结合体,适用于返回 JSON 数据的场景。文章还指出,在需要模板渲染(如 Thymeleaf)而非前后端分离的情况下,应使用 `@Controller` 而非 `@RestController`
338 0