我应该使用啥 Java DateTime 类?

Posted

技术标签:

【中文标题】我应该使用啥 Java DateTime 类?【英文标题】:What Java DateTime class should I use?我应该使用什么 Java DateTime 类? 【发布时间】:2019-06-19 10:08:53 【问题描述】:

我们有一个用于生成报告的库。它从数据文件(SQL、XML、JSON 等)中读取数据,然后可以在用户编写的公式中修改日期时间,然后按照报告输出指定的格式对其进行格式化。

方程中的用法可以是添加时间跨度,获取部分值,如“if date.month == 2”,以及几乎all the datetime macros in Excel。

因为数据可以是 JSON(或没有架构的 XML),所以日期时间可以是“2019-01-25”、“2019-01-25T14:32:23”、“2019-01-25T14:32:23.12345” "、"2019-01-25T14:32:23Z" 或 "2019-01-25T14:32:23Z-0500"(最后两个也可以有 ".12345")。

如果没有时区偏移,我们假设日期时间为 UTC。虽然这应该是真的,但通常不是,它是当地时间,但它的使用方式并不重要。因此,除非指定时区偏移量,否则将其设为 UTC 是可行的(到目前为止,我们一直使用 Date)。

第一个问题 - 我应该使用什么类来保存这个值?根据我的阅读,我认为 ZonedDateTime,但也许是 Instant?

第二个问题 - 当我必须执行诸如将日期时间增加 3 天之类的操作时,我应该使用什么类来表示时间跨度?

第三个问题 - 是否有一些解析器可以解析我上面列出的所有不同字符串?还是我需要调用 String.contains() 来确定格式,然后根据它做一个明确的模式?如果是这样,使用什么类?

【问题讨论】:

您的示例中没有时区,只有时区偏移量,因此OffsetDateTimeZonedDateTime 更有意义。 你考虑过Joda Time吗?这是我最喜欢的时间工作课程。如果你能实现它,如果你愿意,我可以回答它。 @S.Czop 我们使用的是 Java 1.8,所以我们将使用 java.time。 @S.Czop 为什么要将外部库用于标准运行时中现已涵盖的内容(除非您必须使用 Java 7)。 回复。你的第一个问题。看看你的最后一个例子2019-01-25T14:32:23Z-0500:你需要知道 5hrs 的偏移量吗?或者您是否可以只在 UTC 中保持相同的时刻,即2019-01-25T19:32:23Z?或者您更喜欢2019-01-25T14:32:23Z(不是同一时刻,而是同一本地时间)? 【参考方案1】:

第三个问题 - 是否有一些解析器可以解析我上面列出的所有不同字符串?还是我需要调用 String.contains() 来确定格式,然后根据它做一个明确的模式?如果是这样,使用什么类?

我可能大错特错,但是您可以使用DateTimeFormatter 与模式上的可选部分和parseBest 方法:

List<String> dates = List.of(
    "2019-01-25", 
    "2019-01-25T14:32:23",
    "2019-01-25T14:32:23.12345", 
    "2019-01-25T14:32:23Z", 
    "2019-01-25T14:32:23Z-0500"
);

DateTimeFormatter formatter = DateTimeFormatter.ofPattern(
   "yyyy-MM-dd['T'[HH:mm:ss][.SSSSS]][z][x]"
); // all the possible combinations

dates.forEach( date -> 
            TemporalAccessor accessor = formatter.parseBest(date,                       
       OffsetDateTime::from, // going from most specific date
       LocalDateTime::from, 
       LocalDate::from); // to the less specific 

            System.out.println( accessor.getClass() + " " + accessor);
        

);

// output for this is 
class java.time.LocalDate 2019-01-25
class java.time.LocalDateTime 2019-01-25T14:32:23
class java.time.LocalDateTime 2019-01-25T14:32:23.123450
class java.time.OffsetDateTime 2019-01-25T14:32:23Z
class java.time.OffsetDateTime 2019-01-25T14:32:23-05:00

【讨论】:

【参考方案2】:

关于第二个问题:是的,Java JDK 中有一个“时间跨度”类。

对于未附加到时间线的时间跨度:

Period

表示天数/周数/月数/年数。可用于日期计算,自动计算夏令时 (DST)。

例如,要从给定日期减去 3 天,您可以这样做

ZonedDateTime threeDaysAgo = Period.ofDays(-3).addTo(ZonedDateTime.now());

Duration

类似于Period,但以天为单位(以 24 小时为单位,而不是日历日)、小时、分钟、秒和小数秒。

ChronoUnit

如果您需要进行更广泛的计算(例如包括小时/分钟/秒等)还有ChronoUnit 枚举:

ZonedDateTime threeHoursAgo = ChronoUnit.HOURS.addTo(ZonedDateTime.now(), -3);

【讨论】:

是的,知道 - 从不包含开始和结束日期的意义上说,这并不是一个真正的时间跨度 - 不确定这是否是一个问题。而且也没有小时/分钟/秒精度。 你的意思是是和不是。并且无论该术语的含义如何,这正是 OP 所要求的 - 诸如“3 天”之类的容器不在特定日期之间。 编辑答案以包含更广泛的时间单位的解决方案 对于附加到时间线的时间跨度,请参阅 ThreeTen-Extra 库中的 IntervalLocalDateRange 类。

以上是关于我应该使用啥 Java DateTime 类?的主要内容,如果未能解决你的问题,请参考以下文章

mysql的datetime对应java的啥类型,我用date读不出来

java的类Date和Timestamp啥区别

DateTime 和 DateTime2 之间的区别 [重复]

数据库字段类型timeStamp应对应.net实体类的啥类型???

实体类里面DateTime?带问号是啥意思

我应该在 netsh.exe 中使用啥 appid?