jdk8获取当前时间|时间加减|java8时间格式化|时间处理工具|时间比较|线程安全的时间处理方法

简介: jdk8获取当前时间|时间加减|java8时间格式化|时间处理工具|时间比较|线程安全的时间处理方法

前言

在很久之前,我总结了一些jdk7版本之前的关于时间处理的一些公共方法,日期转换成字符串、指定时间加上指定天数后的日期、获取上周周一时间 等等;具体的可以戳链接查看完整的:https://blog.csdn.net/qq_27471405/article/details/79523556


但是这些是非线程安全的,不建议采用,举个例子


在一个类中,有以下代码:

private static SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

public String getDate(Date date){

return sdf.format(date);

}


上面这串代码在并发的时候,是线程不安全的,具体的如何不安全,大家可以搜一下,这里不多讲了


那么今天给大家分享的是jdk8之后的一些时间处理的公共方法,是线程安全的,理应大家以后应该用下面这些方法


一、jdk8与jdk7以及之前的日期和时间处理类的不同:

1. Java的java.util.Date和java.util.Calendar类易用性差,不支持时区,并且是可变的,也就意味着他们都不是线程安全的;

2. 用于格式化日期的类DateFormat被放在java.text包中,它是一个抽象类,所以我们需要实例化一个SimpleDateFormat对象来处理日期格式化,并且DateFormat也是非线程安全,这意味着如果你在多线程程序中调用同一个DateFormat对象,会得到意想不到的结果。

3. 对日期的计算方式繁琐,而且容易出错,因为月份是从0开始的,这意味着从Calendar中获取的月份需要加一才能表示当前月份

由于以上这些问题,出现了一些三方的日期处理框架,例如Joda-Time,data4j等开源项目


二、Java 8日期/时间类

Java 8的日期和时间类包含LocalDate、LocalTime、Instant、Duration以及Period,这些类都包含在java.time包中。


Instant:瞬时实例。


LocalDate:本地日期,不包含具体时间 例如:2014-01-14 可以用来记录生日、纪念日、加盟日等。


LocalTime:本地时间,不包含日期。


LocalDateTime:组合了日期和时间,但不包含时差和时区信息。


ZonedDateTime:最完整的日期时间,包含时区和相对UTC或格林威治的时差。


新API还引入了 ZoneOffSet 和 ZoneId 类,使得解决时区问题更为简便。解析、格式化时间的 DateTimeFormatter 类也全部重新设计。


三:日期和时间主要类的关系(待更新)

1 、LocalDate的关系图:

2、 LocalTime:

3 、LocalDateTime:

4 、OffsetTime:

5 、OffsetDateTime:

6、 ZonedDateTime:

7 、Instant:

 

四:日期操作和处理

 

获取当前日期(只能精确到年月日)

/**
     * 获取当前日期(只能精确到年月日)
     * @param formatStr
     */
    public static void getNowDate(String formatStr){
        if (StringUtils.isBlank(formatStr)){
            formatStr = "yyyy-MM-dd";
        }
        LocalDate now = LocalDate.now();
        System.out.println("当前日期: " + now + " " + now.getDayOfWeek());
        DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern(formatStr);                        // * 原文章链接:https://blog.csdn.net/qq_27471405/article/details/106824023   * 其他均为盗版,公众号:灵儿的笔记(zygxsq)
        String nowFormat = now.format(dateTimeFormatter);
        System.out.println("格式化后的当前日期:"+nowFormat);
    }

如果传格式化到天小时秒的话,会报异常:Exception in thread "main" java.time.temporal.UnsupportedTemporalTypeException: Unsupported field: HourOfDay

获取当前时间(可以精确到毫秒)

 /**
     * 获取当前时间(可以精确到毫秒)
     * 原文章链接:https://blog.csdn.net/qq_27471405/article/details/106824023
     * 其他均为盗版,公众号:灵儿的笔记(zygxsq)
     * @param formatStr
     */
    public static void getNowTime(String formatStr){
        if (StringUtils.isBlank(formatStr)){
            formatStr = "yyyy-MM-dd";
        }
        LocalDateTime now = LocalDateTime.now();
        System.out.println("当前日期: " + now + " " + now.getDayOfWeek());
        DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern(formatStr);                      // * 原文章链接:https://blog.csdn.net/qq_27471405/article/details/106824023    * 其他均为盗版,公众号:灵儿的笔记(zygxsq)
        String nowFormat = now.format(dateTimeFormatter);
        System.out.println("格式化后的当前日期:"+nowFormat);
    }

 

获取上周周一的日期

/**
     * 获取上周周一的日期
     * 原文章链接:https://blog.csdn.net/qq_27471405/article/details/106824023
     * 其他均为盗版,公众号:灵儿的笔记(zygxsq)
     */
    public static void getLastMonday(){
        LocalDate now = LocalDate.now();
        System.out.println("当前日期: " + now + " " + now.getDayOfWeek());
        LocalDate todayOfLastWeek = now.minusDays(7);
        LocalDate last_monday = todayOfLastWeek.with(TemporalAdjusters.previous(DayOfWeek.SUNDAY)).plusDays(1); // * 原文章链接:https://blog.csdn.net/qq_27471405/article/details/106824023   * 其他均为盗版,公众号:灵儿的笔记(zygxsq)
        System.out.println("上周周一日期:"+last_monday); 
    }

 

获取具体年、月、日、小时、分钟、秒

/**
     * 获取具体年、月、日、小时、分钟、秒
     * @param formatStr
     */
    public static void getDetailTime(String formatStr){
        LocalDateTime now = LocalDateTime.now();
        System.out.println("当前日期: " + now + " " + now.getDayOfWeek());
        DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern(formatStr);
        String nowFormat = now.format(dateTimeFormatter);
        System.out.println("格式化后的当前日期:"+nowFormat);
        int year = now.getYear();
        int month = now.getMonthValue();
        int day = now.getDayOfMonth();
        int hour = now.getHour();
        int minute = now.getMinute();
        int second = now.getSecond();
        int nano = now.getNano();
        System.out.printf("年 : %d  月 : %d  日 : %d  小时:%d 分钟:%d 秒:%d  毫秒:%d %n", year, month, day,hour,minute,second,nano);  // * 原文章链接:https://blog.csdn.net/qq_27471405/article/details/106824023   * 其他均为盗版,公众号:灵儿的笔记(zygxsq)
    }

 

指定日期、时间

/**
     * 指定日期、时间
     * 原文章链接:https://blog.csdn.net/qq_27471405/article/details/106824023
     * 其他均为盗版,公众号:灵儿的笔记(zygxsq)
     * @param formatStr
     */
    public static void createTime(String formatStr){
        LocalDate date = LocalDate.of(2020, 04, 27);
        System.out.println("指定日期: " + date);
        LocalDateTime time = LocalDateTime.of(2020, 04, 27,06,10,50);
        System.out.println("指定时间: " + time);
        DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern(formatStr);
        String nowFormat = time.format(dateTimeFormatter);
        System.out.println("格式化后的指定时间:"+nowFormat);
    }

 

判断两个日期是否相等

/**
     * 判断两个日期是否相等、之前、之后
     * 原文章链接:https://blog.csdn.net/qq_27471405/article/details/106824023
     * 其他均为盗版,公众号:灵儿的笔记(zygxsq)
     */
    public static void compareDate(){
        LocalDate now = LocalDate.now();
        System.out.println("当前时间: " + now + " " + now.getDayOfWeek());
        LocalDate date1 = LocalDate.of(2020, 04, 27);
        LocalDate date2 = LocalDate.of(2020, 04, 27);
        LocalDate date3 = LocalDate.of(2020, 04, 28);
        boolean equal = now.isEqual(date1);
        System.out.printf("是否是同一时间:%s ", date1.equals(now));
        System.out.printf("是否是同一时间:%s ", now.isEqual(date1));
        System.out.println();
        System.out.printf("是否是同一时间:%s ", date1.equals(date2));
        System.out.printf("是否是同一时间:%s ", date1.isEqual(date2));
        System.out.println();
        System.out.println("data2(2020.4.27)是否比data3(2020.4.28)小: "+date2.isBefore(date3));             * 原文章链接:https://blog.csdn.net/qq_27471405/article/details/106824023   * 其他均为盗版,公众号:灵儿的笔记(zygxsq)
        System.out.println("data2(2020.4.27)是否比data3(2020.4.28)大: "+date2.isAfter(date3));
    }

 

计算几年后(前)、几月后(前)、几天后(前)等的日期

/**
     * 计算几年后(前)、几月后(前)、几天后(前)等的日期
     * 原文章链接:https://blog.csdn.net/qq_27471405/article/details/106824023
     * 其他均为盗版,公众号:灵儿的笔记(zygxsq)
     * @param formatStr
     */
    public static void calculateTime(String formatStr){
        LocalDateTime now = LocalDateTime.now();
        LocalDateTime newTime = now.plusHours(6);
        System.out.println("当前时间: " + now + " " + now.getDayOfWeek());
        System.out.println("6小时后的时间: " +  newTime);
        DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern(formatStr);
        String nowFormat = now.format(dateTimeFormatter);
        String newFormat = newTime.format(dateTimeFormatter);
        System.out.println("格式化后的当前时间:"+nowFormat);
        System.out.println("格式化后的6小时后的时间:"+newFormat);
        LocalDateTime twoYearsLater = now.plusYears(2);
        String twoYearsFormat = twoYearsLater.format(dateTimeFormatter);
        System.out.println("2年后的时间:"+twoYearsFormat);
        LocalDateTime twoMonthsLater = now.plusMonths(2);
        String twoMonthsFormat = twoMonthsLater.format(dateTimeFormatter);
        System.out.println("2个月后的时间:"+twoMonthsFormat);
        LocalDateTime twoWeeksLater = now.plusWeeks(2);
        String twoWeeksFormat = twoWeeksLater.format(dateTimeFormatter);
        System.out.println("2周后的时间:"+twoWeeksFormat);
        LocalDateTime twoDaysLater = now.plusDays(2);
        String twoDaysFormat = twoDaysLater.format(dateTimeFormatter);
        System.out.println("2天后的时间:"+twoDaysFormat);
        LocalDateTime twoMinutesLater = now.plusMinutes(2);
        String twoMinutesFormat = twoMinutesLater.format(dateTimeFormatter);
        System.out.println("2分钟后的时间:"+twoMinutesFormat);
        LocalDateTime twoMinutesBefore = now.plusMinutes(-2);
        String twoMinutesBeforeFormat = twoMinutesBefore.format(dateTimeFormatter);
        System.out.println("2分钟前的时间:"+twoMinutesBeforeFormat);
        //原文章链接:https://blog.csdn.net/qq_27471405/article/details/106824023
        //其他均为盗版,公众号:灵儿的笔记(zygxsq)
        //还可以直接通过plus方法计算 几年(月周天)后
        LocalDateTime twoYearsPlusLater = now.plus(2, ChronoUnit.YEARS);
        String twoYearsPlusLaterFormat = twoYearsPlusLater.format(dateTimeFormatter);
        System.out.println("2年后的时间:"+twoYearsPlusLaterFormat);
        //负号表示 之前
        LocalDateTime twoDaysPlusBefore = now.plus(-2, ChronoUnit.DAYS);
        String twoDaysPlusBeforeFormat = twoDaysPlusBefore.format(dateTimeFormatter);
        System.out.println("2天前的时间:"+twoDaysPlusBeforeFormat);
        //也可以用minus,也表示之前
        LocalDateTime twoDaysMinusBefore = now.minus(2, ChronoUnit.DAYS);
        String twoDaysMinusBeforeFormat = twoDaysMinusBefore.format(dateTimeFormatter);
        System.out.println("2天前的时间:"+twoDaysMinusBeforeFormat);
    }

 

判断指定月份有多少天

 /**
     * 判断指定月份有多少天
     */
    public static void getMonthDays(){
        YearMonth currentYearMonth = YearMonth.now();
        System.out.println("当前时间:"+currentYearMonth);
        System.out.println("当前月份有多少天:"+currentYearMonth.lengthOfMonth());
        YearMonth february = YearMonth.of(2020, Month.FEBRUARY);
        System.out.println("指定时间的月份2月:"+february);
        System.out.println("指定时间的月份2月有多少天:"+february.lengthOfMonth());
    }

 

计算两个日期之间相差月数、天数、分钟数

/**
     * 计算两个日期之间相差月数、天数、分钟数
     * 原文章链接:https://blog.csdn.net/qq_27471405/article/details/106824023
     * 其他均为盗版,公众号:灵儿的笔记(zygxsq)
     */
    public static void getDaysBetweenTwoDate(){
        LocalDate startDate = LocalDate.of(2020, 04, 27);
        LocalDate endDate = LocalDate.of(2020, 07, 2);
        long months = startDate.until(endDate, ChronoUnit.MONTHS);
        long days = startDate.until(endDate, ChronoUnit.DAYS);
        System.out.println("startDate(2020.04.27)和endDate(2020.07.02)相差月数:"+months);
        System.out.println("startDate(2020.04.27)和endDate(2020.07.02)相差天数:"+days);
        LocalDateTime startTime = LocalDateTime.of(2020, 04, 27,18,20,10);
        LocalDateTime endTime = LocalDateTime.of(2020, 04, 27,18,30,12);
        long minutes = startTime.until(endTime, ChronoUnit.MINUTES);
        System.out.println("startTime(2020.04.27 18:20:10)和endTime(2020.04.27 18:30:20)相差分钟数:"+minutes); // * 原文章链接https://blog.csdn.net/qq_27471405/article/details/106824023 * 其他均为盗版,公众号:灵儿的笔记(zygxsq)
    }

相关文章
|
6天前
|
安全 Java 测试技术
Java并行流陷阱:为什么指定线程池可能是个坏主意
本文探讨了Java并行流的使用陷阱,尤其是指定线程池的问题。文章分析了并行流的设计思想,指出了指定线程池的弊端,并提供了使用CompletableFuture等替代方案。同时,介绍了Parallel Collector库在处理阻塞任务时的优势和特点。
|
6天前
|
安全 Java 编译器
JDK 10中的局部变量类型推断:Java编程的简化与革新
JDK 10引入的局部变量类型推断通过`var`关键字简化了代码编写,提高了可读性。编译器根据初始化表达式自动推断变量类型,减少了冗长的类型声明。虽然带来了诸多优点,但也有一些限制,如只能用于局部变量声明,并需立即初始化。这一特性使Java更接近动态类型语言,增强了灵活性和易用性。
87 53
|
2天前
|
安全 Java 开发者
深入解读JAVA多线程:wait()、notify()、notifyAll()的奥秘
在Java多线程编程中,`wait()`、`notify()`和`notifyAll()`方法是实现线程间通信和同步的关键机制。这些方法定义在`java.lang.Object`类中,每个Java对象都可以作为线程间通信的媒介。本文将详细解析这三个方法的使用方法和最佳实践,帮助开发者更高效地进行多线程编程。 示例代码展示了如何在同步方法中使用这些方法,确保线程安全和高效的通信。
15 9
|
5天前
|
存储 安全 Java
Java多线程编程的艺术:从基础到实践####
本文深入探讨了Java多线程编程的核心概念、应用场景及其实现方式,旨在帮助开发者理解并掌握多线程编程的基本技能。文章首先概述了多线程的重要性和常见挑战,随后详细介绍了Java中创建和管理线程的两种主要方式:继承Thread类与实现Runnable接口。通过实例代码,本文展示了如何正确启动、运行及同步线程,以及如何处理线程间的通信与协作问题。最后,文章总结了多线程编程的最佳实践,为读者在实际项目中应用多线程技术提供了宝贵的参考。 ####
|
2天前
|
监控 安全 Java
Java中的多线程编程:从入门到实践####
本文将深入浅出地探讨Java多线程编程的核心概念、应用场景及实践技巧。不同于传统的摘要形式,本文将以一个简短的代码示例作为开篇,直接展示多线程的魅力,随后再详细解析其背后的原理与实现方式,旨在帮助读者快速理解并掌握Java多线程编程的基本技能。 ```java // 简单的多线程示例:创建两个线程,分别打印不同的消息 public class SimpleMultithreading { public static void main(String[] args) { Thread thread1 = new Thread(() -> System.out.prin
|
5天前
|
Java
JAVA多线程通信:为何wait()与notify()如此重要?
在Java多线程编程中,`wait()` 和 `notify()/notifyAll()` 方法是实现线程间通信的核心机制。它们通过基于锁的方式,使线程在条件不满足时进入休眠状态,并在条件满足时被唤醒,从而确保数据一致性和同步。相比其他通信方式,如忙等待,这些方法更高效灵活。 示例代码展示了如何在生产者-消费者模型中使用这些方法实现线程间的协调和同步。
15 3
|
4天前
|
安全 Java
Java多线程集合类
本文介绍了Java中线程安全的问题及解决方案。通过示例代码展示了使用`CopyOnWriteArrayList`、`CopyOnWriteArraySet`和`ConcurrentHashMap`来解决多线程环境下集合操作的线程安全问题。这些类通过不同的机制确保了线程安全,提高了并发性能。
|
5天前
|
Java
java小知识—进程和线程
进程 进程是程序的一次执行过程,是系统运行的基本单位,因此进程是动态的。系统运行一个程序即是一个进程从创建,运行到消亡的过程。简单来说,一个进程就是一个执行中的程序,它在计算机中一个指令接着一个指令地执行着,同时,每个进程还占有某些系统资源如CPU时间,内存空间,文件,文件,输入输出设备的使用权等等。换句话说,当程序在执行时,将会被操作系统载入内存中。 线程 线程,与进程相似,但线程是一个比进程更小的执行单位。一个进程在其执行的过程中产生多个线程。与进程不同的是同类的多个线程共享同一块内存空间和一组系统资源,所以系统在产生一个线程,或是在各个线程之间做切换工作时,负担要比
14 1
|
5天前
|
Java UED
Java中的多线程编程基础与实践
【10月更文挑战第35天】在Java的世界中,多线程是提升应用性能和响应性的利器。本文将深入浅出地介绍如何在Java中创建和管理线程,以及如何利用同步机制确保数据一致性。我们将从简单的“Hello, World!”线程示例出发,逐步探索线程池的高效使用,并讨论常见的多线程问题。无论你是Java新手还是希望深化理解,这篇文章都将为你打开多线程的大门。
|
6天前
|
安全 Java 编译器
Java多线程编程的陷阱与最佳实践####
【10月更文挑战第29天】 本文深入探讨了Java多线程编程中的常见陷阱,如竞态条件、死锁、内存一致性错误等,并通过实例分析揭示了这些陷阱的成因。同时,文章也分享了一系列最佳实践,包括使用volatile关键字、原子类、线程安全集合以及并发框架(如java.util.concurrent包下的工具类),帮助开发者有效避免多线程编程中的问题,提升应用的稳定性和性能。 ####
28 1