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观察留给我自己。

  1. 如果使用Java 8+,请使用Java 8 Date / Time API。
  2. 如果使用Java之前的Java 8版本,请使用Joda-Time或其他改进的Java库。
  3. 如果无法使用Java 8或第三方库,请尽可能使用Calendar而不是Date ,尤其是用于实例化。
  4. 如果使用Date反正实例化Date使用任一SimpleDateFormat.parse(String)的方法或使用Date(long)来实例化Date因为历元零基于毫秒。
  5. 如果使用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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/352343.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

python 与别的程序通信_《Python》进程之间的通信(IPC)、进程之间的数据共享、进程池...

一、进程间通信---队列和管道(multiprocess.Queue、multiprocess.Pipe) 进程间通信:IPC(inter-Process Communication) 1、队列 概念介绍: 创建共享的进程队列,Queue是多进程的安全的队列&#…

Matlab里evalin和assignin的用法

原文地址:Matlab里evalin和assignin的用法作者:了凡春秋assignin与evalin MATLAB通常的基本工作空间是base空间。MATLAB在程序运行过程中,将为每个函数分配它自己的函数工作空间(从基本空间中分割出的一块, 以函数…

判断一个程序员水平高低的标准?

a.结果导向 胜者为王,败者为寇。也可以理解为做过什么NB的项目,带来了多少价值。b.竞赛比武 在同一平台下,大家八仙过海各显神通。c.广度和深度 在平时工作或交谈中,逼格最高者被大家膜拜。d.熟练度 …

git编辑器选哪个_[Git]Git创建和修改代码库

有了上一篇的简易Git使用指南,接下来我们就可以创建自己的代码库了创建代码库1.把文件夹变成git文件夹git init 这样子就这里面的内容就可以git了2.把要git的文件放入暂存区 git有三个空间: Working Directory工作区,Staging Area暂存区,Repo…

Q 语言初学者系列:(1)开门篇

声明:本系列文章全部参考自官方教程,由于缺乏中文资料而且本人E文实在太菜,对于E文较好的朋友可以直接通过下面的链接访问官方网站提供的教程, 欢迎大家一起学习讨论。 hhttps://code.kx.com/trac/wiki/QforMortals2/contents 用户…

Java 将数据写入磁盘并读取磁盘上的文件

package test; import java.io.BufferedReader;import java.io.FileReader;import java.io.FileWriter;import java.util.ArrayList;import java.util.List; public class test { public static void main(String[] args) { //创建集合 List<String> listnew ArrayList&l…

simulink怎么生成vxworks的执行程序_Matlab/Simulink基础了解(五):基础Simulink模型搭建及Embedded基础使用...

为了方便大家阅读&#xff0c;从这章开始在章节名中添加该章节要讲的主要的东西。本章给大家讲一个最简单的Simulink模型&#xff1a;在处理应用逻辑时常常会判断车速信号来得到车是否静止&#xff0c;如果车已经跑起来了&#xff0c;很多功能都会被禁用&#xff0c;比如诊断&a…

Q 语言初学者系列:(2)基本数据类型

明&#xff1a;本系列文章全部参考自官方教程&#xff0c;由于缺乏中文资料而且本人E文实在太菜&#xff0c;对于E文较好的朋友可以直接通过下面的链接访问官方网站提供的教程&#xff0c; 欢迎大家一起学习讨论。 hhttps://code.kx.com/trac/wiki/QforMortals2/contents 用户名…

Megacli恢复RAID0磁盘数据

今天干了一件蠢事&#xff0c;距离删库跑路&#xff0c;只差一步。把一块RAID0的磁盘给拔掉了,拔掉之后发现这是一块数据盘&#xff0c;幸好这个数据库是一台备库。赶紧动手恢复&#xff0c;以下是恢复的过程。 首先把拔下来的盘插回去&#xff0c;通过Megacli查看状态是这样的…

内核堆栈 用户堆栈_堆栈痕迹从何而来?

内核堆栈 用户堆栈我相信&#xff0c;阅读和理解堆栈跟踪是每个程序员都必须具备的一项基本技能&#xff0c;以便有效地解决每种JVM语言的问题&#xff08;另请参阅&#xff1a; 过滤日志中无关的堆栈跟踪行和首先记录引起根的异常 &#xff09;。 那么我们可以从一个小测验开始…

Java中使用log4j记录日志

在项目开发中&#xff0c;记录错误日志是一个很有必要功能。一是方便调试&#xff1b;二是便于发现系统运行过程中的错误&#xff1b;三是存储业务数据&#xff0c;便于后期分析&#xff1b; 在java中&#xff0c;记录日志&#xff0c;有很多种方式。 比如&#xff0c;自己实…

python如何输出两列数据_如何用python将一列数据分为两列?

引用来自“Ashkandi”的评论[{date: c[:10], time: c[11:]} for c in Col] 引用来自“vx2008”的评论 谢谢回复&#xff0c;这行代码执行完了以后&#xff0c;日期和时间都村到哪里了呢&#xff1f; 我是了一下&#xff0c;调用date&#xff0c;提示没有定义date&#xff0c;请…

Q 语言初学者系列:(3)Lists 初级

声明&#xff1a;本系列文章全部参考自官方教程&#xff0c;由于缺乏中文资料而且本人E文实在太菜&#xff0c;对于E文较好的朋友可以直接通过下面的链接访问官方网站提供的教程&#xff0c; 欢迎大家一起学习讨论。 hhttps://code.kx.com/trac/wiki/QforMortals2/contents 用户…

数据库图书管理建表与修改表

根据调研选定实体及相应属性画出E-R图 ​ 2、将E-R模型转换为对应关系模型&#xff0c;并指出主码和外码 图书book&#xff08;书号&#xff0c;类别&#xff0c;出版社&#xff0c;作者&#xff0c;书名&#xff0c;定价&#xff0c;备注&#xff09;&#xff1b; 读者reade…

如何指南:Apache Drill入门

Apache Drill是一种引擎&#xff0c;可以连接到许多不同的数据源&#xff0c;并为它们提供SQL接口。 它不仅是想跳入任何复杂事物的SQL接口&#xff0c;而且是一个功能强大的接口&#xff0c; 其中包括对许多内置函数和窗口函数的支持。 尽管它可以连接到您仍然可以使用SQL查询…

python3编程入门_在类Unix系统上开始Python3编程入门

>>> s Hello >>> x len(s) >>> print("The length of %s is %d" % (s,x)) The length of Hello is 5 看看《Python基础编程》中对格式化输出的总结&#xff1a; (1). %字符&#xff1a;标记转换说明符的开始 (2). 转换标志&#xff1a;-…

visual studio 调试时提示 已加载“C:\Windows\SysWOW64\ntdll.dll”。无法查找或打开 PDB 文件。

问题描述 “Win32Project3.exe”(Win32): 已加载“D:\software\VS2013\VS2013 文档\Win32Project3\Debug\Win32Project3.exe”。已加载符号。 “Win32Project3.exe”(Win32): 已加载“C:\Windows\SysWOW64\ntdll.dll”。无法查找或打开 PDB 文件。 “Win32Project3.exe”(Wi…

matlab的一个疑问?

把逻辑值放入一个已知矩阵&#xff0c;为啥结果是&#xff1a;真就取矩阵的值&#xff0c;假就不取值&#xff1f; K>> aaaarandi(10,10,2) aaaa 6 3 10 4 6 7 5 2 6 3 8 2 1 2 9 4 2 9 5 5 K>> aaaa9 ans 102 logical array 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 …

如何使用log4j记录日志

【1】从零开始 a). 新建Java Project>>新建package>>新建java类&#xff1b; b). import jar包&#xff08;一个就够&#xff09;&#xff0c;这里我用的是log4j-1.2.14.jar&#xff0c; c). 新建log4j.properties&#xff0c;置于project根目录下&#xff1b; log…

python验证码 识别代码不准_谈谈Python进行验证码识别的一些想法

用python加“验证码”为关键词在baidu里搜一下&#xff0c;可以找到很多关于验证码识别的文章。我大体看了一下&#xff0c;主要方法有几类&#xff1a;一类是通过对图片进行处理&#xff0c;然后利用字库特征匹配的方法&#xff0c;一类是图片处理后建立字符对应字典&#xff…