java8的时间和`Date`的对比 java 日期和时间
bigegpt 2024-10-25 10:24 5 浏览
java8的时间和Date的对比
java8提供了新的时间接口。相对Date,Calendar,个人感觉最大的好处是对时间操作的学习成本很低,比Calendar低。
1. LocalDate,LocalTime,LocalDateTime
LocalDate 代表日期,LocalTime表示时刻,类似11:23这样的时刻。 LocalDateTime就是前面2个的结合,这个可以从java.time.LocalDateTime#toString的代码看出一二:
@Override public String toString() { return date.toString() + 'T' + time.toString(); }
date,time 在java.time.LocalDateTime中
/** * The date part. */ private final LocalDate date; /** * The time part. */ private final LocalTime time;
实际使用中,计算日期就用LocalDate,计算日期加时刻用LocalDateTime,如果只有时刻就是LocalTime(感觉在说废话)
这三个的用法基本上一样,通过方法名就知道用法那种
1.1 获取当前时间的对象
LocalDateTime localDateTime = LocalDateTime.now(); Date date = new Date();
localDateTime相比Date更像是一个工具类,就是为了时间操作使用。其构造方法是私有的。
1.2 从字符串中解析
字符串 2019-01-11 解析成时间对象
String str = "2019-01-11"; DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd"); LocalDate localDate = LocalDate.parse(str, formatter); SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd"); try { Date date = simpleDateFormat.parse(str); } catch (ParseException e) { e.printStackTrace(); }
DateTimeFormatter的包路径是java.time.format和LocalDate一样在java.time下面,而SimpleDateFormat和Date是不同的。所以当判断引入路径的时候更容易判断。
当解析失败的时候,两个异常的抛出不一样,DateTimeFormatter抛出的是DateTimeParseException,继承自RuntimeException,而ParseException明显继承的是Exception。
个人感觉这个思路是,前者如果抛出异常那就是编程上错误,而后者则是的程序代码的不稳定性。我更倾向于第一种的异常设计,应该加强对入参的检测判断,而不是通过捕获异常去处理入参的错误。(类似NumberFormatException)
1.3 LocalDate比Date更强的初始化时间
Date 设置某个日期,基本上3个方式,时间戳/Calendar/字符串解析。相对的LocalDate就简单了很多
LocalDate.of(2019,1,12);
其他的也一样
1.4 时间戳的转换
时间戳和时区关系的参考 时间转换代码参考
在这里时间戳的转换不如Date直接。主要因为LocalDate本身是没有时区的。
- 时间戳传LocalDateTime
long timestamp = System.currentTimeMillis(); Instant instant = Instant.ofEpochMilli(timestamp); LocalDateTime.ofInstant(instant, ZoneId.systemDefault());
- LocalDateTime转时间戳
LocalDateTime dateTime = LocalDateTime.now(); dateTime.toInstant(ZoneOffset.ofHours(8)).toEpochMilli(); dateTime.toInstant(ZoneOffset.of("+08:00")).toEpochMilli(); dateTime.atZone(ZoneId.systemDefault()).toInstant().toEpochMilli();
关于时区的计算也很简单,就是相差几个小时就加上多少秒
有些时区计算的时候,不妨自己加时间也一样,elasticsearch+logstash设置@timestamp时间是默认UTC Z的时间,和咱们差了8个小时
LocalDateTime.parse(json.getString("@timestamp"), DateTimeFormatter.ISO_DATE_TIME).plusHours(8L)
1.5 和Date互转
import java.time.Instant; import java.util.Date; public class Main { public static void main(String[] args) { Date dt = new Date(); System.out.println("Date: " + dt); Instant in = dt.toInstant(); System.out.println("Instant: " + in); Date dt2 = Date.from(in); System.out.println("Date: " + dt2); } }
Instant 和 LocalDate或LocalDateTime 就不赘述了...
代码来自 Java 日期时间传统互操作性
1.6 更好的理解和操作方式
Date、Calendar的操作,例如设置月份,day of week 都有些让人迷惑,例如1月的定义是0,周一是0。1号好像也是0吧(我真没咋用过这东西,现用现百度...
LocalDate感觉好多了。例如DayOfWeek是枚举类型。使用枚举就不会理解错了吧
很多日期和时间操作,无非就是加减时间和比较.
使用‘加’的示例:
不用再去使用一个不熟悉的Calendar去操作了(Calendar提供的接口都是啥玩意,get,set的)
Calendar cal = Calendar.getInstance(); cal.set(Calendar.MONTH, cal.get(Calendar.MONTH) + 1)
2. 线程安全性比较
LocalDate...系列是线程安全的
额..每一个字段都用了final关键字了,都变不了... 所以进行操作后都是返回新的copy对象
至于说Date线程不安全,get,set的肯定在多线程的时候容易出现问题,不过set方法已经都@Deprecated废弃了。当然不是因为线程安全问题废弃的,是因为有了更好的替代
Calendar.set(Calendar.DAY_OF_MONTH, int date)
不过感觉还是不如这个更清晰明了
LocalDate.of(2019,1,12);
2.1 SimpleDateFormat的线程安全性
参考:深入理解Java:SimpleDateFormat安全的时间格式化
在一定负载情况下,SimpleDateFormat会出问题的。简单测试一下
package open.note; import java.text.SimpleDateFormat; import java.time.LocalDateTime; import java.time.format.DateTimeFormatter; import java.util.Date; import java.util.concurrent.CountDownLatch; import java.util.function.Consumer; public class UnSafeTest { private static String time = "2019-01-11 11:11:11"; private static long timestamp = 1547176271000L; private static LocalDateTime dateTime = LocalDateTime.of(2019,1,11,11,11,11); private static SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); private static DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"); public static void main(String[] args) { dateFormatTest((obj)->{ try { Date date = dateFormat.parse(time); if (date.getTime() != timestamp){ System.out.println(date); } } catch (Exception e) { System.out.println(e.getMessage()); } }); System.out.println("---------------"); dateFormatTest((obj)->{ try { LocalDateTime dateTime = LocalDateTime.parse(time,formatter); if (!dateTime.isEqual(UnSafeTest.dateTime)){ System.out.println(dateTime); } } catch (Exception e) { System.out.println(e.getMessage()); } }); } private static void dateFormatTest(Consumer runnable){ CountDownLatch countDownLatch = new CountDownLatch(1000); for (int i = 0; i < 1000; i++) { new Thread(()->{ runnable.accept(null); countDownLatch.countDown(); }).start(); } try { countDownLatch.await(); } catch (InterruptedException e) { e.printStackTrace(); } } }
输出结果
multiple points multiple points empty String Sat Jan 11 11:11:11 CST 111 Fri Jan 04 11:11:11 CST 2019 For input string: "" Mon Dec 31 11:11:11 CST 2018 Mon Dec 31 11:11:11 CST 2018 For input string: "" Tue Jan 11 11:11:11 CST 42101 ---------------
测试过程中,SimpleDateFormat 1000个线程里,有5次,时间解析错了,5次异常了(时间错了,比抛出异常还可怕)
DateTimeFormatter只是对比参考一下,未出现异常(人家已经声明是线程安全了...)
当然SimpleDateFormat线程不安全应该人尽皆知的,但依然有不安全的使用,但每次使用都new一个实例,当负载大的时候也不好。所以一个线程一个SimpleDateFormat实例应该可以的。
最后
java8 对时间操作的类还有很多 到java.time包下去看看,以后总会用得到的地方。
Instant:时间戳
Duration:持续时间,时间差
LocalDate:只包含日期,比如:2016-10-20
LocalTime:只包含时间,比如:23:12:10
LocalDateTime:包含日期和时间,比如:2016-10-20 23:14:21
Period:时间段
ZoneOffset:时区偏移量,比如:+8:00
ZonedDateTime:带时区的时间
Clock:时钟,比如获取目前美国纽约的时间
作者:后端工程师-北风刮的不认真了;? 著作权归作者所有,如有侵权请联系删除.
相关推荐
- 得物可观测平台架构升级:基于GreptimeDB的全新监控体系实践
-
一、摘要在前端可观测分析场景中,需要实时观测并处理多地、多环境的运行情况,以保障Web应用和移动端的可用性与性能。传统方案往往依赖代理Agent→消息队列→流计算引擎→OLAP存储...
- warm-flow新春版:网关直连和流程图重构
-
本期主要解决了网关直连和流程图重构,可以自此之后可支持各种复杂的网关混合、多网关直连使用。-新增Ruoyi-Vue-Plus优秀开源集成案例更新日志[feat]导入、导出和保存等新增json格式支持...
- 扣子空间体验报告
-
在数字化时代,智能工具的应用正不断拓展到我们工作和生活的各个角落。从任务规划到项目执行,再到任务管理,作者深入探讨了这款工具在不同场景下的表现和潜力。通过具体的应用实例,文章展示了扣子空间如何帮助用户...
- spider-flow:开源的可视化方式定义爬虫方案
-
spider-flow简介spider-flow是一个爬虫平台,以可视化推拽方式定义爬取流程,无需代码即可实现一个爬虫服务。spider-flow特性支持css选择器、正则提取支持JSON/XML格式...
- solon-flow 你好世界!
-
solon-flow是一个基础级的流处理引擎(可用于业务规则、决策处理、计算编排、流程审批等......)。提供有“开放式”驱动定制支持,像jdbc有mysql或pgsql等驱动,可...
- 新一代开源爬虫平台:SpiderFlow
-
SpiderFlow:新一代爬虫平台,以图形化方式定义爬虫流程,不写代码即可完成爬虫。-精选真开源,释放新价值。概览Spider-Flow是一个开源的、面向所有用户的Web端爬虫构建平台,它使用Ja...
- 通过 SQL 训练机器学习模型的引擎
-
关注薪资待遇的同学应该知道,机器学习相关的岗位工资普遍偏高啊。同时随着各种通用机器学习框架的出现,机器学习的门槛也在逐渐降低,训练一个简单的机器学习模型变得不那么难。但是不得不承认对于一些数据相关的工...
- 鼠须管输入法rime for Mac
-
鼠须管输入法forMac是一款十分新颖的跨平台输入法软件,全名是中州韵输入法引擎,鼠须管输入法mac版不仅仅是一个输入法,而是一个输入法算法框架。Rime的基础架构十分精良,一套算法支持了拼音、...
- Go语言 1.20 版本正式发布:新版详细介绍
-
Go1.20简介最新的Go版本1.20在Go1.19发布六个月后发布。它的大部分更改都在工具链、运行时和库的实现中。一如既往,该版本保持了Go1的兼容性承诺。我们期望几乎所...
- iOS 10平台SpriteKit新特性之Tile Maps(上)
-
简介苹果公司在WWDC2016大会上向人们展示了一大批新的好东西。其中之一就是SpriteKitTileEditor。这款工具易于上手,而且看起来速度特别快。在本教程中,你将了解关于TileE...
- 程序员简历例句—范例Java、Python、C++模板
-
个人简介通用简介:有良好的代码风格,通过添加注释提高代码可读性,注重代码质量,研读过XXX,XXX等多个开源项目源码从而学习增强代码的健壮性与扩展性。具备良好的代码编程习惯及文档编写能力,参与多个高...
- Telerik UI for iOS Q3 2015正式发布
-
近日,TelerikUIforiOS正式发布了Q32015。新版本新增对XCode7、Swift2.0和iOS9的支持,同时还新增了对数轴、不连续的日期时间轴等;改进TKDataPoin...
- ios使用ijkplayer+nginx进行视频直播
-
上两节,我们讲到使用nginx和ngixn的rtmp模块搭建直播的服务器,接着我们讲解了在Android使用ijkplayer来作为我们的视频直播播放器,整个过程中,需要注意的就是ijlplayer编...
- IOS技术分享|iOS快速生成开发文档(一)
-
前言对于开发人员而言,文档的作用不言而喻。文档不仅可以提高软件开发效率,还能便于以后的软件开发、使用和维护。本文主要讲述Objective-C快速生成开发文档工具appledoc。简介apple...
- macOS下配置VS Code C++开发环境
-
本文介绍在苹果macOS操作系统下,配置VisualStudioCode的C/C++开发环境的过程,本环境使用Clang/LLVM编译器和调试器。一、前置条件本文默认前置条件是,您的开发设备已...
- 一周热门
- 最近发表
- 标签列表
-
- mybatiscollection (79)
- mqtt服务器 (88)
- keyerror (78)
- c#map (65)
- resize函数 (64)
- xftp6 (83)
- bt搜索 (75)
- c#var (76)
- mybatis大于等于 (64)
- xcode-select (66)
- httperror403.14-forbidden (63)
- logstashinput (65)
- hadoop端口 (65)
- dockernetworkconnect (63)
- esxi7 (63)
- vue阻止冒泡 (67)
- c#for循环 (63)
- oracle时间戳转换日期 (64)
- jquery跨域 (68)
- php写入文件 (73)
- java大写转小写 (63)
- kafkatools (66)
- mysql导出数据库 (66)
- jquery鼠标移入移出 (71)
- 取小数点后两位的函数 (73)