2015-12-21 12 views
6

私はこのZonedDateTime

@RequestMapping(value="/customer/device/startDate/{startDate}/endDate/{endDate}", method=RequestMethod.GET, produces=MediaType.APPLICATION_JSON_VALUE) 
public Page<DeviceInfo> getDeviceListForCustomerBetweenDates(@PathVariable ZonedDateTime startDate, @PathVariable ZonedDateTime endDate, Pageable pageable) { 
    ... code here ... 
} 

のように見える私のSpringアプリケーションでのRESTエンドポイントを持っている私は、ミリ秒、秒の両方としてパス変数を渡して試してみました。しかし、私は次の例外に両方の方法を取得:

"Failed to convert value of type 'java.lang.String' to required type 'java.time.ZonedDateTime'; nested exception is org.springframework.core.convert.ConversionFailedException: Failed to convert from type java.lang.String to type @org.springframework.web.bind.annotation.PathVariable java.time.ZonedDateTime for value '1446361200'; nested exception is java.time.format.DateTimeParseException: Text '1446361200' could not be parsed at index 10" 

誰かが、私は(どちらか秒またはミリ秒)に渡すことができる方法を説明し、そのような1446361200などの文字列と、それはZonedDateTimeに変換するために取得していただけますか?

または、文字列として渡してから変換を実行する唯一の方法はありますか?もしそうなら、同様のデザインを持つ複数のメソッドに対してこれを扱う一般的な方法はありますか?

+0

'ZonedDateTime'は比較的新しく、Springはそれを直接サポートするように更新されていない可能性があります。これを回避する方法については、JasonZの回答を参照してください。 – Powerlord

答えて

6

ZonedDateTimeパラメータにはデフォルトのコンバータがあります。これは、Java 8のDateTimeFormatter

DateTimeFormatter.ofLocalizedDateTime(FormatStyle.SHORT); 

これは、任意のFormatStyleか本当に限り、あなたが懸念しているとして、あなたの例では、働いていない任意のDateTimeFormatterしてきた可能性のように作成されたを使用しています。 DateTimeFormatterは、あなたが提供したものであり、タイムスタンプではなく日付文字列を解析し、フォーマットします。

あなたはこのような

public Page<DeviceInfo> getDeviceListForCustomerBetweenDates(
    @PathVariable @DateTimeFormat(iso = DateTimeFormat.ISO.DATE_TIME) ZonedDateTime startDate, 
    @PathVariable @DateTimeFormat(iso = DateTimeFormat.ISO.DATE_TIME) ZonedDateTime endDate, 
    Pageable pageable) { ... 

として、または適切なpattern

2000-10-31T01のような対応する日付文字列を使用してパラメータに適切なカスタム@org.springframework.format.annotation.DateTimeFormatを提供している可能性が

:30:00.000 -05:00

UNIXのタイムスタンプで上記の操作を行うことはできません。 The canonical wayZonedDateTimeにタイムスタンプするには、を指定して、Instant#ofEpochSecond(long)に変換します。

long startTime = 1446361200L; 
ZonedDateTime start = Instant.ofEpochSecond(startTime).atZone(ZoneId.systemDefault()); 
System.out.println(start); 

@PathVariableでこの作業を行うカスタムConverterを登録するには。

class ZonedDateTimeConverter implements Converter<String, ZonedDateTime> { 
    private final ZoneId zoneId; 

    public ZonedDateTimeConverter(ZoneId zoneId) { 
     this.zoneId = zoneId; 
    } 

    @Override 
    public ZonedDateTime convert(String source) { 
     long startTime = Long.parseLong(source); 
     return Instant.ofEpochSecond(startTime).atZone(zoneId); 
    } 
} 

ような何か、今addFormatters

@Override 
protected void addFormatters(FormatterRegistry registry) { 
    registry.addConverter(new ZonedDateTimeConverter(ZoneId.systemDefault())); 
} 

をオーバーライドし、WebMvcConfigurationSupport@Configuration注釈付きクラスに登録し、Spring MVCのはZonedDateTimeオブジェクトにStringパスセグメントをデシリアライズするために、このコンバータを使用します。春ブーツで


、私はあなただけで対応するConverterため@Beanを宣言することができますし、それが自動的に登録されますが、それは私の言葉を取ることはありませんと思います。

5

@PathVariableに渡したデータをStringデータ型として受け入れる必要があります。その場合は、自分で変換してください。エラーログには、そのことがわかります。

スプリングライブラリはコンバートできませんストリング値 "1446361200"からZonedDateTimeまで@PathVariableからバインディングまでは残念です。デフォルトでは

+0

あなたは何をすべきかについて正しいですが、これはジャクソンではなく、春の変換についてです。 – chrylis

1

@PathVariableは限られた7つの基本的なタイプを含むタイプのセット(booleanbyteshortintlongfloat、およびdouble)プラスDateをサポートしています。

ただし、extend thatコントローラでを使用し、ZonedDateTime.classのバインディングを追加することは可能です。私はあなたがこれを外部クラスで定義できるかどうかは分かりませんが、もしそうでなければ、を使用するすべてのコントローラでこの@InitBinderを定義する必要があります。

編集:カスタムPropertyEditorを作成し、registerCustomEditorを使用してバインドする必要があります。

関連する問題