web-dev-qa-db-ja.com

ISOパラメータを指定したDateTimeFormatがタイムゾーンを正しく解析していません

私はmockMVCを使用してテストしようとしているこのコントローラーを持っています

@RequestMapping(value = "/something/{language}", method = RequestMethod.GET, produces = { "application/json", "application/xml" })
    public ResponseEntity<someEntity> getInfo( 
            @PathVariable String language, 
            @DateTimeFormat(iso= DateTimeFormat.ISO.DATE_TIME) @RequestParam(required = false) Date fromDate
    )

したがって、ドキュメントのような日付形式を解析可能にすることを期待しています。DATE_TIME最も一般的なISO DateTime形式yyyy-MM-dd'T'HH:mm:ss.SSSZ、例:.

しかし、私は次のようなものを取得し続けます:

ハンドラーの実行により例外が発生しました:タイプ「Java.lang.String」の値を必要なタイプ「Java.util.Date」に変換できませんでした。ネストされた例外は

org.springframework.core.convert.ConversionFailedException: 
Failed to conv ert from type Java.lang.String to type 
@org.springframework.format.annotation.DateTimeFormat 
@org.springframework.web.bind.annotation.RequestParam Java.util.Date for value '2015-09-26T01:30:00.000Z'; nested exception is
Java.lang.IllegalArgumentException: Unable to parse '2015-09-26T01:30:00.000Z'

私が見る限り、私は何も悪いことをしていません。もちろんそれは間違いありません。誰かが私の悪いことを光らせることができますか?例外はAPIに渡す正しい値を示しているので、これ以上コードを投稿する必要はないと思いますか?

7
Mathijs Segers

使い方

日付をString(HTTPリクエストはテキストベース)として受け取り、patternによって日付オブジェクトに変換する方法をSpringに指示します。

//Spring controller 
@GetMapping
public List<Foobar> find(
   @RequestParam(name = "startDate", required = false)
   @DateTimeFormat(pattern = "YOUR_DATE_PATTERN" or iso="ISO Enum member") //how to convert the date string
   Date startDate {
  return service.find(startDate); //work with the Java.util.Date object
}

SpringはこのタスクをJava.text.DateTimeFormatに委任するため、パターンはフォーマッタークラスが機能する有効なパターンである必要があります。

@ DateTimeFormat-パターンVSIso

  • パターン:パターンを指定します。フォーマッタに直接渡されます。
  • Iso:org.springframework.format.annotation.DateTimeFormat.ISOEnumのメンバーで、事前に作成された日付文字列パターンがあります。列挙型ドキュメントから:

DATE最も一般的なISO日付形式yyyy-MM-dd、例:.

DATE_TIME最も一般的なISODateTime形式yyyy-MM-dd'T'HH:mm:ss.SSSZ、例:.

NONEISOベースのフォーマットパターンを適用しないことを示します。

TIME最も一般的なISO時間形式HH:mm:ss.SSSZ、例:.

  • すべての列挙型メンバー(NONEを除く)は、タイムゾーンに「Z」を使用していることに注意してください。

日付パターンで「Z」はどういう意味ですか?

  • 日付と時刻のパターンのJavadocを見ると、タイムゾーンを処理するための2つのオプションがあります。

    1. 'Z' Char:RFC 822タイムゾーン構文(Springはこの構文を使用します)
zone      =  "UT"  / "GMT"                ; Universal Time
                                        ; North American : UT

        /  "EST" / "EDT"                ;  Eastern:  - 5/ - 4

        /  "CST" / "CDT"                ;  Central:  - 6/ - 5

        /  "MST" / "MDT"                ;  Mountain: - 7/ - 6

        /  "PST" / "PDT"                ;  Pacific:  - 8/ - 7

        /  1ALPHA                       ; Military: Z = UT;
                                        ;  A:-1; (J not used)
                                        ;  M:-12; N:+1; Y:+12

        / ( ("+" / "-") 4DIGIT )        ; Local differential
                                        ;  hours+min. (HHMM)
  1. 'X'文字:ISO8601タイムゾーン指定子

時間オフセット(15:00-03:30)OR 'Z' for UTC/GMT timezone

問題

  • org.springframework.format.annotation.DateTimeFormat.ISO.DATE_TIME Enumメンバーを選択すると、タイムゾーンのRFC822構文でyyyy-MM-dd'T'HH:mm:ss.SSSZパターンが使用されます。

修正

  • 同じパターンを使用しますが、タイムゾーンに「X」を使用します(ISO 8601構文を使用):

    yyyy-MM-dd'T'HH:mm:ss.SSSX

Zタイムゾーンについて

  • ISO 8601の状態:

協定世界時(UTC)

時刻がUTCの場合は、時刻の直後にスペースなしでZを追加します。 Zは、ゼロUTCオフセットのゾーン指定子です。したがって、「09:30 UTC」は、「09:30Z」または「0930Z」として表されます。 「14:45:15UTC」は「14:45:15Z」または「144515Z」になります。

ISO 8601時間表現のZ接尾辞は、同じ文字がZuluタイムゾーンを指定するために使用されるため、「Zulu時間」と呼ばれることがあります。ただし、軍事タイムゾーンのリストを定義するACP 121標準は、UTCについて言及しておらず、以前は国際常用時標準として使用されていたグリニッジ標準時[27]から「ズールー時間」を導き出します。

関連リンク

5
linuxunil

DateTimeFormat.ISO.DATE_TIMEによる

最も一般的なISODateTime形式yyyy-MM-dd'T'HH:mm:ss.SSSZ、例: 2000-10-31 01:30:00.000-05:00。

ここで、Zはタイムゾーン値を表します(例:-05:00)。

解析できない文字列値は2015-09-26T01:30:00.000Zです。ここで、Zは実際のタイムゾーン値に置き換える必要があります。

たとえば、2015-09-26T01:30:00.000-04:00ISO.DATE_TIMEによって正しく解析されます

3
Sanjeev

notを試して、パラメータfromDateを文字列として渡します。

同じ問題が発生し、パラメーターの値を二重引用符で囲んでいない場合(")API呼び出し(私はPostmanを使用しました)では、機能しました。ただし、一部の文字(+など)をエンコードする必要がある場合があります。

1
Francesco