LoginSignup
1
0

More than 3 years have passed since last update.

enrich my libraryパターンでZonedDateTimeをリッチにする

Last updated at Posted at 2019-07-20

はじめに

scalaのimplicit classを使ったenrich my libraryパターンでZonedDateTimeを便利に使おうという話です。

環境

scala 2.10 以上(implicit classが使えるのが2.10から)

時刻情報を扱うのがめんどくさい

めんどくさくないですか?

java8からjava.timeパッケージが入って色々楽になったものの、まだめんどくさいです。

私が関わっているサービスでは、年月日でパーティションを切っているDBテーブルがあり、ZoneDateTimeからyyyyMMdd形式の数値(20190101とか20191231とか)を取り出したい場面が頻繁にあります。

そういうとき、以下のような処理が必要になります。

val now = ZonedDateTime.now() //とりあえず現在時刻
val formatter = DateTimeFormatter.ofPattern("yyyyMMdd")
val yyyyMMdd = now.format(formatter).toInt

DateTimeFormatterのインスタンスはスレッドセーフなので、どこかに定数として定義しておけばいいので、実質的には

now.format(formatter).toInt

の1行にできるんですが。。。。

now.yyyyMMdd.toInt

というふうにZonedDateTimeにメソッドが生えててほしくないですか?

生えててほしくないですか!!!?!?!?

それができるんです。

そう、Scalaならね。

implicit classでZonedDateTimeを便利に拡張しよう

implicit classというのは、既存クラスを拡張できる仕組みです。

詳しくはドワンゴ新卒研修資料のimplicitについての解説を参照するか、ググるかしてください。

以下のようなクラスを作ります

implicit class RichZonedDateTime(val self: ZonedDateTime) extends AnyVal {
    private val yyyyMMddFormatter = DateTimeFormatter.ofPattern("yyyyMMdd")
    def yyyyMMdd: Int = {
        self.format(yyyyMMddFormatter).toInt
    }
}

クラス名はなんでもいいのですが、拡張元のクラスの接頭辞にRichとつけるのが単純でいいかと思います。(ググって出てくるのは大体それ)

selfの型には拡張したいクラスを指定します。

上記のクラスがスコープ内にある状態だと、以下のようにZonedDateTimeのインスタンスから(ソースコード上は)直接yyyyMMddメソッドを叩けるようになります

val now = ZonedDateTime.now()
now.yyyyMMdd

yyyyMMddメソッドを叩いたタイミングで暗黙的にRichZonedDateTimeに変換されるという認識です。(あってるよね?)

今回のケースはシンプルですが、取り出しに複雑な処理が必要になるものをimplicit classのメソッドとして定義すると、便利に使えると思います。(月の最終日を取得するとか)

感想

デザインパターンの使い所あるあるパターン集みたいな本が欲しいです。

最近アンクルおじさんのClean Architecture本読んでるんですが(まだ半分)Interface(または各言語のそれに準ずる機能)の使い所の理解が深まりました。

JavaだとInterfaceの利用は避けては通れない感じがあるんですが、大学で最初に触ったときは、「なんで間にこんな何層も挟まるんだ?」と思いましたからね。

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0