JAVA中的SimpleDateFormat是非线程安全的,所有在1.8的JDK版本里提供了线程安全的DateTimeFormatter类,由于是线程安全的,故我们可以将此类缓存起来多次利用提高效率。

同时在JDK8中提供了LocalDate、LocalTime、LocalDateTime,下面的工具类也对这3个新类提供了格式化和反格式化的支持。

package com.longge.util;

import java.time.Instant;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.Period;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.util.Calendar;
import java.util.Date;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.TimeUnit; import org.apache.commons.lang3.StringUtils; import com.longge.exception.TimeUnitNotSupportException; import lombok.NonNull; /**
* 带缓存的基于DateTimeFormatter的日期格式化工具类
* @author yangzhilong
* @date 6/21/2019
*/
public class DateUtils {
private static final Map<String, DateTimeFormatter> FORMATTER_CACHE = new ConcurrentHashMap<>(); private DateUtils() {} /**
* 日期的格式化定义
* @author yangzhilong
* @date 6/21/2019
*/
public static class Pattern {
private Pattern() {} public static class Date {
private Date() {} /**
* yyyy-MM-dd
*/
public static final String YYYY_MM_DD = "yyyy-MM-dd";
/**
* yyyy-M-dd
*/
public static final String YYYY_M_DD = "yyyy-M-dd";
/**
* yyyy-M-d
*/
public static final String YYYY_M_D = "yyyy-M-d";
/**
* yyyy/MM/dd
*/
public static final String YYYY_MM_DD_2 = "yyyy/MM/dd";
/**
* yyyy/M/dd
*/
public static final String YYYY_M_DD_2 = "yyyy/M/dd";
/**
* yyyy/M/d
*/
public static final String YYYY_M_D_2 = "yyyy/M/d";
/**
* yyyyMMdd
*/
public static final String YYYYMMDD = "yyyyMMdd";
/**
* yyyyMdd
*/
public static final String YYYYMDD = "yyyyMdd";
/**
* yyyyMd
*/
public static final String YYYYMD = "yyyyMd"; /**
* MM-dd-yyyy
*/
public static final String MM_DD_YYYY = "MM-dd-yyyy";
/**
* M-dd-yyyy
*/
public static final String M_DD_YYYY = "M-dd-yyyy";
/**
* M-d-yyyy
*/
public static final String M_D_YYYY = "M-d-yyyy";
/**
* MM/dd/yyyy
*/
public static final String MM_DD_YYYY_2 = "MM/dd/yyyy";
/**
* M/dd/yyyy
*/
public static final String M_DD_YYYY_2 = "M/dd/yyyy";
/**
* M/d/yyyy
*/
public static final String M_D_YYYY_2 = "M/d/yyyy";
/**
* MMddyyyy
*/
public static final String MMDDYYYY = "MMddyyyy";
/**
* Mddyyyy
*/
public static final String MDDYYYY = "Mddyyyy";
/**
* Mdyyyy
*/
public static final String MDYYYY = "Mdyyyy";
} public static class DateTime {
private DateTime() {} /**
* yyyy-MM-dd HH:mm:ss
*/
public static final String YYYY_MM_DD_SPACE_HH_MM_SS = "yyyy-MM-dd HH:mm:ss";
/**
* yyyy-M-d H:m:s
*/
public static final String YYYY_M_D_SPACE_H_M_S = "yyyy-M-d H:m:s";
/**
* yyyy/MM/dd HH:mm:ss
*/
public static final String YYYY_MM_DD_SPACE_HH_MM_SS2 = "yyyy/MM/dd HH:mm:ss";
/**
* HH:mm yyyy-MM-dd
*/
public static final String HH_MM_SPACE_YYYY_MM_DD = "HH:mm yyyy-MM-dd";
/**
* HH:mm yyyy/MM/dd
*/
public static final String HH_MM_SPACE_YYYY_MM_DD2 = "HH:mm yyyy/MM/dd";
/**
* H:mm yyyy-MM-dd
*/
public static final String H_MM_SPACE_YYYY_MM_DD = "H:mm yyyy-MM-dd";
/**
/**
* H:mm yyyy/MM/dd
*/
public static final String H_MM_SPACE_YYYY_MM_DD2 = "H:mm yyyy/MM/dd";
/**
* H:mm,yyyy-MM-dd
*/
public static final String H_MM_COMMA_YYYY_MM_DD = "H:mm,yyyy-MM-dd";
/**
* H:mm,yyyy-MM-dd
*/
public static final String H_MM_COMMA_YYYY_MM_DD2 = "H:mm,yyyy/MM/dd";
/**
* H:mm,yyyy-M-d
*/
public static final String H_MM_COMMA_YYYY_M_D = "H:mm,yyyy-M-d";
/**
* H:m,yyyy-M-d
*/
public static final String H_M_COMMA_YYYY_M_D = "H:m,yyyy-M-d";
/**
* H:mm,yyyy-M-d
*/
public static final String H_MM_COMMA_YYYY_M_D2 = "H:mm,yyyy/M/d";
/**
* H:m,yyyy-M-d
*/
public static final String H_M_COMMA_YYYY_M_D2 = "H:m,yyyy/M/d";
}
} /**
* 格式化不带时分秒的日期
* @param date
* @param pattern {@link DateUtils.Pattern.Date}
* @return
*/
public static String formatDate(@NonNull Date date, @NonNull String pattern) {
Instant instant = date.toInstant();
ZoneId zone = ZoneId.systemDefault();
LocalDate localDate = LocalDateTime.ofInstant(instant, zone).toLocalDate();
return formatDate(localDate, pattern);
} /**
* 格式化不带时分秒的LocalDate
* @param localDate
* @param pattern {@link DateUtils.Pattern.Date}
* @return
*/
public static String formatDate(@NonNull LocalDate localDate, @NonNull String pattern) {
if(StringUtils.isBlank(pattern)) {
throw new NullPointerException("pattern is null");
} DateTimeFormatter formatter = createCacheFormatter(pattern);
return localDate.format(formatter);
} /**
* 格式化带时分秒的日期
* @param date
* @param pattern {@link DateUtils.Pattern.DateTime}
* @return
*/
public static String formatDateTime(@NonNull Date date, @NonNull String pattern) {
LocalDateTime formatDateTime = LocalDateTime.ofInstant(date.toInstant(), ZoneId.systemDefault());
return formatDateTime(formatDateTime, pattern);
} /**
* 格式化带时分秒的LocalDateTime
* @param localDateTime
* @param pattern {@link DateUtils.Pattern.DateTime}
* @return
*/
public static String formatDateTime(@NonNull LocalDateTime localDateTime, @NonNull String pattern) {
if(StringUtils.isBlank(pattern)) {
throw new NullPointerException("pattern is null");
}
DateTimeFormatter formatter = createCacheFormatter(pattern);
return localDateTime.format(formatter);
} /**
* 转换不带时分秒的字符串到Date
* @param date
* @param pattern {@link DateUtils.Pattern.Date}
* @return
*/
public static Date parseDate(@NonNull String date, @NonNull String pattern) {
LocalDate localDate = parseLocalDate(date, pattern);
Instant instant = localDate.atStartOfDay().atZone(ZoneId.systemDefault()).toInstant();
return Date.from(instant);
} /**
* 转换不带时分秒的字符串到LocalDate
* @param date
* @param pattern {@link DateUtils.Pattern.Date}
* @return
*/
public static LocalDate parseLocalDate(@NonNull String date, @NonNull String pattern) {
if(StringUtils.isBlank(date)) {
throw new NullPointerException("date is null");
}
if(StringUtils.isBlank(pattern)) {
throw new NullPointerException("pattern is null");
}
DateTimeFormatter formatter = createCacheFormatter(pattern);
return LocalDate.parse(date, formatter);
} /**
* 转换带时分秒的字符串到Date
* @param dateTime
* @param pattern {@link DateUtils.Pattern.Date}
* @return
*/
public static Date parseDateTime(@NonNull String dateTime, @NonNull String pattern) {
if(StringUtils.isBlank(dateTime)) {
throw new NullPointerException("date is null");
}
if(StringUtils.isBlank(pattern)) {
throw new NullPointerException("pattern is null");
}
LocalDateTime localDateTime = parseLocalDateTime(dateTime, pattern);
Instant instant = localDateTime.atZone(ZoneId.systemDefault()).toInstant();
return Date.from(instant);
} /**
* 转换带时分秒的字符串到LocalDateTime
* @param dateTime
* @param pattern {@link DateUtils.Pattern.DateTime}
* @return
*/
public static LocalDateTime parseLocalDateTime(@NonNull String dateTime, @NonNull String pattern) {
DateTimeFormatter formatter = createCacheFormatter(pattern);
return LocalDateTime.parse(dateTime, formatter);
} /**
* 日期的加减(仅支持天/小时/分/秒)
* @param date
* @param addValue
* @param unit
* @return
*/
public static Date dateAdd(@NonNull Date date, int addValue, TimeUnit unit) {
Calendar cal = Calendar.getInstance();
cal.setTime(date); if (TimeUnit.DAYS.equals(unit)) {
cal.add(Calendar.DAY_OF_YEAR, addValue);
} else if (TimeUnit.HOURS.equals(unit)) {
cal.add(Calendar.HOUR_OF_DAY, addValue);
} else if (TimeUnit.MINUTES.equals(unit)) {
cal.add(Calendar.MINUTE, addValue);
} else if (TimeUnit.SECONDS.equals(unit)) {
cal.add(Calendar.SECOND, addValue);
} else {
throw new TimeUnitNotSupportException();
}
return cal.getTime();
} /**
* 计算2个日期的差
* @param begin
* @param end
* @return
*/
public static Period calculationPeriod(@NonNull Date begin, Date end) {
Calendar beginCal = Calendar.getInstance();
beginCal.setTime(begin); Calendar endCal = Calendar.getInstance();
endCal.setTime(end); LocalDate beginLocal =
LocalDate.of(beginCal.get(Calendar.YEAR), beginCal.get(Calendar.MONTH), beginCal.get(Calendar.DAY_OF_YEAR));
LocalDate endLocal =
LocalDate.of(beginCal.get(Calendar.YEAR), beginCal.get(Calendar.MONTH), beginCal.get(Calendar.DAY_OF_YEAR)); return Period.between(beginLocal, endLocal);
} /**
* DateTimeFormatter缓存处理
* @param begin
* @param end
* @return
*/
private static DateTimeFormatter createCacheFormatter(String pattern) {
if (pattern == null || pattern.length() == 0) {
throw new IllegalArgumentException("Invalid pattern specification");
} DateTimeFormatter formatter = FORMATTER_CACHE.get(pattern);
if(null == formatter) {
formatter = DateTimeFormatter.ofPattern(pattern);
FORMATTER_CACHE.put(pattern, formatter);
} return formatter;
}
}

带缓存的基于DateTimeFormatter的日期格式化工具类的更多相关文章

  1. Java 日期格式化工具类

    import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.Calendar; impor ...

  2. java基础篇 -- 常用的日期加减和日期格式化工具类

    平时我们遇到日期的加减,感觉是相当麻烦的,以下是常用的日志加减的方法,包括日的加减.月的加减等,也包括了一些常用的日期格式化,这样在我们以后碰到日期加减的时候会省去很多麻烦,欢迎大神指正和吐槽: pa ...

  3. Java ——日期时间 日期时间相关类 随机数 定义类属性时建议使用引用数据类型

    本节重点思维导图 Date对象创建 两个构造函数: Date() ----使用当前日期和时间来初始化对象 Date(long millisec) -----接收一个参数,该参数是从1970年1月1日起 ...

  4. 基于AFN封装的带缓存的网络请求

    给大家分享一个基于AFN封装的网络请求 git: https://github.com/zhouxihi/NVNetworking #带缓存机制的网络请求 各类请求有分带缓存 , 不带缓存, 可自定义 ...

  5. 基于Java8的日期时间工具类DateTimeFormatter

    原文:https://blog.csdn.net/qq_36596145/article/details/85331002 import java.time.Instant; import java. ...

  6. Delphi中带缓存的数据更新技术

    一. 概念 在网络环境下,数据库应用程序是c/s或者是多层结构的模式.在这种环境下,数据库应用程序的开发应当尽可能考虑减少网络数据传输量,并且尽量提高并发度.基于这个目的,带缓存的数据更新技术应运而生 ...

  7. JS 日期工具类-基于yDate

    源码下载 前言:最近在用到JS日期操作时,发现有一些不方便,于是搜素了一些网上的资料,基于一个开源工具类-yDate 进行了个性化定制,封装成了一个日期工具类工具函数大概介绍:1.普通的日期操作2. ...

  8. 带缓存的输入输出-bufferedinputstream类与bufferedoutputstream类

    package hengzhe.cn.o1; import java.io.*; /* * 带缓存的输入输出-bufferedinputstream类与bufferedoutputstream类 * ...

  9. 不带缓存的I/O和标准(带缓存的)I/O

    首先,先稍微了解系统调用的概念:       系统调用,英文名system call,每个操作系统都在内核里有一些内建的函数库,这些函数可以用来完成一些系统系统调用把应用程序的请求传给内核,调用相应的 ...

随机推荐

  1. selenium自动化爬虫测试

    import time from selenium import webdriver from lxml import etree from selenium.webdriver import Act ...

  2. Linux命令groupadd

    groupadd [选项] 组 创建一个新的组.Groupadd命令使用命令行中指定的值加上系统默认值创建新的组账户.新组将根据需要输入系统. (1).选项 -f,--force 如果指定的组已经存在 ...

  3. 动态路由 RIP

    不同网段之间进行通信,中间有多个路由器的情况下,我们可以通过配置RIP动态路由来实现数据转发. 实验拓扑 如图所示连接,地址规划如下: 名称 接口 IP地址 R1 f0/0 192.168.10.1/ ...

  4. echarts 通过源码方法 传入对应data数据获取分割步长值

    通过源码方法获取这里的分割数字长度 /** * Quantity of a number. e.g. 0.1, 1, 10, 100 * * @param {number} val * @return ...

  5. Executors、ThreadPoolExecutor线程池讲解

    官方+白话讲解Executors.ThreadPoolExecutor线程池使用 Executors:JDK给提供的线程工具类,静态方法构建线程池服务ExecutorService,也就是Thread ...

  6. Linux学习之组管理和权限管理

    Linux组的基本介绍 在Linux中的每个用户必须属于一个组,不能独立于组外.在Linux中每个文件有所有者,所在组,其他组的概念. 1)所有者 2)所在组 3)其他组 4)改变用户所在的组 文件/ ...

  7. 进程间通信之数据传输--Socket

    The client server model Most interprocess communication uses the client server model. These terms re ...

  8. flask 源码浅析(flask 如何处理请求(多线程,多进程,IO多路复用))

    2018-04-04 13:09:47 lucky404 阅读数 5724更多 分类专栏: python   版权声明:本文为博主原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接 ...

  9. Pycharm中设置默认头注释

    在编写Python项目时,我们可能需要添加一些默认的信息,比如添加文件创建的时间,比如添加文件作者,等等,这些信息可以自己在python脚本中添加,但是也可以在Pycharm中配置模板,每次创建文件的 ...

  10. 百度UEditor添加视频 增加支持“通用代码”功能,支持微信

    今天发现用UEditor默认的添加视频,在微信内置浏览器里无法正常显示.估计是微信屏蔽了UEditor使用的<embeded>标签.插入iframe形式的通用代码则能正常显示. 用百度UE ...