【问题标题】:Java SimpleDateFormat always returning January for MonthJava SimpleDateFormat 总是返回一月份的月份
【发布时间】:2010-08-24 19:29:03
【问题描述】:

我正在从 Active Directory 中获取日期值 (createWhen),并将其转换为 Java 日期,以获取在两个日期之间创建的帐户列表。一切正常,除了一种方法:我从 AD 日期到 Java 日期的方法。该方法如下所示:

private Date getParsedDate(String givenString) {
    System.out.println("Value from AD is: " + givenString);
    Date parsedDate = null;
    String formattedString = this.formatDateString(givenString);
    System.out.println("Formatted String is: " + formattedString);
    SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM/DD");
    try {
        parsedDate = sdf.parse(formattedString);
        System.out.println("Final date string is: " + parsedDate.toString());
    } catch (ParseException ex) {
        ex.printStackTrace();
    }
    return parsedDate;
}

并且,对于来自 AD 的单个任意数据:

Value from AD is: 20050912190509.0Z

Formatted String is: 2005/09/12

Final date string is: Wed Jan 12 00:00:00 EST 2005

显然,它正确地选择了日期和年份(如果我选择包括小时/分钟/秒,它也正确地包括那些),但是每个日期都被放置在一月份某种原因。

现在,我确信我的错误是一个非常简单的错误,但我已经重新检查了我的格式大约十次,现在我已经看不到它了。第二双眼睛能否有希望地查看我的代码并指出我哪里出了问题,让月份如此严重不正确?

谢谢。

【问题讨论】:

    标签: java active-directory simpledateformat


    【解决方案1】:

    将模式字符串从“yyyy/MM/DD”更改为“yyyy/MM/dd”

    SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM/dd");
    

    【讨论】:

    • 解决了,谢谢。显然谷歌给我的页面给了我不正确的文档。这就是我不去源头所得到的。
    • 完美的解决方案,对我来说从 mm 换成 MM 效果很好
    【解决方案2】:

    确保您不要使用“mm”而不是“MM”或“MMM”。因为小 m 表示分钟,大写 M 表示月份。

    【讨论】:

      【解决方案3】:

      TL;DR

          LocalDate parsedDate = OffsetDateTime
                  .parse("20050912190509.0Z", DateTimeFormatter.ofPattern("uuuuMMddHHmmss.SX"))
                  .toLocalDate();
      

      这会产生LocalDate2005-09-12

      java.time

      我正在贡献现代答案。 Suhas Phartale’s answer 是正确的,并且在 7 年前编写时是一个很好的答案。现在臭名昭著的麻烦 SimpleDateFormat 类早已过时,而我们在现代 Java 日期和时间 API java.time 中拥有更好的东西。我强烈建议您使用它而不是旧的日期时间类。

      详情

      从您的代码看来,您在解析之前从 AD 重新格式化了您的字符串。没必要,直接解析AD中的字符串即可。我们可能直接将其解析为LocalDate,但我建议将其解析为OffsetDateTime,以获取字符串的时间和偏移量;如您所见,之后可以直接将其转换为LocalDateLocalDate 是一个没有时间的日期,因此它似乎比旧的 Date 类更符合您的要求。

      字符串采用 UTC 格式(最后用 Z 表示)。以上为您提供了字符串中的日期,即 UTC 日期。相反,如果您想要的是 UTC 时间 9 月 12 日 19:05 时所在时区的日期:

          LocalDate parsedDate = OffsetDateTime.parse(givenString, adDateTimeFormatter)
                  .atZoneSameInstant(ZoneId.of("America/Coral_Harbour"))
                  .toLocalDate();
      

      我假设我们已经将格式化程序声明为静态字段:

      private static final DateTimeFormatter adDateTimeFormatter
              = DateTimeFormatter.ofPattern("uuuuMMddHHmmss.SX");
      

      在这种情况下,结果是相同的,对于其他时区则不会。请用您自己想要的时区替换 America/Coral_Harbour。要使用 JVM 的时区设置,请指定 ZoneId.systemDefault()。但是请注意,该设置可能会被您程序的其他部分或在同一 JVM 中运行的其他程序更改,因此这是脆弱的。

      Suhas Phartale 的回答在 java.time 中也有效:格式模式字符串区分大小写,我需要使用小写 dd 来表示月份。

      教程

      the Oracle tutorial 中了解有关java.time 的更多信息和/或在网上搜索其他资源。

      【讨论】:

        【解决方案4】:

        我发布此答案是因为我是从 here 重定向的,以上解决方案没有解决我的问题

        对我来说,情况是,在解析了这个日期“2020-03-01T07:00:00+0530”后,我得到的结果是 1/2 [dd/MM],这是我想要的格式,但是结果包含错误的月份,因为日期字符串清楚地表明月份是3 [MARCH]

        所以基本上 cal.get(Calendar.DAY_OF_MONTH) 返回我 2 而不是实际的 3。

        根据 MONTH 部分中的docs

        “公历和儒略历中的第一个月是 一月是0;最后一个取决于 a 中的月数 年。”

        所以我们只需要添加一个 +1 就可以得到实际月份。猜猜这种行为可能是从月份数组中返回月份的名称吗?! [1月、2月等]

        以下是我的实现示例(我的字符串中的日期格式为“yyyy-MM-dd'T'HH:mm:ssZ”):

        Calendar cal = Calendar.getInstance();
                    SimpleDateFormat sdf = new SimpleDateFormat(Constant.DATE_FORMAT_WITH_TIMEZONE,Locale.ENGLISH);
                    try {               
                        cal.setTime(Objects.requireNonNull(sdf.parse(forecastList.get(listPosition).fcst_valid_local)));
                    } catch (ParseException e) {
                        e.printStackTrace();
                    }
                    String s = "%s/%d";
                    String output = String.format(s,cal.get(Calendar.DAY_OF_MONTH),(cal.get(Calendar.MONTH)+1)));
        

        希望这对某人有所帮助。

        【讨论】:

          猜你喜欢
          • 2017-06-09
          • 2020-03-08
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2016-06-09
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多