学习java很痛苦_Java日期细微的痛苦提醒

学习java很痛苦

这些天我不再需要使用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对象的最简单方法也许是通过SimpleDateFormatparse(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

学习java很痛苦

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值