使用 Joda 的不同时区的日期之间的天数

Posted

技术标签:

【中文标题】使用 Joda 的不同时区的日期之间的天数【英文标题】:Days between to date of different timezone using Joda 【发布时间】:2021-09-24 04:14:36 【问题描述】:

我有一个格式为“2021-07-15T05:00:00.527+05:30”的输入日期字符串 我想要与当前时间的日期差异(当前时间为 UTC)。

DateTime inputDateTime = new DateTime(input, DateTimeZone.UTC);
DateTime now = new DateTime(DateTimeZone.UTC);
Days.daysBetween(now, inputDateTime).getDays();

如果我将输入日期转换为 UTC,这会产生错误的结果。 有没有办法从输入日期获取偏移量并将其添加到当前 UTC 日期,然后比较日期?

编辑:

抱歉,问题措辞有误。我试图找出给定输入日期是今天还是前一天还是明天是相对于 utc 时区的偏移量。

在服务器时间为 2021-07-14T23:00:00.527Z 时,上述输入日期应取为今天(即 0)。 如果在服务器时间是 2021-07-14T13:00:00.527Z,对于相同的输入数据,它应该是明天(即 1)。

编辑2:

我确实尝试将两者都转换为 localDate, Days.daysBetween(now.toLocalDate(), inputDateTime.toLocalDate()).getDays() 但是当 UTC 时间在前一个日期 2021-07-14T23:00:00.527Z 和给定日期 2021-07-15T05:00:00.527+05:30 时,产生 1 但我希望它是 0 `

【问题讨论】:

您期望得到哪个结果,却给出了哪个错误结果? 我无法复制。刚才运行您的代码时,我得到0,在我看来这是正确的。 抱歉,问题的措辞似乎有误。我正在尝试检查 isToday 或 isTomorrow 是否有给定的输入字符串。我认为我不应该为此使用 Days.daysBetween。 您需要将DateTime 转换为LocalDate。找到今天的LocalDate UTC 并进行比较。并在今天加上 1 天以获得明天并再次比较。 感谢@OleV.V。看起来我在将给定日期转换为本地日期时犯了一个错误。对 Edit2 的任何建议都会有帮助。 【参考方案1】:

我正在尝试检查 isToday 或 isTomorrow 是否有给定的输入字符串。

我建议:

    String input = "2021-07-19T05:00:00.527+05:30";
    
    DateTime inputDateTime = new DateTime(input, DateTimeZone.UTC);
    LocalDate inputDate = inputDateTime.toLocalDate();
    LocalDate today = LocalDate.now(DateTimeZone.UTC);
    boolean isToday = inputDate.equals(today);
    LocalDate tomorrow = today.plusDays(1);
    boolean isTomorrow = inputDate.equals(tomorrow);
    
    System.out.format("Is today? + %b; is tomorrow? %b.%n", isToday, isTomorrow);

刚刚运行时的输出 - 7 月 18 日大约 18:32 UTC:

是今天吗? + 真的;是明天吗?假的。

我以输入字符串2021-07-19T05:00:00.527+05:30 为例。它等于 2021-07-18T23:30:00.527Z (UTC)。所以我今天和明天比较的日期是 2021-07-18。

java.time

来自 Joda-Time 主页的额外引述:

... 请注意,从 Java SE 8 开始,用户被要求迁移到 java.time (JSR-310) - JDK 的核心部分,它取代了这个 项目。

(Joda-Time - Home;粗体字为原创)

对应的java.time代码类似。只有从字符串到日期和时间的转换在文本上有所不同。它明确表明正在进行偏移转换,我认为这是一个优势:

    OffsetDateTime inputDateTime = OffsetDateTime.parse(input)
            .withOffsetSameInstant(ZoneOffset.UTC);
    LocalDate inputDate = inputDateTime.toLocalDate();
    LocalDate today = LocalDate.now(ZoneOffset.UTC);
    boolean isToday = inputDate.equals(today);
    LocalDate tomorrow = today.plusDays(1);
    boolean isTomorrow = inputDate.equals(tomorrow);
Joda-Time - Home Oracle tutorial: Date Time 解释如何使用 java.time。 Java Specification Request (JSR) 310,其中首次描述了 java.time。 ThreeTen Backport project,java.time 向后移植到 Java 6 和 7(JSR-310 的 ThreeTen)。 ThreeTenABP,android 版 ThreeTen Backport Question: How to use ThreeTenABP in Android Project,解释得很透彻。

【讨论】:

非常明确的答案!我建议您也发布java.time 解决方案以及在旧版本中使用它的方法。 嗨@OleV.V。谢谢。但是有一件事如果这是在 7 月 18 日 18:29 或之前运行的,我预计今天是错误的,明天对于给定的输入日期是正确的。因为对于输入日期,直到今天 18:30 才过,对吧?还是我的想法错了。 这很奇怪,@user2668552。您是指 UTC 或您自己的时区的 18:29 吗?显然LocalDate.now(DateTimeZone.UTC) 应该在 18:30 UTC 前后给出相同的结果。请问minimal reproducible example? 我在 UTC 的服务器上运行它。因此,当我将输入日期 2021-07-15T05:00:00.527+05:30 转换为 UTC 并获取 LocalDate 时,它​​将是 2021-07-14。当 UTC 时间在 2021 年 7 月 14 日 18:30 之前,对于输入日期时区的用户,它仍然是明天而不是今天。将在某个时候分享示例。【参考方案2】:

我现在使用 java.time 在我的代码中执行此操作。我从输入日期获取偏移量,将其添加到当前 UTC 时间,然后获取两者的本地日期并进行比较。 不确定这是否涵盖了夏令时等场景。

    ZonedDateTime zonedScheduleDate = ZonedDateTime.parse(inputDate);
    ZoneId zone = zonedScheduleDate.getZone();
    ZonedDateTime instantAtUserTimezone = Instant.now().atZone(zone);
    return (int) DAYS.between(instantAtUserTimezone.toLocalDate(), zonedScheduleDate.toLocalDate());

【讨论】:

我建议您使用这个答案。如果您不介意,也请标记为已接受。

以上是关于使用 Joda 的不同时区的日期之间的天数的主要内容,如果未能解决你的问题,请参考以下文章

如何计算不同时区的两个 NSDate 对象之间的天数差异?

如何使用 Joda Time 解析包含时区的日期

使用 Joda-Time 获取给定日期和时区的 UTC 偏移量

Joda Time 将时区日期时间转换为毫秒

使用 joda time 将一个时区转换为另一个时区

为什么org.joda.time.LocalDate是没有时区的日期?