题
每次我需要在 Java 中使用日期和/或时间戳时,我总是觉得自己做错了什么,并花费无数时间试图找到更好的方法来使用 API,而无需编写自己的日期和时间实用程序类。这是我刚刚遇到的一些恼人的事情:
从 0 开始的月份。我意识到最佳实践是使用 Calendar.SEPTEMBER 而不是 8,但令人烦恼的是 8 代表 9 月而不是 8 月。
获取没有时间戳的日期。我总是需要将日期的时间戳部分清零的实用程序。
我知道过去还遇到过其他问题,但记不起来了。请随意在您的回复中添加更多内容。
所以,我的问题是...您使用哪些第三方 API 来简化 Java 对日期和时间操作的使用(如果有)?关于使用的任何想法 乔达?有人仔细研究过 JSR-310 日期和时间 API 吗?
其他提示
java.time
Java 8 及更高版本现在包括 java.time 框架。灵感来自 乔达时间, , 被定义为 JSR 310, ,扩展为 三十额外 项目。看 教程.
该框架取代了旧的 java.util.Date/.Calendar 类。转换方法允许您来回转换以使用尚未更新的 java.time 类型的旧代码。
核心类是:
Instant
时间轴上的某个时刻,始终在 世界标准时间.ZoneId
一个时区。子类ZoneOffset
包括 UTC 常量.ZonedDateTime
=Instant
+ZoneId
表示时间轴上调整为特定时区的时刻。
该框架解决了您列出的几个问题。
从 0 开始的月份
java.time 中的月份数字为 1-12。
更好的是,一个 Enum
(Month
) 提供一年中每个月的对象实例。所以你不需要依赖代码中的“神奇”数字,比如 9
或者 10
.
if ( theMonth.equals ( Month.OCTOBER ) ) { …
此外,该枚举还包括一些方便的实用方法,例如获取月份的本地化名称。
如果还不熟悉 Java 枚举,请阅读 教程 并学习。它们非常方便且功能强大。
没有时间的约会
这 LocalDate
类表示仅日期值,没有时间,没有时区。
LocalDate localDate = LocalDate.parse( "2015-01-02" );
请注意,确定日期需要时区。巴黎的新一天比蒙特利尔的黎明更早,而蒙特利尔的天气仍然是“昨天”。这 ZoneId
类代表一个时区。
LocalDate today = LocalDate.now( ZoneId.of( "America/Montreal" ) );
同样,有一个 LocalTime
尚未与日期或时区绑定的时间类。
关于 java.time
这 java.time 框架内置于 Java 8 及更高版本中。这些课程取代了麻烦的旧课程 遗产 日期时间类,例如 java.util.Date
, Calendar
, & SimpleDateFormat
.
这 乔达时间 项目,现在在 维护模式, ,建议迁移到 java.time 类。
要了解更多信息,请参阅 甲骨文教程. 。并在 Stack Overflow 上搜索许多示例和解释。规格为 JSR 310.
从哪里获取 java.time 类?
- Java SE 8, Java SE 9, , 然后
- 内置。
- 具有捆绑实现的标准 Java API 的一部分。
- Java 9 添加了一些小功能和修复。
- Java SE 6 和 Java SE 7
- 许多 java.time 功能都向后移植到 Java 6 和 7 三十后端口.
- 安卓
- 这 三十ABP 项目适应 三十后端口 (如上所述)专门针对 Android。
- 看 如何使用 ThreeTenABP....
这 三十额外 项目通过附加类扩展了 java.time。该项目是 java.time 未来可能添加的内容的试验场。您可能会在这里找到一些有用的类,例如 Interval
, YearWeek
, YearQuarter
, , 和 更多的.
Apache Commons Lang 项目有一个 DateUtils
执行有用的日期操作的类。
我用 DateUtils.truncate()
很多,这将为您将日期的部分“清零”(如果您希望日期对象代表日期而不包含任何时间信息,这会很有帮助)。每种方法都适用 Date
和 Calendar
对象也。
我已经专门使用 Joda 三年了,并且肯定会推荐它 - 它的整个区域都覆盖了一个“按其说明操作”的界面。
当你开始时,Joda 可能看起来很复杂,因为它有周期、持续时间和间隔的概念,看起来有点相似,但你可以简单地通过替换来开始 org.joda.time.DateTime
(或者 org.joda.time.DateMidnight
) 为了 java.util.Date
在您的代码中,并在了解其他领域之前坚持使用这些类包含的许多有用的方法。
我随时随地都在使用 GregorianCalendar。简单的 java.util.Date 太复杂了,是的。
所以,我的建议是 - 使用 GC,它很简单
在 JavaScript 中也是一样的。当某人认为让 2008 表示 2008 年、31 表示该月的第 31 天、以及 - 这是最好的部分 - 11 表示第 12 个月是个好主意时,他们一定是在吸烟。
另一方面,他们三分之二都答对了。
Java 总是让我着迷的是日期时间库。我从未使用过 Joda,只是简单地看了一下,看起来它是一个非常好的实现,如果我正确理解 JSR-130,它会从 Joda 获取知识并最终将其包含在 JavaSE 中。
在过去的项目中,我经常包装 Java 日期时间对象,这本身就是一项艰巨的任务。然后使用包装器进行日期操作。
日期 API 的设计非常困难,特别是如果它们必须处理本地化的话。尝试自己动手,看看,至少值得做一次。Joda 能够做得这么好,这对它的开发者来说是真正的荣誉。为了回答你的问题,我只听说过关于这个库的好消息,尽管我自己从未使用过它。
许多程序员开始使用 Date,它有许多已弃用的重载构造函数(使其难以使用),但是一旦您了解了 GregorianCalendar,它就会变得更容易管理。这里的例子非常有帮助:
http://java.sun.com/j2se/1.4.2/docs/api/java/util/GregorianCalendar.html
编写自己的日期 API 非常简单,它位于原始 Java 类、日期和日历之上。基本上,日期和日历都受到这样一个事实的困扰:它们试图将两个概念塞进一个类中:
- 日期(即年月日)
- 即时(即当前时间(毫秒)
当您理解这一点时,它将彻底改变您在代码中处理类似日期的概念的方式。事情会变得更简单、更清晰、更好。从各个意义上来说!
对我来说,Joda 过于复杂,至少对于绝大多数目的来说是这样,而且我特别不喜欢它们违背标准 Java 表单这一事实,一个例子是它们如何解析和格式化日期。Stephen Colebourne,JODA 背后的人,是 JSR-310 的规范负责人,恕我直言,它也遇到了同样的问题(我在过去几年中一直关注并为讨论做出了贡献)。
自己做;这很容易。只需填写以下类别:MyDate(包装年-月-日)、Month(枚举)、TimeOfDay(小时-分钟-秒-毫秒)、DayOfWeek(枚举)、Instant(包装长整型)。在即时和日期之间转换时始终考虑时区。
如果这看起来令人畏惧,您可以在幕后使用 Calendar 和 SimpleDateFormat。您将在一天内完成此操作并且永远不会后悔。