【问题标题】:DateTime parser format in java 8java 8中的日期时间解析器格式
【发布时间】:2021-07-17 16:08:32
【问题描述】:

我正在尝试解析如下的 datetimeStamp,但我无法找到正确的解析器。有人可以建议我如何解析这样的日期:

import java.time.format.DateTimeFormatter;
import java.time.LocalDateTime;
public class HelloWorld{

     public static void main(String []args){
          int DAYS = 30;
         String date ="2021-04-23T12:09:56.123-07:00";
            DateTimeFormatter DATE_TIME_FORMATTER = DateTimeFormatter
      .ofPattern("YYYY-MM-DD'T'hh:mm:ss.SSS±hh:mm");
        
        LocalDateTime localDateTime = LocalDateTime.parse(date, DATE_TIME_FORMATTER);
        System.out.println("Local Date" + localDateTime);
      LocalDateTime now = LocalDateTime.now();
      if (localDateTime.isBefore(now) && localDateTime.isAfter(now.plusDays(DAYS)))
        {
             System.out.println("Date is incorrect");
        }else{
             System.out.println("Success");
        }
     }
}

下面还有一些额外的细节: 必须以 ISO 8601 扩展格式表示为以下之一 - YYYY-MM-DDThh:mm:ss[ .sss ]Z, YYYY-MM-DDThh:mm:ss[ .sss ]±hh:mm 。其中 [ .sss ] 是可选的,可以是 1 到 3 位数字。必须是未来不超过 30 天的值。万事达卡建议使用(当前时间 + 30 分钟)的值。最大长度 - 29。类型 - 字符串。 例如:“2015-07-04T12:09:56.123-07:00”

请帮助我使用指定日期的正确格式化程序。

【问题讨论】:

  • 你的代码到底有什么问题?
  • 代码中ofPattern()中的arg DateTimeFormatter DATE_TIME_FORMATTER = DateTimeFormatter .ofPattern("YYYY-MM-DD'T'hh:mm:ss.SSS±hh:mm");跨度>
  • ±hh:mm 应该是Z
  • 你不能像这样解析String。您需要不同的模式(或根本不需要)和不同的类:OffsetDateTime 而不是 LocalDateTime(它无法读取和存储有关偏移量的信息)。
  • “作为以下之一” - 这意味着您尝试解析的格式并不总是相同?顺便说一句,我会试试这个 yyyy-MM-dd'T'HH:mm:ss.SSSXXX

标签: java datetime-format


【解决方案1】:

完全摆脱这种错误模式(以及DateTimeFormatter),使用OffsetDateTime 而不是LocalDateTime,后者无法存储有关偏移量的信息。

这是您代码的转换(稍作调整和注释):

public static void main(String[] args) {
    String date = "2021-04-23T12:09:56.123-07:00";
    
    /*
     * no DateTimeFormatter needed due to default format of the String
     */
    
    // use an OffsetDateTime to parse a String with an offset
    OffsetDateTime odtParsed = OffsetDateTime.parse(date);
    // print it
    System.out.println("Parsed OffsetDateTime is " + odtParsed);
    // take the current instant as an OffsetDateTime at an offset of -7 hours
    OffsetDateTime now = OffsetDateTime.now(ZoneOffset.ofHours(-7));
    
    // run your check and get a success
    if (odtParsed.isBefore(now) && odtParsed.isAfter(now.plusDays(DAYS))) {
        System.out.println("Date is incorrect");
    } else {
        System.out.println("Success");
    }
}

打印出来

Parsed OffsetDateTime is 2021-04-23T12:09:56.123-07:00
Success

提示:这对于不同格式的Strings 将失败。如果格式仅略有不同,您也许可以创建一个DateTimeFormatter(通过DateTimeFormatterBuilder)来处理可选部分等。

编辑

如果只有一天的毫秒是可选的,并且偏移量的格式总是由加号或减号组成,后跟两位数表示小时,冒号和两位数表示分钟,则以下示例可能显示了一种足够的方法它通用

public static void main(String[] args) {
    String date = "2021-04-23T12:09:56.123-07:00";
    String date1 = "2021-04-23T12:09:56.123+02:00";
    String date2 = "2021-04-23T12:09:56.123+00:00";
    String date3 = "2021-04-23T12:09:56-07:00";
    String date4 = "2021-04-23T12:09:56+02:00";
    String date5 = "2021-04-23T12:09:56+00:00";
    
    // DateTimeFormatter using optional millis of second
    DateTimeFormatter dtf = DateTimeFormatter.ofPattern("uuuu-MM-dd'T'HH:mm:ss[.SSS]xxx");
    
    // use an OffsetDateTime to parse a String with an offset
    OffsetDateTime odtParsed = OffsetDateTime.parse(date, dtf);
    OffsetDateTime odtParsed1 = OffsetDateTime.parse(date1, dtf);
    OffsetDateTime odtParsed2 = OffsetDateTime.parse(date2, dtf);
    OffsetDateTime odtParsed3 = OffsetDateTime.parse(date3, dtf);
    OffsetDateTime odtParsed4 = OffsetDateTime.parse(date4, dtf);
    OffsetDateTime odtParsed5 = OffsetDateTime.parse(date5, dtf);
    // print it
    System.out.println("Parsed OffsetDateTime is " + odtParsed);
    System.out.println("Parsed OffsetDateTime is " + odtParsed1);
    System.out.println("Parsed OffsetDateTime is " + odtParsed2);
    System.out.println("Parsed OffsetDateTime is " + odtParsed3);
    System.out.println("Parsed OffsetDateTime is " + odtParsed4);
    System.out.println("Parsed OffsetDateTime is " + odtParsed5);
}

输出:

Parsed OffsetDateTime is 2021-04-23T12:09:56.123-07:00
Parsed OffsetDateTime is 2021-04-23T12:09:56.123+02:00
Parsed OffsetDateTime is 2021-04-23T12:09:56.123Z
Parsed OffsetDateTime is 2021-04-23T12:09:56-07:00
Parsed OffsetDateTime is 2021-04-23T12:09:56+02:00
Parsed OffsetDateTime is 2021-04-23T12:09:56Z

如果您不希望将零小时和零分钟的偏移量输出为Z,则使用DateTimeFormatter 进行如下输出:

OffsetDateTime odtParsed5 = OffsetDateTime.parse(date5, dtf);

这使得输出看起来像这样:

Parsed OffsetDateTime is 2021-04-23T12:09:56.000+00:00

即使它们都是零,也会打印一天中的毫秒。

另一个编辑:

要检查日期是否在过去 30 天未来 30 天范围内,最好只使用日期部分:

public static void main(String[] args) {
    // the first part is already known from the examples above...
    String date = "2021-04-23T12:09:56.123-07:00";
    DateTimeFormatter dtf = DateTimeFormatter.ofPattern("uuuu-MM-dd'T'HH:mm:ss[.SSS]xxx");
    OffsetDateTime odtParsed = OffsetDateTime.parse(date, dtf);
    
    // get the current instant as an OffsetDateTime (in UTC == +00:00)
    OffsetDateTime now = OffsetDateTime.now(ZoneOffset.UTC);
    
    /*
     * might be smart to keep time of day out of the calculation, so...
     */
    
    // get the date only out of the OffsetDateTime
    LocalDate today = now.toLocalDate();
    // create one for 30 days before
    LocalDate thirtyDaysBeforeToday = today.minusDays(30);
    // and one 30 days in the future
    LocalDate thirtyDaysInTheFuture = today.plusDays(30);
    // finally extract the date part from the parsed date time
    LocalDate d = odtParsed.toLocalDate();
    
    // make your checks using the LocalDates, maybe separate the two cases of an invalid date
    if (d.isBefore(thirtyDaysBeforeToday)) {
        System.err.println("Invalid date: too far in the past");
    } else if (d.isAfter(thirtyDaysInTheFuture)) {
        System.err.println("Invalid date: too far in the future");
    } else {
        System.out.println("Valid date");
    }
}

尝试一些不同的有效和无效日期...

【讨论】:

  • 但 -7 只是一个示例,它必须与提供的任何日期兼容。请你能建议我怎样才能使它通用。
  • @NikitaDixit 当然,请参阅我回答的最后编辑。
  • 嗨,谢谢,是的,这已经足够了。感谢您的所有帮助,但解析是完美的基本上我需要检查日期是否有效。它应该是今天的日期或未来 30 天内。我无法通过这些测试/检查。
  • 非常感谢。您能否建议我如何获取当前时间,即现在使用偏移量。
  • @NikitaDixit 不客气...请考虑接受其中一个答案。接受答案甚至会给你一点声望。
【解决方案2】:

这里有 3 个不同的问题:

  1. ±hh:mm - 根据docs of DateTimeFormatter(请记住,阅读是基础!在提出 SO 问题之前务必阅读 javadoc!),± 不是一回事。 hhmm 是事物,但不是“偏移时间”。代表 tz 偏移的“模式”是一个字母;您很可能正在寻找Z。但这通常不包括:

  2. LocalDateTime 不能表示偏移量,也不知道时区。如果你想这样,你正在寻找ZonedDateTime 或者很可能是OffsetDateTime

  3. 您的模式不包含语言环境,这意味着它的输出以及它可以解析的内容取决于您运行此代码的计算机的语言环境,这听起来很糟糕。始终使用.ofPattern("someString", Locale.ENGLISH)(或其他语言环境),除非您真的真的确定您希望应用程序依赖于您运行它的服务器的配置,这种情况应该很少见。

【讨论】:

  • 虽然记住提供语言环境是一个好习惯(Locale.getDefault(Locale.Category.FORMAT) 这正是我们所希望的),但在这种情况下,将其排除在外并没有任何实际意义,因为该模式不包括任何依赖于语言环境的部分。
【解决方案3】:

您的文档使用 ± 表示 +-,其占位符不是 Java 占位符。只需使用DateTimeFormatter.ISO_OFFSET_DATE_TIME

【讨论】:

    猜你喜欢
    • 2015-06-26
    • 1970-01-01
    • 2017-09-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-01-01
    • 2015-08-13
    相关资源
    最近更新 更多