ryhmrt’s blog

意識低い系プログラマの雑記

Jacksonのデフォルトタイムゾーン

今週に入ってからSpringMVCでWebAPIをごりごり書いているのですが、いざ日付型を扱うというところになってちょっとはまったのでメモ書き。

謀ったなJackson

SpringMVCのJSON処理は標準でJacksonを使うようになっています。

Jacksonで日付型をフォーマットするためには

    @JsonFormat(pattern = "yyyy/MM/dd")
    private Date date;

とかやるわけなんですが、これだとタイムゾーンがGMTで計算されて変になったりします。

    @JsonFormat(pattern = "yyyy/MM/dd", timezone = "Asia/Tokyo")
    private Date date;

とか書くこともできるんですが、さすがにこれを一々指定するのは気が重い。

@JsonFormat のJavaDocのtimezone部分を見ると、

TimeZone to use for serialization (if needed). Special value of DEFAULT_TIMEZONE can be used to mean "just use the default", where default is specified by the serialization context, which in turn defaults to system defaults (TimeZone.getDefault()) unless explicitly set to another locale.

とか書いてあるので、

TimeZone.setDefault(TimeZone.getTimeZone("Asia/Tokyo"));

と、アプリの初期時にやっておけば良いと思ったそこの貴方は残念賞。

Jacksonで明示的にデフォルト指定をしない場合のタイムゾーンは "GMT" 固定です。

com.fasterxml.jackson.databind.cfg.BaseSettings を見ると、昔は TimeZone.getDefault() を使っていたのかな、と思うようなコメントアウト(!!)があって目を疑います。

    private static final TimeZone DEFAULT_TIMEZONE = 
            //  TimeZone.getDefault()
            /* [databind#915] 26-Sep-2015, tatu: Should be UTC, plan to change
             * it so for 2.7
             */
            TimeZone.getTimeZone("GMT");

エスパーするとしたら、タイムゾーンの環境依存で発見しにくいバグに悩まされて、デフォルトをGMT固定に変更したとかでしょうか...

尚、Jacksonの公式WikiにあるFAQの日付処理のトピックでは、一番最初に「タイムゾーン何も指定しなければGMTだから、よろしく」と書いてありました。 http://wiki.fasterxml.com/JacksonFAQDateHandling

これで勝てねば貴様は無能だ

以下のようなクラスをプロジェクトの適当な場所に作ればOKです。

@Configuration
public class WebConfiguration extends WebMvcConfigurerAdapter {
    @Override
    public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
        Jackson2ObjectMapperBuilder builder = new Jackson2ObjectMapperBuilder()
                .timeZone("Asia/Tokyo")
                .dateFormat(new SimpleDateFormat("yyyy/MM/dd HH:mm:ss"));
        converters.add(new MappingJackson2HttpMessageConverter(builder.build()));
    }
}

上のコードではついでにデフォルトの日付フォーマットも変更してます。

参考: http://docs.spring.io/spring/docs/current/spring-framework-reference/html/mvc.html#mvc-config-message-converters