java8时间类API安全问题(赠送新的时间工具类哟)
LocalDateTime等新出的日期类全是final修饰的类,不能被继承,且对应的日期变量都是final修饰的,也就是不可变类。赋值一次后就不可变,不存在多线程数据问题。

simpleDateFormat.parse()
simpleDateFormat.format() 注意calendar.setTime(date);,Calendar类是里面基本都是final修饰的,calendar是共享变量,并且这个共享变量没有做线程安全控制。当多个线程同时使用相同的SimpleDateFormat对象【如用static修饰的SimpleDateFormat,一般会封装在工具类,复用】调用format方法时,多个线程会同时调用calendar.setTime方法,可能一个线程刚设置好time值另外的一个线程马上把设置的time值给修改了导致返回的格式化时间可能是错误的。 在多并发情况下使用SimpleDateFormat需格外注意: SimpleDateFormat除了format方法是线程不安全以外,parse方法也是线程不安全的。parse方法实际调用alb.establish(calendar).getTime()方法来解析,alb.establish(calendar)方法里主要完成了


平时封装工具时,封装个静态的SimpleDataFormat
里面这个变量时共享变量,多线程时会出现这样的场景:
A先设置,B也来设置时间值,由于并发了,后面C也来设置值,导致A,B取的值可能时C设置的值
结尾送上个我个人封装java8新的时间工具类供大家使用
package util.bloomfilter; import java.time.Instant;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.ZoneOffset;
import java.time.format.DateTimeFormatter;
import java.util.Date; /**
* java8时间工具类
*/
public class DateUtil {
private DateUtil() throws Exception {
throw new Exception("时间工具禁止new");
} public static final String YYYYMMDDHHMMSSS = "yyyyMMddHHmmss";
public static final String YYYY_MM_DD_HH_DD_SS_TIME = "yyyy-MM-dd HH:mm:ss";
public static final String YYYYMMDDHHMMSSTIME = "yyyy/MM/dd HH:mm:ss";
public static final String YYYY_MM_DD = "yyyy-MM-dd";
public static final String YYYYMMDD = "yyyy/MM/dd";
public static final String YYYYMMDDDATE = "yyyyMMdd"; //根据时间格式化成指定格式日期yyyyMMddHHmmss的字符串
public static String getYYYYMMDDHHMMSSS(LocalDateTime localDateTime) {
//时间传唤为指定格式字符串
return localDateTime.format(DateTimeFormatter.ofPattern(YYYYMMDDHHMMSSS));
} //根据时间格式化成指定格式日期yyyy-MM-dd HH:mm:ss的字符串
public static String getYYYY_MM_DD_HH_DD_SS_TIME(LocalDateTime localDateTime) {
//时间传唤为指定格式字符串
return localDateTime.format(DateTimeFormatter.ofPattern(YYYY_MM_DD_HH_DD_SS_TIME));
} //根据时间格式化成指定格式日期yyyy/MM/dd HH:mm:ss的字符串
public static String getYYYYMMDDHHMMSSTIME(LocalDateTime localDateTime) {
return localDateTime.format(DateTimeFormatter.ofPattern(YYYYMMDDHHMMSSTIME));
} //根据时间格式化成指定格式日期yyyy-MM-dd的字符串
public static String getYYYYMMDD(LocalDateTime localDateTime) {
return localDateTime.format(DateTimeFormatter.ofPattern(YYYY_MM_DD));
} //根据时间格式化成指定格式日期yyyy/MM/dd的字符串
public static String getYYYYMMDD01(LocalDateTime localDateTime) {
return localDateTime.format(DateTimeFormatter.ofPattern(YYYYMMDD));
} //根据时间格式化成指定格式日期yyyyMMdd的字符串
public static String getYYYYMMDDDATE(LocalDateTime localDateTime) {
return localDateTime.format(DateTimeFormatter.ofPattern(YYYYMMDDDATE));
} /**
* 以上是日期转换为指定格式字符串
* >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
*
*/ //yyyy-MM-dd HH:mm:ss格式字符串 转化为时间
public static LocalDateTime YYYY_MM_DD_HH_DD_SS_TIME_TO_LocalDateTime(String dateStr) {
return LocalDateTime.parse(dateStr, DateTimeFormatter.ofPattern(YYYY_MM_DD_HH_DD_SS_TIME));
} //YYYYMMDDHHMMSSS格式字符串 转化为时间
public static LocalDateTime YYYYMMDDHHMMSSS_TO_LocalDateTime(String dateStr) {
return LocalDateTime.parse(dateStr, DateTimeFormatter.ofPattern(YYYYMMDDHHMMSSS));
} //yyyy/MM/dd HH:mm:ss 格式字符串 转化为时间
public static LocalDateTime YYYYMMDDHHMMSSTIME_TO_LocalDateTime(String dateStr) {
return LocalDateTime.parse(dateStr, DateTimeFormatter.ofPattern(YYYYMMDDHHMMSSTIME));
} //yyyy-MM-dd 格式字符串 转化为时间
public static LocalDate YYYY_MM_DD_TO_LocalDateTime(String dateStr) {
return LocalDate.parse(dateStr, DateTimeFormatter.ofPattern(YYYY_MM_DD));
} //yyyy/MM/dd 格式字符串 转化为时间
public static LocalDate YYYYMMDD_TO_LocalDateTime(String dateStr) {
return LocalDate.parse(dateStr, DateTimeFormatter.ofPattern(YYYYMMDD));
}
//yyyyMMdd 格式字符串 转化为时间
public static LocalDate YYYYMMDDDATE_TO_LocalDateTime(String dateStr) {
return LocalDate.parse(dateStr, DateTimeFormatter.ofPattern(YYYYMMDDDATE));
} /**
* 以上是指定格式字符串换为相应日期
* >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
*
*/ //毫秒计时间戳
public static Long getMillionsTime(LocalDateTime localDateTime) {
return localDateTime.toInstant(ZoneOffset.of("+8")).toEpochMilli();
} //秒计时间戳
public static Long getSeconds(LocalDateTime localDateTime) {
return localDateTime.toEpochSecond(ZoneOffset.of("+8"));
} /**
* 以上是日期转化为时间戳
* >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
*
*/ //秒级时间戳转化为LocalDateTime
// 入参是这种 时间戳 long second = LocalDateTime.now().toInstant(ZoneOffset.of("+8")).getEpochSecond();
public static LocalDateTime getSeconds(Long seconds) {
//当前市区时间
LocalDateTime localDateTime = LocalDateTime.ofEpochSecond(seconds, 0, ZoneOffset.ofHours(8));
return localDateTime;
} //秒级时间戳转化为LocalDateTime
// 入参是这种 时间戳 long milliseconds = LocalDateTime.now().toInstant(ZoneOffset.of("+8")).toEpochMilli();
public static LocalDateTime milliseconds(Long milliseconds) {
LocalDateTime localDateTime = LocalDateTime.ofEpochSecond(milliseconds/1000, 0, ZoneOffset.ofHours(8));
return localDateTime;
} //精确毫秒级别 保留三位小数的那种
//入参 long milliseconds = LocalDateTime.now().toInstant(ZoneOffset.of("+8")).toEpochMilli();
public static LocalDateTime millisecondsppoint(Long milliseconds) {
LocalDateTime localDateTime = Instant.ofEpochMilli(milliseconds).atZone(ZoneOffset.ofHours(8)).toLocalDateTime();
return localDateTime;
} /**
* 以上是时间戳转化为日期
* >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
*
*/ //LocalDateTime 转化为 Date
public static Date getLocalDateTime_TO_DateTime(LocalDateTime localDateTime){
// 获得 Instant
Instant instant = Instant.ofEpochSecond(localDateTime.toEpochSecond(ZoneOffset.ofHours(8)));
// 获得 Date
Date date = Date.from(instant);
return date;
} //LocalDateTime 转化为 Date
public static Date getLocalDateTime_TO_DateTime0(LocalDateTime localDateTime){
// 获得 Instant
Instant instant = localDateTime.atZone(ZoneOffset.ofHours(8)).toInstant();
// 获得 Date
Date date = Date.from(instant);
return date;
} //LocalDate 转化为 Date
public static Date getLocalDate_TO_Date(LocalDate localDate){
// 获得 Instant
Instant instant = localDate.atStartOfDay(ZoneOffset.ofHours(8)).toInstant();
// 获得 Date
Date date = Date.from(instant);
return date;
} // Date转化为 LocalDate
public static LocalDate getLocalDate(Date date){
// 获得 LocalDate
LocalDate localDate = date.toInstant().atOffset(ZoneOffset.ofHours(8)).toLocalDate();
return localDate;
} public static void main(String[] args) {
// String str="2021-08-27 10:41:22";
// System.out.println(DateUtil.YYYY_MM_DD_HH_DD_SS_TIME_TO_LocalDateTime(str));
// String str0="20210827104122";
// System.out.println(DateUtil.YYYYMMDDHHMMSSS_TO_LocalDateTime(str0));
// String str1="2021/08/27 10:41:22";
// System.out.println(DateUtil.YYYYMMDDHHMMSSTIME_TO_LocalDateTime(str1));
// String str2="2021-08-27";
// System.out.println(DateUtil.YYYY_MM_DD_TO_LocalDateTime(str2));
// String str3="2021/08/27";
// System.out.println(DateUtil.YYYYMMDD_TO_LocalDateTime(str3));
// String str4="20210827";
// System.out.println(DateUtil.YYYYMMDDDATE_TO_LocalDateTime(str4)); //秒转化为日期
// long second = LocalDateTime.now().toInstant(ZoneOffset.of("+8")).getEpochSecond();
// System.out.println(second);
// System.out.println(DateUtil.getSeconds(second));
//
//毫秒转化日期
// long milliseconds = LocalDateTime.now().toInstant(ZoneOffset.of("+8")).toEpochMilli();
// System.out.println(milliseconds);
// System.out.println(DateUtil.milliseconds(milliseconds));
//毫秒转化为毫秒精确级别日期
// long millisecondss = LocalDateTime.now().toInstant(ZoneOffset.of("+8")).toEpochMilli();
// System.out.println(millisecondss);
// System.out.println(DateUtil.millisecondsppoint(millisecondss)); System.out.println(DateUtil.getLocalDateTime_TO_DateTime(LocalDateTime.now()));
System.out.println(DateUtil.getLocalDate_TO_Date(LocalDate.now()));
System.out.println(DateUtil.getLocalDate(new Date())); } }
java8时间类API安全问题(赠送新的时间工具类哟)的更多相关文章
- Expo大作战(二十七)--expo sdk api之Util(expo自带工具类),tackSnapshotAsync,Svg,SQLite
简要:本系列文章讲会对expo进行全面的介绍,本人从2017年6月份接触expo以来,对expo的研究断断续续,一路走来将近10个月,废话不多说,接下来你看到内容,讲全部来与官网 我猜去全部机翻+个人 ...
- c#中@标志的作用 C#通过序列化实现深表复制 细说并发编程-TPL 大数据量下DataTable To List效率对比 【转载】C#工具类:实现文件操作File的工具类 异步多线程 Async .net 多线程 Thread ThreadPool Task .Net 反射学习
c#中@标志的作用 参考微软官方文档-特殊字符@,地址 https://docs.microsoft.com/zh-cn/dotnet/csharp/language-reference/toke ...
- BadgeView新提示开源工具类
BadgeView是使用某个图标作为新功能的提醒,类似于收到短息后短信图标的右上方有信息数目或者其他的显示性提示.BadgeView很好的实现了这个功能,而且进行了拓展,可自定义位置和提示图标. 工具 ...
- 【转载】C#工具类:实现文件操作File的工具类
在应用程序的开发中,文件操作的使用基本上是必不可少的,FileStream类.StreamWriter类.Directory类.DirectoryInfo类等都是文件操作中时常涉及到的类,我们可以通过 ...
- mybatis的基本配置:实体类、配置文件、映射文件、工具类 、mapper接口
搭建项目 一:lib(关于框架的jar包和数据库驱动的jar包) 1,第一步:先把mybatis的核心类库放进lib里
- UUID与System.currentTimeMillis()产生一个新文件名的工具类
1.FileUtils.java package Utils.GenerateNewFileName; import java.util.UUID; public class FileUtils { ...
- Vcode的生成工具类,生成制定长度验证码,图文验证码工具类
public class VCodeUtils { // 使用到Algerian字体,系统里没有的话需要安装字体,字体只显示大写,去掉了1,0,i,o几个容易混淆的字符 public static f ...
- 【工具类】获取Http请求IP的工具类
public class IpAddressUtil { public static String getIpAddr(HttpServletRequest request){ String ipAd ...
- 【工具类】获取请求头中User-Agent工具类
public class AgentUserKit { private static String pattern = "^Mozilla/\\d\\.\\d\\s+\\(+.+?\\)&q ...
随机推荐
- 简单快速安装Apache+PHP+MySql服务环境(三)—— 下载安装phpmyadmin
为了方便在Linux上操作mysql数据库,打算安装一个phpmyadmin,不过在下载安装的过程中出现了一些坑,特此记录. 1. 在官网上下载phpmyadmin https://files.php ...
- Navicat Premium 12安装及破解
特别提醒,Navicat Premium 12安装包请用我给的链接下载,不然会无法破解 下载Navicat Premium 12地址:https://pan.baidu.com/s/1AQsryKpJ ...
- 福昕foxit phantom pdf高级编辑器企业版10.1 pro安装破解教程
本文提供福昕foxit phantom pdf高级编辑器企业版10.1的安装教程.pj教程,可以使用全部功能,注意的是此方法对个人版无效. 没有必要再尝试别的文章,仅看这一篇即可!别的文章亲测是通过修 ...
- Python - 赋值运算符
前置知识 先了解下变量: https://www.cnblogs.com/poloyy/p/15042257.html 再了解下算术运算符: https://www.cnblogs.com/poloy ...
- SQL之case when then用法_之二
select CustomerNo, Name, Sex, Birthday, IDType, IDNo, validityday, case (null ) when '1' then '高级VIP ...
- canvas的globalCompositeOperation属性
在开发过程中遇到过类似刮刮卡的效果,就是涂抹时变透明,显示出下方的内容,做法思路简单说一下问题和解决方案: 分为2层,最下面一层是内容,比如'一等奖',上面一层用一个canvas遮挡住,画布本来是透明 ...
- 3G/4G串口服务器
Z3G/4G串口服务器 ZLAN8303-7是上海卓岚继ZLAN8100之后推出的3G/4G联网解决方案.支持7模的4G串口服务器.其产品支持Modbus功能.自定义注册包心跳包功能. ZLAN830 ...
- 为什么crictl和ctr的输出有时不一样
containerd 相比于docker , 多了namespace概念, 每个image和container 都会在各自的namespace下可见, 目前k8s会使用k8s.io 作为命名空间 cr ...
- 浅谈C#取消令牌CancellationTokenSource
前言 相信大家在使用C#进行开发的时候,特别是使用异步的场景,多多少少会接触到CancellationTokenSource.看名字就知道它和取消异步任务相关的,而且一看便知大名鼎鼎的Cancella ...
- 进程信号的未决状态(pending status)
这两天看了apue有关进程信号的部分,觉得未决状态这个词很是不一般,呵呵.一开始当我看到这个词,我不理解,什么意思呢,读了好几遍.不知道是书里面讲的晦涩难懂,还是脑子越来越不行了,就是没有搞明白.后来 ...