Java Date Nuances的痛苦提醒
这些天,我不再需要使用java.util.Date了,但是最近选择这样做,这让我想起了使用与Java Date
关联的API的痛苦 。 在这篇文章中,我看了弃用的参数化Date构造函数的一些令人惊讶的API期望,该构造函数接受六个整数 。
在2016年,如果使用Java SE 8编写新代码,则Java开发人员很可能会使用Java 8的新Date / Time API,或者如果使用Java的版本,则可能会使用第三方Java日期/时间库(例如Joda-Time) 。 Java早于Java8。我选择最近在一个非常简单的基于Java的工具中使用Date
,我希望将它作为单个Java源代码文件交付(无需构建工具即可轻松编译)并且不依赖于外部的任何库。 Java SE。 此简单工具的目标部署环境是Java SE 7,因此不能选择Java 8 Date / Time API。
接受六个整数的Date
构造函数的缺点之一是这六个整数之间的区别,并确保按正确的顺序提供它们。 即使强制执行正确的命令,指定月份和年份也会有一些细微的意外。 正确实例化Date
对象的最简单方法也许是通过SimpleDateFormat 。 parse(String)或通过不建议使用的Date(long)构造函数接受从时期零开始的毫秒数。
我的第一个代码清单演示了一个用0小时,0分钟和0秒表示一个表示“ 2016年9月26日”的Date
实例。 此代码清单使用String通过SimpleDateFormat.parse(String)
实例化Date
实例。
final SimpleDateFormat formatter = new SimpleDateFormat(DEFAULT_FORMAT);
final Date controlDate = formatter.parse(CONTROL_DATE_TIME_STR);
printDate("Control Date/Time", controlDate);
运行上述命令时,打印结果将达到预期效果,并且输出日期与为Date
实例提供并分析的字符串匹配。
=============================================================
= Control Date/Time -> Mon Sep 26 00:00:00 MDT 2016
=============================================================
使用接受整数以表示Date
实例的不同“字段”的Date
构造函数可能会很诱人,但它们会带来前面提到的细微差别。
下一个代码清单显示了一种非常幼稚的方法来调用Date
构造函数,该构造函数接受六个以下列顺序表示这些字段的整数:年,月,日期,小时,分钟,秒。
// This will NOT be the intended Date of 26 September 2016
// with 0 hours, 0 minutes, and 0 seconds because both the
// "month" and "year" parameters are NOT appropriate.
final Date naiveDate = new Date(2016, 9, 26, 0, 0, 0);
printDate("new Date(2016, 9, 26, 0, 0, 0)", naiveDate);
运行上述代码的输出与前面显示的“控制”案例没有相同的月份(10月而不是9月)或年份(不是2016年)。
=============================================================
= new Date(2016, 9, 26, 0, 0, 0) -> Thu Oct 26 00:00:00 MDT 3916
=============================================================
月比我们预期的晚了一个月(10月而不是9月),因为month参数是从零开始的参数,一月由0表示,九月由8而不是9表示。这是处理以下问题的最简单方法之一从零开始的月份,对Date
构造函数的更可读的调用是为月份使用适当的java.util.Calendar字段。 下一个示例演示如何使用Calendar.SEPTEMBER进行此操作。
// This will NOT be the intended Date of 26 September 2016
// with 0 hours, 0 minutes, and 0 seconds because the
// "year" parameter is not correct.
final Date naiveDate = new Date(2016, Calendar.SEPTEMBER, 26, 0, 0, 0);
printDate("new Date(2016, Calendar.SEPTEMBER, 26, 0, 0, 0)", naiveDate);
刚刚列出的代码段修复了月份规范,但是年份仍然不正确,如下面显示的关联输出所示。
=============================================================
= new Date(2016, Calendar.SEPTEMBER, 26, 0, 0, 0) -> Tue Sep 26 00:00:00 MDT 3916
=============================================================
这一年仍然相距1900年(而不是2016年为3916年)。 这是由于决定将六整数Date
构造函数的第一个整数参数指定为年份,减去1900年。因此,提供“ 2016”作为第一个参数,将年份指定为2016 + 1900 = 3916。 ,要解决此问题,我们需要提供116(2016-1900)作为构造函数的第一个int
参数。 为了使普通人更容易理解这一点,我喜欢将其字面编码为2016-1900,如下面的代码清单所示。
final Date date = new Date(2016-1900, Calendar.SEPTEMBER, 26, 0, 0, 0);
printDate("new Date(2016-1900, Calendar.SEPTEMBER, 26, 0, 0, 0)", date);
在使用从零开始的月份并将预期年份表示为当前年份减去1900的情况下,正确地实例化Date
,如在下一个输出列表中所示。
=============================================================
= new Date(2016-1900, Calendar.SEPTEMBER, 26, 0, 0, 0) -> Mon Sep 26 00:00:00 MDT 2016
=============================================================
Date
的Javadoc文档确实描述了这些细微差别,但这提醒人们,最好使用清晰,可理解的API,不需要注释中描述的细微差别。 Date(int,int,int,int,int,int)构造函数的Javadoc确实宣告,年需要减去1900,并且月份由0到11之间的整数表示。它还描述了为什么此六整数构造函数已弃用 :“从JDK版本1.1开始,由Calendar.set(年+ 1900,月,日期,小时,分钟,秒)或GregorianCalendar(年+ 1900,月,日期,小时,分钟,秒)代替。”
不建议使用类似的六整数GregorianCalendar(int,int,int,int,int,int)构造函数,尽管它仍然期望从零开始的month参数,但是在证明时,它不希望一个参数将1900减去实际年份。年参数。 当使用适当的Calendar
month常量指定月份时,当可以在年份中传递2016年并且可以在月份中传递Calendar.SEPTEMBER
时,这将使API调用更具可读性。
我现在很少直接使用Date
类,以至于我忘记了它的细微差别,并且在极少数场合让我再次使用Date
时必须重新学习它们。 因此,我将这些有关Date
观察留给我自己。
- 如果使用Java 8+,请使用Java 8 Date / Time API。
- 如果使用Java之前的Java 8版本,请使用Joda-Time或其他改进的Java库。
- 如果无法使用Java 8或第三方库,请尽可能使用
Calendar
而不是Date
,尤其是用于实例化。 - 如果使用
Date
反正实例化Date
使用任一SimpleDateFormat.parse(String)
的方法或使用Date(long)
来实例化Date
因为历元零基于毫秒。 - 如果使用
Date
构造函数分别接受表示日期/时间分量的多个整数,请使用适当的Calendar
month字段使API调用更具可读性,并考虑编写一个简单的构造器来“包装”对六整数构造函数的调用。
通过使用他人的API,我们可以学到很多有关使API有用且易于学习的知识,以及使API较难学习的知识。 希望这些经验教训将有助于我们编写自己的API。 这篇文章的重点是Date(int, int, int, int, int, int)
构造函数,它提出了一些问题,这些问题导致API不够理想。 相同类型的多个参数可以轻松地乱序提供参数,而与提供年份和月份有关的“不自然”规则给客户端开发人员增加了负担,使他们不得不阅读Javadoc来理解这些不太明显的内容规则。
翻译自: https://www.javacodegeeks.com/2016/09/painful-reminder-java-date-nuances.html
Java Date Nuances的痛苦提醒相关推荐
- 学习java很痛苦_Java日期细微的痛苦提醒
学习java很痛苦 这些天我不再需要使用java.util.Date了,但是最近选择这样做,这让我想起了使用与Java Date关联的API的痛苦 . 在这篇文章中,我看了弃用的参数化Date构造函数 ...
- java str2date,java date类与string类实例代码分享
Date类用来指定日期和时间,其构造函数及常用方法如下: publicDate() 从当前时间构造日期时间对象. publicStringtoString() 转换成字符串. publiclongge ...
- Java Date Time 教程
原文链接 作者:Jakob Jenkov 译者:魏嘉鹏 目录 Java 8 Date Time API Java 7 Date Time API 当你初次尝试弄明白怎么去使用Java的date ti ...
- java 日期 解析_Java日期解析(Java DATE Parsing)
Java日期解析(Java DATE Parsing) 我有一个java.util.Date的愚蠢问题. 我有这一行代码,但我不明白为什么这个日期是用这种格式无法解析的. public class T ...
- java Date获取 年月日时分秒
转载自 java Date获取 年月日时分秒 package com.util;import java.text.DateFormat; import java.util.Calendar; im ...
- Java Date Time 教程-java.sql.Date
Java的java.sql.Date类在JDBC API中被使用.如果你需要在java.sql.PreparedStatement上设置日期或者从java.sql.ResultSet获取日期,你将会和 ...
- java date只保存年月日_java date 只保留年月日
java date 只保留年月日 [2021-01-30 22:42:23] 简介: php去除nbsp的方法:首先创建一个PHP代码示例文件:然后通过"preg_replace(&quo ...
- java date转换timestamp_Java Date转Timestamp
Java Date转Timestamp 1 Java Date转Timestamp的介绍 我们可以使用java.sql.Timestamp类的构造函数在Java中将Date转换为Timestamp. ...
- Java Date getTime()方法具有什么功能呢?
转自: Java Date getTime()方法具有什么功能呢? 下文笔者讲述java中Date实例对象之getTime()方法的功能简介说明,如下所示: Date getTime()方法功能简介说 ...
最新文章
- angularjs ngTable -Custom filter template-calendar
- Phalcon和YII的优点
- 理解矩阵 的一些评论
- 【ARM】ARM汇编程序设计(三) 循环结构
- linux进程cpu资源分配命令nice,renice,taskset
- 手机拍照显示_最值得购买的4款5G手机,每款都有一技之长,有你在用的吗?
- ASA 9.21 in Vmware Workstation 10
- 罚款200元的交通违法行为
- [react] 你对immutable有了解吗?它有什么作用?
- echarts源码:图标类插件开发
- 关于机器学习 Machine Learning中loss函数参数正则化的一点思考
- libcurl 发送邮件_libcurl smtp发送邮件附件大小限制问题
- 第二十二篇 定义函数的三种形式以及函数的返回值
- Hbuilder如何创建并运行Vue项目
- 【window操作系统下Github版本的回滚问题】
- 详解《云原生架构白皮书》,附下载链接
- 质疑江民电脑保护系统,涉嫌抄袭
- Thinkpad R60 驱动下载及安装方法 for windows XP
- windows 10 账号密码策略及规则
- c语言51单片机调节led亮度,51单片机中用PWM控制LED亮度调节
热门文章
- 最新后端架构师技术图谱
- Tomcat的web项目部署方式
- java中的break与continue用法
- 张老师讲Python~
- 20级、19级 | 一天一瞬间!【日更】
- ssh(Spring+Spring mvc+hibernate)——applicationContext.xml
- linux将光驱挂载到目录下,Linux操作系统下关于光驱的挂载
- java design按钮_DesignJava 设计模式,讲述 的各种 方便在项目中进行 框架结构 Develop 238万源代码下载- www.pudn.com...
- oxyen eclipse 启动 报错 se启动提示javaw.exe in your current PATH、No java virtual machine
- python3多线程第三方库_Python3 多线程