22

2つの日付の間に作成されたアカウントのリストを取得するために、Active Directoryから日付値(createWhen)を取得し、それをJavaの日付に変換する作業を行っています。すべてが正常に機能しています。1つのメソッドを除いて、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

明らかに、それは日と年を正しくピックアップしています(そして、私が時間/分/秒を含めることを選択した場合、それらも正しく含まれます)が、すべての日付は何らかの理由で1月に配置されています。

さて、私のエラーはかなり単純なものだと確信していますが、フォーマットを約10回再確認したところ、もう表示できなくなっています。うまくいけば、2番目の目で私のコードを調べて、月がひどく間違っているのにどこが間違っているのかを指摘できますか?

ありがとう。

4

4 に答える 4

50

パターン文字列を「yyyy/MM/DD」から「yyyy/MM/dd」に変更します

SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM/dd");
于 2010-08-24T19:41:37.743 に答える
5

「MM」または「MMM」の代わりに「mm」を使用しないでください。小さいmは分を示し、大文字のMは月を示します。

于 2016-07-13T05:53:13.680 に答える
1

TL; DR

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

これにより、LocalDateのが得られ2005-09-12ます。

java.time

私は現代の答えに貢献しています。Suhas Phartaleの答えは正解であり、7年前に書かれたときは良い答えでした。現在、悪名高い厄介SimpleDateFormatなクラスは古くjava.time、最新のJava日時APIの方がはるかに優れています。古い日時クラスの代わりにこれを使用することを強くお勧めします。

詳細

コードから、解析する前にADから文字列を再フォーマットしているようです。その必要はありません。ADからの文字列を直接解析できます。直接解析して。にしたかもしれませんが、時間を取得して文字列からオフセットするためにLocalDate解析することをお勧めします。OffsetDateTimeご覧のとおり、これはLocalDate後で直接変換できます。Aは時刻のない日付であるため、古いクラスLocalDateよりも要件に一致しているようです。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

チュートリアル

詳細についてjava.time、Oracleチュートリアルを参照するか、ネット上で他のリソースを検索してください。

于 2017-12-11T11:08:45.970 に答える
0

私はここからリダイレクトされ、上記の解決策は私の問題を解決しなかったので、私はこの答えを投稿しています

私にとってのシナリオは、この日付「2020-03-01T07:00:00 + 0530」を解析した後、希望する形式である1/2 [dd / MM]として結果を取得していましたが、その結果には日付文字列が月がであることを明確に示しているため、間違った月3 [MARCH]

つまり、基本的にcal.get(Calendar.DAY_OF_MONTH)は、実​​際の3ではなく2を返していました。

そして、MONTHセクションのドキュメントによると

「グレゴリオ暦とユリウス暦の最初の月は1月で0です。最後の月は、1年の月数によって異なります。」

したがって、+ 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)));

これが誰かを助けることを願っています。

于 2020-03-01T08:11:18.040 に答える