为什么建议使用你 LocalDateTime ,而不是 Date
为什么建议使用你 LocalDateTime ,而不是 Date?
在项目开发过程中经常遇到时间处理,但是你真的用对了吗,理解阿里巴巴开发手册中禁用static修饰SimpleDateFormat吗
通过阅读本篇文章你将了解到:
-
为什么需要LocalDate、LocalTime、LocalDateTime【java8新提供的类】
-
java8新的时间API的使用方式,包括创建、格式化、解析、计算、修改
为什么需要LocalDate、LocalTime、LocalDateTime
-
Date如果不格式化,打印出的日期可读性差
Tue Sep 10 09:34:04 CST 2019
-
使用SimpleDateFormat对时间进行格式化,但SimpleDateFormat是线程不安全的SimpleDateFormat的format方法最终调用代码:
private StringBuffer format(Date date, StringBuffer toAppendTo, FieldDelegate delegate) { // Convert input date to time field list calendar.setTime(date); boolean useDateFormatSymbols = useDateFormatSymbols(); for (int i = 0; i < compiledPattern.length; ) { int tag = compiledPattern[i] >>> 8; int count = compiledPattern[i++] & 0xff; if (count == 255) { count = compiledPattern[i++] << 16; count |= compiledPattern[i++]; } switch (tag) { case TAG_QUOTE_ASCII_CHAR: toAppendTo.append((char)count); break; case TAG_QUOTE_CHARS: toAppendTo.append(compiledPattern, i, count); i += count; break; default: subFormat(tag, count, delegate, toAppendTo, useDateFormatSymbols); break; } } return toAppendTo; }
calendar是共享变量,并且这个共享变量没有做线程安全控制。当多个线程同时使用相同的SimpleDateFormat对象【如用static修饰的SimpleDateFormat】调用format方法时,多个线程会同时调用calendar.setTime方法,可能一个线程刚设置好time值另外的一个线程马上把设置的time值给修改了导致返回的格式化时间可能是错误的。
在多并发情况下使用SimpleDateFormat需格外注意SimpleDateFormat除了format是线程不安全以外,parse方法也是线程不安全的。parse方法实际调用alb.establish(calendar).getTime()方法来解析,alb.establish(calendar)方法里主要完成了
-
重置日期对象cal的属性值
-
使用calb中中属性设置cal
-
返回设置好的cal对象
但是这三步不是原子操作
多线程并发如何保证线程安全 - 避免线程之间共享一个SimpleDateFormat对象,每个线程使用时都创建一次SimpleDateFormat对象 => 创建和销毁对象的开销大 - 对使用format和parse方法的地方进行加锁 => 线程阻塞性能差 - 使用ThreadLocal保证每个线程最多只创建一次SimpleDateFormat对象 => 较好的方法
-
Date对时间处理比较麻烦,比如想获取某年、某月、某星期,以及n天以后的时间,如果用Date来处理的话真是太难了,你可能会说Date类不是有getYear、getMonth这些方法吗,获取年月日很Easy,但都被弃用了啊
Come On 一起使用java8全新的日期和时间API
LocalDate
只会获取年月日
-
创建LocalDate
//获取当前年月日
LocalDate localDate = LocalDate.now();
//构造指定的年月日
LocalDate localDate1 = LocalDate.of(2019, 9, 10);
-
获取年、月、日、星期几
int year = localDate.getYear();
int year1 = localDate.get(ChronoField.YEAR);
Month month = localDate.getMonth();
int month1 = localDate.get(ChronoField.MONTH_OF_YEAR);
int day = localDate.getDayOfMonth();
int day1 = localDate.get(ChronoField.DAY_OF_MONTH);
DayOfWeek dayOfWeek = localDate.getDayOfWeek();
int dayOfWeek1 = localDate.get(ChronoField.DAY_OF_WEEK);
LocalTime
只会获取几点几分几秒
-
创建LocalTime
LocalTime localTime = LocalTime.of(13, 51, 10); LocalTime localTime1 = LocalTime.now();
-
获取时分秒
//获取小时
int hour = localTime.getHour();
int hour1 = localTime.get(ChronoField.HOUR_OF_DAY);
//获取分
int minute = localTime.getMinute();
int minute1 = localTime.get(ChronoField.MINUTE_OF_HOUR);
//获取秒
int second = localTime.getSecond();
int second1 = localTime.get(ChronoField.SECOND_OF_MINUTE);
LocalDateTime
获取年月日时分秒,等于LocalDate+LocalTime
-
创建LocalDateTime
LocalDateTime localDateTime = LocalDateTime.now();
LocalDateTime localDateTime1 = LocalDateTime.of(2019, Month.SEPTEMBER, 10, 14, 46, 56);
LocalDateTime localDateTime2 = LocalDateTime.of(localDate, localTime);
LocalDateTime localDateTime3 = localDate.atTime(localTime);
LocalDateTime localDateTime4 = localTime.atDate(localDate);
-
获取LocalDate
LocalDate localDate2 = localDateTime.toLocalDate();
-
获取LocalTime
LocalTime localTime2 = localDateTime.toLocalTime();
Instant
获取秒数
-
创建Instant对象
Instant instant = Instant.now();
-
获取秒数
long currentSecond = instant.getEpochSecond();
-
获取毫秒数
long currentMilli = instant.toEpochMilli();
个人觉得如果只是为了获取秒数或者毫秒数,使用System.currentTimeMillis()来得更为方便
修改LocalDate、LocalTime、LocalDateTime、Instant
LocalDate、LocalTime、LocalDateTime、Instant为不可变对象,修改这些对象对象会返回一个副本
-
增加、减少年数、月数、天数等 以
LocalDateTime
为例
LocalDateTime localDateTime = LocalDateTime.of(2019, Month.SEPTEMBER, 10, 14, 46, 56);
//增加一年
localDateTime = localDateTime.plusYears(1);
localDateTime = localDateTime.plus(1, ChronoUnit.YEARS);
//减少一个月
localDateTime = localDateTime.minusMonths(1);
localDateTime = localDateTime.minus(1, ChronoUnit.MONTHS);
-
通过
with
修改某些值
//修改年为2019
localDateTime = localDateTime.withYear(2020);
//修改为2022
localDateTime = localDateTime.with(ChronoField.YEAR, 2022);
还可以修改月、日
时间计算
比如有些时候想知道这个月的最后一天是几号、下个周末是几号,通过提供的时间和日期API可以很快得到答案
LocalDate localDate = LocalDate.now();
LocalDate localDate1 = localDate.with(firstDayOfYear());
比如通过firstDayOfYear()返回了当前日期的第一天日期,还有很多方法这里不在举例说明
格式化时间
LocalDate localDate = LocalDate.of(2019, 9, 10);
String s1 = localDate.format(DateTimeFormatter.BASIC_ISO_DATE);
String s2 = localDate.format(DateTimeFormatter.ISO_LOCAL_DATE);
//自定义格式化
DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("dd/MM/yyyy");
String s3 = localDate.format(dateTimeFormatter);
DateTimeFormatter默认提供了多种格式化方式,如果默认提供的不能满足要求,可以通过DateTimeFormatter的ofPattern方法创建自定义格式化方式
解析时间
LocalDate localDate1 = LocalDate.parse("20190910", DateTimeFormatter.BASIC_ISO_DATE);
LocalDate localDate2 = LocalDate.parse("2019-09-10", DateTimeFormatter.ISO_LOCAL_DATE);
和SimpleDateFormat相比,DateTimeFormatter是线程安全的
小结
LocalDateTime
:Date
有的我都有,Date
没有的我也有,日期选择请Pick Me
SpringBoot中应用LocalDateTime
-
将LocalDateTime字段以时间戳的方式返回给前端 添加日期转化类
public class LocalDateTimeConverter extends JsonSerializer<LocalDateTime> { @Override public void serialize(LocalDateTime value, JsonGenerator gen, SerializerProvider serializers) throws IOException { gen.writeNumber(value.toInstant(ZoneOffset.of("+8")).toEpochMilli()); }
}
并在
LocalDateTime
字段上添加
@JsonSerialize(using = LocalDateTimeConverter.class)
注解,如下:
@JsonSerialize(using = LocalDateTimeConverter.class)
protected LocalDateTime gmtModified;
-
将LocalDateTime字段以指定格式化日期的方式返回给前端 在
LocalDateTime
字段上添加
@JsonFormat(shape=JsonFormat.Shape.STRING, pattern="yyyy-MM-dd HH:mm:ss")
注解即可,如下:
@JsonFormat(shape=JsonFormat.Shape.STRING, pattern="yyyy-MM-dd HH:mm:ss")
protected LocalDateTime gmtModified;
-
对前端传入的日期进行格式化 在
LocalDateTime
字段上添加
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
注解即可,如下:
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
protected LocalDateTime gmtModified;
相关文章:
为什么建议使用你 LocalDateTime ,而不是 Date
为什么建议使用你 LocalDateTime ,而不是 Date? 在项目开发过程中经常遇到时间处理,但是你真的用对了吗,理解阿里巴巴开发手册中禁用static修饰SimpleDateFormat吗 通过阅读本篇文章你将了解到: 为什么需要LocalDate…...
【大数据】HADOOP-YARN容量调度器Spark作业实战
目录需求配置多队列的容量调度器验证队列资源需求 default 队列占总内存的40%,最大资源容量占总资源的60% ops 队列占总内存的60%,最大资源容量占总资源的80% 配置多队列的容量调度器 在yarn-site.xml里面配置使用容量调度器 <!-- 使用容量调度器…...
平面及其方程
一、曲面和交线的定义 空间解析几何中,任何曲面或曲线都看作点的几何轨迹。在这样的意义下,如果曲面SSS与三元方程: F(x,y,z)0(1)F(x,y,z)0\tag{1} F(x,y,z)0(1) 有下述关系: 曲面 SSS 上任一点的坐标都满足方程(1)(1)(1)不在曲…...
7 配置的封装
概述 IPC设备通常有三种配置信息:一是默认配置,存储了设备所有配置项的默认值,默认配置是只读的,不能修改;二是用户配置,存储了用户修改过的所有配置项;三是私有配置,存储了程序内部使用的一些配置项,比如:固件升级的URL、固件升级标志位等。恢复出厂设置的操作,实际…...
03_Docker 入门
03_Docker 入门 文章目录03_Docker 入门3.1 确保 Docker 已经就绪3.2 运行我们的第一个容器3.3 使用第一个容器3.4 容器命名3.5 重新启动已经停止的容器3.6 附着到容器上3.7 创建守护式容器3.8 容器内部都在干些什么3.9 Docker 日志驱动3.10 查看容器内的进程3.11 Docker 统计信…...
Python 为什么要 if __name__ == “__main__“:
各位读者,你们知道以下两个Python文件有什么区别吗? main1.py def main():output Helloprint(output)if __name__ "__main__":main()main2.py output Hello print(output)当我们直接运行 main1.py 与 main2.py 的时候,程序都…...
455. 分发饼干、376. 摆动序列、53. 最大子数组和
455.分发饼干 题目描述: 假设你是一位很棒的家长,想要给你的孩子们一些小饼干。但是,每个孩子最多只能给一块饼干。 对每个孩子 i,都有一个胃口值 g[i],这是能让孩子们满足胃口的饼干的最小尺寸;并且每块…...
基于Springbot+微信小程序的购药平台的设计与实现
基于Springbot微信小程序的购药平台的设计与实现 ✌全网粉丝20W,csdn特邀作者、博客专家、CSDN新星计划导师、java领域优质创作者,博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌ 🍅文末获取项目下载方式🍅 一、…...
aws lambda rust的sdk和自定义运行时
rust的aws sdk 参考资料 https://docs.aws.amazon.com/sdk-for-rust/latest/dg/getting-started.htmlhttps://awslabs.github.io/aws-sdk-rust/https://github.com/awslabs/aws-sdk-rusthttps://github.com/awsdocs/aws-doc-sdk-examples/tree/main/rust_dev_preview rus sd…...
[安装之3] 笔记本加装固态和内存条教程(超详细)
由于笔记本是几年前买的了,当时是4000,现在用起来感到卡顿,启动、运行速度特别慢,就决定换个固态硬盘,加个内存条,再给笔记本续命几年。先说一下加固态硬盘SSD的好处:1.启动快 2.读取延迟小 3.写…...
极客时间左耳听风-高效学习
左耳听风——高效学习篇 P95 | 高效学习:端正学习态度 本人真实⬇️⬇️⬇️⬇️ “ 大部分人都认为自己爱学习,但是: 他们都是只有意识没有行动,他们是动力不足的人。 他们都不知道自己该学什么,他们缺乏方向和目标。…...
MSR寄存器访问
1.介绍 MSR是CPU的一组64位寄存器,每个MSR都有它的地址值(如下图所示),可以分别通过RDMSR 和WRMSR 两条指令进行读和写的操作。 如图中为8个P-state寄存器,地址分别为0xC001 0064 ~ 0xC001 006B,每个寄存…...
ArcGIS:模型构建器实现批量按掩膜提取影像
用研究区域的矢量数据来裁剪栅格数据集时,一般我们使用ArcGIS中的【按掩膜提取工具】。如果需要裁剪的栅格数据太多,处理起来非常的麻烦,虽然ArcGIS中有批处理的功能,但是还是需要手动选择输入输出数据。 如下图,鼠标…...
算法刷题打卡第94天: 找出给定方程的正整数解
找出给定方程的正整数解 难度:中等 给你一个函数 f(x, y) 和一个目标结果 z,函数公式未知,请你计算方程 f(x,y) z 所有可能的正整数 数对 x 和 y。满足条件的结果数对可以按任意顺序返回。 尽管函数的具体式子未知,但它是单调…...
浅析SAS协议(1):基本介绍
文章目录概述SAS协议发展历程SAS技术特性SAS设备拓扑SAS phySAS地址SAS设备类型SAS协议分层参考链接概述 SAS,全称Serial Attached SCSI,即串行连结SCSI,是一种采用了串行总线的高速互连技术。通过物理上使用串行总线连结,在链路…...
93.【Vue-细刷-02】
Vue-02(十六)、基本列表渲染 (v-for)1.使用v-for遍历数组2.使用v-for遍历对象3.使用v-for遍历字符串(十七)、列表过滤 (filter())1.⭐JS中Change属性的原生状态⭐2.使用watch监听实现3.const {xxx} this 在Vue的作用⭐⭐4.JS箭头函数参数的简写⭐5.使用computed进行计算实现(最…...
Allegro负片层不显示反盘的原因和解决办法
Allegro负片层不显示反盘的原因和解决办法 在用Allegro做PCB设计的时候,负片设计是较为常用的一种方式,有时会出现打开负片层却看不到反盘的情况,如下图 L2层是负片层 L2层仍然只能看到盘 如何才能看到反盘显示的效果,具体操作如下 首先确定L2层层叠里面设置的是负片...
ACM数论 裴蜀定理(贝祖定理)
一.内容定义 「裴蜀定理」,又称贝祖定理(Bzouts lemma)。是一个关于最大公约数的定理。其内容定义为:对于不全为零的任意整数 a 和 b,记二者的最大公约数为 g 即 gcd(a,b) g,则对于任意整数 x 和 y 都一定…...
基础篇—CSS Position(定位)解析
CSS Position(定位) position 属性指定了元素的定位类型。 position 属性的五个值: relativefixedabsolutesticky元素可以使用的顶部,底部,左侧和右侧属性定位。然而,这些属性无法工作,除非是先设定position属性。他们也有不同的工作方式,这取决于定位方法。 1、static…...
正则表达式与grep
基本正则表达式BRE集合 匹配字符匹配次数位置锚定 符号作用^尖角号,用于模式的最正常,如“^haha”,匹配以haha单词开头的行$美元符,用于模式的最右侧,如“haha$”,表示haha单词结尾的行^$组合符ÿ…...
开发必备的IDEA 插件!效率提升 50 倍!
日常开发中,面向百度编程的程序员,很多时候,你跟大佬级别的差距,可能不仅仅是知识面的差距,还有就是开发效率的差距。以下是我常用的几个IDEA插件,废话不多说,直接肝干货! 1. Codot…...
aws eks 集群访问ecr仓库拉取镜像的认证逻辑
本文主要讨论三个问题 ecr帮助程序在docker上如何配置eks集群访问ecr仓库的逻辑kubelet授权ecr的源码分析 ecr帮助程序 在docker环境下,可以通过在$HOME/.docker/config.json中指定凭证管理程序 docker login aws同样提供了证书助手,避免手动执行ecr认…...
Linux Socket Buffer介绍
一. 前言 Linux内核网络子系统的实现之所以灵活高效,主要是在于管理网络数据包的缓冲器-socket buffer设计得高效合理。在Linux网络子系统中,socket buffer是一个关键的数据结构,它代表一个数据包在内核中处理的整个生命周期。 二. Socket Bu…...
ACL与NAT
ACL---访问控制列表,是一种策略控制工具 功能:1.定义感兴趣流量(数据层面 ) 2.定义感兴趣路由(控制层面) ACL 条目表项组成: 编号规则:步数或者跳数默认值为5,…...
使用gdb来debug程序并查找Segmentation fault原因
GDB 调试前言GDB基础用法1.启动及退出调试2.设置参数3.执行程序4.流程控制5.设置断点6.输出信息7.查看栈帧8.info命令9.显示源码GDB调试coredump文件关注公众号【程序员DeRozan】,回复【1207】,免费获取计算机经典资料及现金红包 前言 在开发程序时&…...
vbs简单语法及简单案例
文章目录一、简单语法1、变量2、输入3、输出4、选择语句5、循环二、用记事本编译中文乱码问题三、制作一个简单vbs脚本表白一、简单语法 1、变量 语法: dim 变量名例: dim a,b a1 b2 msgbox ab运行: 2、输入 语法:InputBox(…...
学板绘课程学费一般多少钱
学板绘课程学费一般多少钱?培训机构的费用和师资、模式有关,价格贵不贵要结合相同类型的机构多多对比。因为好些平台做了很多的宣传广告,运营成本很高, 终羊毛出在羊身上,这样的机构知名度很高,但是性价比不…...
48.在ROS中实现local planner(1)- 实现一个可以用的模板
有了之前45.在ROS中实现global planner(1)- 实现一个可以用模板的global planner的经验, 现在再去创建一个local planner的包就容易多了 1. 创建包 创建 cd ~/pibot_ros/ros_ws/src # 这里可以使用自己的ros workspace catkin_create_pkg sample_loc…...
jenkins基础部署
一、jenkins是什么1.Jenkins的前身是Hudson,采用JAVA编写的持续集成开源工具。Hudson由Sun公司在2004年启动,第一个版本于2005年在java.net发布。2007年开始Hudson逐渐取代CruiseControl和其他的开源构建工具的江湖地位。在2008年的JavaOne大会上在开发者…...
Unity3D -知识点(1)
1.场景视图鼠标滚轮:场景放大缩小鼠标右键:场景左右平移场景编辑器中,能看到什么?网格,每一格大小为1unit,建模不同,规定不同,(对应屏幕上100个像素)世界坐标系y轴向上为正x轴向右为…...
深圳企业公司做网站/广州网站推广软件
实验模式: 这张图是我做想要做链路聚合,但是在链路聚合实验中,出现了点儿小小小的问题,介于篇幅太长,所以单独把问题抛出来; (在这里我们不讨论关于生成树的问题,因为默认为我都掌握…...
如何建设游戏平台网站/视频app推广
(一)初识LibSVM LibSVM是台湾 林智仁(Chih-Jen Lin) 教授2001年开发的一套支持向量机的库,这套库运算速度还是挺快的,可以很方便的对数据做分类或回归。由于libSVM程序小,运用灵活,输入参数少,并…...
做app推广上哪些网站吗/微信营销模式
Contens第四周1、爬虫的基本流程有:1.1、Request(请求)1.2、Response(响应):第五周:*知识拓展:*1、HTML(超文本标记语言)2、XHTML是更纯净更严格的HTML代码第…...
如何提高wordpress访问速度/谷歌搜索引擎363
转载原文在win环境下使用Git与GitHub建立关联or第二篇文章or图解说...
玉溪网站制作/上海百度公司地址
docker搭建npm仓库(verdaccio) 文章目录docker搭建npm仓库(verdaccio)拉去镜像设置存储目录创建目录结构配置文件内容运行拉去镜像 docker pull verdaccio/verdaccio 设置存储目录 mkdir -p ~/data/verdaccio/volume 创建目录…...
做视频网站视频/电脑优化工具
Linux指令篇:文件打印--lpd(转)名称: lpd使用权限: 所有使用者使用方式:lpd [-l] [#port]lpd 是一个常驻的打印机管理程序,它会根据 /etc/printcap 的内容来管理本地或远端的打印机。/etc/printcap 中定义的每一个打印机必须在 /v…...