旧的日期时间 API(java.util
日期时间类型及其格式类型SimpleDateFormat
等)已过时且容易出错。让我们首先了解如何SimpleDateFormat
错误地处理类似这样的字符串00/00/0000
,稍后我们将介绍现代日期时间 API 如何防止尝试处理这样的无效字符串。
以下演示将帮助我们轻松理解概念和问题:
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Locale;
public class Main {
public static void main(String[] args) throws ParseException {
SimpleDateFormat sdfInput = new SimpleDateFormat("dd/MM/yyyy", Locale.ENGLISH);
SimpleDateFormat sdfOutput = new SimpleDateFormat("dd MMMM yG", Locale.ENGLISH);
System.out.println(sdfOutput.format(sdfInput.parse("00/00/2021")));
}
}
输出:
30 November 2020AD
关于的一些事实SimpleDateFormat
:
SimpleDateFormat
处理月份,1
如January
.
- 它以循环方式处理年、月和日,这与处理方式
int
和long
处理方式非常相似。
为了完整起见,请查看以下语句的输出:
System.out.println(Integer.MAX_VALUE + 1); // -2147483648
System.out.println(Integer.MIN_VALUE - 1); // 2147483647
基于这个概念,这就是SimpleDateFormat
解析的方式00/00/2021
:
- 月,
00
:回到上个月,即 12 月,这也意味着年份将变为 2020。
- Day-of-month,
00
:回到上个月的最后一天,这也意味着 12 月将向后移动一个位置成为 11 月,11 月的最后一天是 30。
因此,输出将是 30 November 2020AD
。
测验:输入字符串的输出是-01/-01/2021
什么?
如果您的答案是:30 October 2020AD
,则您已正确理解。
下面给出了更多示例:
SimpleDateFormat sdfInput = new SimpleDateFormat("dd/MM/yyyy", Locale.ENGLISH);
SimpleDateFormat sdfOutput = new SimpleDateFormat("dd MMMM yG", Locale.ENGLISH);
System.out.println(sdfOutput.format(sdfInput.parse("00/00/0000"))); // 30 November 2BC
System.out.println(sdfOutput.format(sdfInput.parse("00/-01/2021"))); // 31 October 2020AD
System.out.println(sdfOutput.format(sdfInput.parse("00/13/2021"))); // 31 December 2021AD
System.out.println(sdfOutput.format(sdfInput.parse("00/14/2021"))); // 31 January 2022AD
为什么2BC
?
幸运的是1.没有第 0 年。在 1AD 之前,我们有 1BC。因此,我们将第 0 年称为 1BC。如果你回到一年前,那将是2BC。您想查看此答案以获得更多解释。
在使用旧的日期时间 API 时,您会遇到许多这样的惊喜。由于这些原因,建议完全停止使用它并切换到java.time
现代日期时间 API *。
java.time
让我们看看java.time
现代 API 如何防止尝试处理这样的无效字符串:
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.Locale;
public class Main {
public static void main(String[] args) {
LocalDate.parse("00/00/0000", DateTimeFormatter.ofPattern("dd/MM/uuuu", Locale.ENGLISH));
}
}
输出:
线程“主”java.time.format.DateTimeParseException 中的异常:无法解析文本“00/00/0000”:MonthOfYear 的值无效(有效值 1 - 12):0
从Trail: Date Time了解更多关于java.time
现代日期时间 API 2.的信息。
1. 否则,对于0年应该称为0AD还是0BC,它会打开一罐蠕虫。
2. 出于任何原因,如果您必须坚持使用 Java 6 或 Java 7,您可以使用ThreeTen-Backport,它将大部分java.time功能向后移植到 Java 6 和 7。如果您正在为 Android 项目工作并且您的 Android API 级别仍然不符合 Java-8,请检查Java 8+ APIs available through desugaring和How to use ThreeTenABP in Android Project。