【问题标题】:Compare String time to Local Server Time比较字符串时间和本地服务器时间
【发布时间】:2017-10-27 14:41:17
【问题描述】:

拥有一个具有特定日期格式的字符串对象。 需要检查该 dateStr 是否在本地计算机上的当前时间之后。 转换问题和LocalDateTime

String dateStr = "Oct 27 2017 02:29:00 GMT+0000";
public static final String DATE_FORMAT = "MMM dd yyyy HH:mm:ss zzzZ";

我知道下面的代码中有问题,使用LocalDateTime

public static boolean isFutureDate(String dateStr){
      DateTimeFormatter formatter = DateTimeFormatter.ofPattern(DATE_FORMAT);
      LocalDateTime dateTime = LocalDateTime.parse(dateStr, formatter);
      return(dateTime.isAfter(LocalDateTime.now()));
}

问题在于时区和日期转换。 请帮助找到检查 dateStr 是否在 Java 8 中的当前本地日期之后的正确方法?

【问题讨论】:

  • 请包含常量 DATE_FORMAT 的内容...
  • 添加 DATE_FORMAT
  • 这里的鱼腥味是什么定义?您可以看到任何错误?
  • 不,返回的响应不是预期的。而且我知道 LocalDateTime 不考虑时区。
  • @AshokFelix 上面共享的代码为我返回了false,鉴于字符串中提到的时间实际上早于我当前的本地日期时间,我认为这是合适的。

标签: date java-8 java-time datetime-parsing datetime-conversion


【解决方案1】:

Local… 类型没有时区

您为数据使用了错误的类型。

包括LocalDateTime 在内的Local… 类型故意没有时区或UTC 偏移量的概念。因此,它们代表时间线上的一个时刻,只是一系列可能时刻的粗略概念。仅在时区未知或不相关时使用LocalDateTime;永远不要在历史上的实际时刻使用它。

OffsetDateDate 用于具有与UTC 偏移的值、小时数和分钟数。

ZonedDateTime 用于具有指定时区的值。 Asia/KolkataAmerica/Montreal 之类的时区是特定区域过去、现在和未来对其与 UTC 的偏移量变化的历史。夏令时 (DST) 等异常情况意味着偏移量发生了变化。

如果您知道所有输入都是 GMT/UTC,请使用 OffsetDateTime。如果输入可能使用时区,则解析为 ZonedDateTime 对象。

这种输入数据格式很糟糕。如果您有任何控制权,请在将日期时间值作为文本交换时使用标准 ISO 8601 格式。

Stack Exchange 已经多次介绍了所有这些内容。请在发帖前进行更彻底的搜索。并搜索 Stack Overflow 以了解更多信息。我在这里保持简短的回答,因为这是重复的。

【讨论】:

    【解决方案2】:

    在解析为 LocalDateTime 时,您忽略了偏移量 (+0000),我不确定这是否是您真正想要的。

    在这种情况下,+0000 偏移量表示日期/时间是 UTC 2017 年 10 月 27 日 02:29 AM。当您解析为 LocalDateTime 时,您将忽略偏移量(因此它仅表示“2017 年 10 月 27 日th 02:29 AM”,不附加到任何时区)并与您的本地进行比较日期/时间(或 JVM 默认时区中的当前日期/时间)。

    如果您想进行同时考虑偏移的比较,您可以将其解析为 OffsetDateTime 并转换为 Instant 以将其与实际的 UTC 时刻进行比较,而不考虑时区。

    另外,月份名称是英文的(我假设它是英文的,但你可以相应地更改它),所以你必须在格式化程序中使用 java.util.Locale(如果你没有设置语言环境,它会使用JVM默认,不保证永远是英文):

    // parse to OffsetDateTime (use the same formatter)
    String dateStr = "Oct 27 2017 02:29:00 GMT+0000";
    DateTimeFormatter fmt = DateTimeFormatter.ofPattern("MMM dd yyyy HH:mm:ss zzzZ", Locale.US);
    OffsetDateTime odt = OffsetDateTime.parse(dateStr, fmt);
    // compare Instant's
    System.out.println(odt.toInstant().isAfter(Instant.now()));
    

    虽然它现在适合您,但请记住,即使在运行时,也可以更改默认语言环境,恕不另行通知。如果您的输入包含对区域设置敏感的日期(例如月份名称),最好按上述方式指定。

    【讨论】:

    • 注意解析日期,格式为parsed appropriately
    • 第一个代码块没有给我预期的当前 GMT 时间和我的本地时间。我正在尝试你的第二种方法。但是解析器按预期工作:)
    • @AshokFelix 第一个代码块只获取日期和时间并忽略偏移量 - 它不进行任何转换
    • @nullpointer 确实,zzzZ 格式有效,我在测试时打错了字,但我认为它没有。我已从答案中删除了该注释,谢谢!
    • @AshokFelix 解析器可以工作,因为您的 JVM 的默认语言环境可能是英语(或任何其他将“Oct”识别为月份名称的语言),但不能保证在所有配置中都能正常工作(我的 JVM 设置为葡萄牙语,如果我没有设置特定的语言环境,它会失败) - 我在答案中添加了一条注释
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-08-04
    • 1970-01-01
    相关资源
    最近更新 更多