BLOG

2019-01-29

【Javaのお話】日時処理編

わっふい!しまじろーです。

もうそんな時期でもありませんが、明けましておめでとうございます。

 

前回の記事から、少し間が空いてしまいましたが、引き続き「Javaのお話」していきたいと思います。

今回は日時処理についてです。

 


 

・まずはじめに

何かと処理する機会は多いはずなのに、イマイチ身に付かない日時処理について備忘がてら色々とまとめてみたいと思います。

 

Javaで日時を扱えるクラスとして以下があります。

  • ◆ java.util.Date

  • ◆ java.util.Calendar

  • ◆ java.time.LocalDateTime

耳馴染みのあるものから無いものまで、一先ず、それぞれのクラスについて調査してみました。

 

・Dateクラス

JDK1.0で追加されたクラス。

もはや過去の遺物となっており、このクラスから「年月日」を取得するメソッドは非推奨になっております。

Java8以前では、DateFormatクラスと組合せて日付の表示を行ったりと、何かとお世話になった方も多いのではないでしょうか。

しかしながら残念なポイントが多々ありまして。。。

  • ◆Dateクラス単体では日付・時刻の加算等ができない
  • ◆月の値がなぜか「0」始まり
    •  ◇理由としてはC言語に由来するもの
  • ◆デフォルトの文字列表現がUnix形式

現在のスタンスとしては、「とある時点での特定の日時を表すオブジェクト」となっている様です。

 

 

・Calendarクラス

JDK1.1で導入。

Dateクラスを使って日時の操作を行うクラス。

Calendarクラスのインスタンスは現在時刻に初期化されるため、任意の時刻等を設定したい場合はDateクラスのインスタンスを用いる。

時刻のみや日付のみは扱えず、年月日時分秒の指定が必要。

mutableなオブジェクトなので複数スレッドから操作を行った時に開発者の意図しない動作となることがあります。

(私も、若かりし頃にバグの原因がわからず苦しめられたことがあります。。。)

 

 

・LocalDateTimeクラス

JDK1.8で導入。

やっとまともに日時を扱えるクラス群が登場!

java.timeパッケージのひとつとして満を持して登場。

現在日時でも任意の日時でもstaticメソッドで取得可能。

月の値が「1-12」になりました。

タイムゾーンの情報は持たないので、必要であれば以下のクラスを使用する。

  • ◆ ZonedDateTime

    •  ◇ タイムゾーン付き

    •  ◇ 2015-12-15T23:30:59.999+09:00[Asia/Tokyo]

  • OffsetDateTime

    •  ◇ オフセット付き

    •  ◇ 2015-12-15T23:30:59.999+09:00

       

そして何より、immutableになったことでスレッドセーフになりました。

 

 


 

・操作例

Java8以降であればこんな感じでやれますよー。

 

◆日時比較

2つのインスタンスを比較(日付として未来/過去/同値の判定)できるメソッドが用意されています。

LocalDateTime now1 = LocalDateTime.now();
LocalDateTime now2 = LocalDateTime.now();
boolean isBefore = now1.isBefore(now2);
boolean isAfter = now1.isAfter(now2);
boolean isEqual = now1.isEqual(now2);

 

◆進めたり戻したり

加算、減算は各フィールドに対応したplusメソッド、minusメソッドが用意されています。

LocalDateTime now = LocalDateTime.now();
LocalDateTime d1 = now.plusSeconds(1); // 1秒加算
LocalDateTime d2 = now.minusDays(1);   // 1日減算

immutableなので、それぞれ別のインスタンスが返却されます。

チェインすることで、複数の変更を加えることが可能です。

 

 

◆月末の日付を取得

LoocalDateクラスであればそれ用のメソッドが用意されています。

LocalDate date = LocalDate.now();
int days = date.lengthOfMonth();

 

 

◆現在日の年度を取得

単純に考えれば、現在日を取得し月が1-3だった場合は年から-1する、それ以外はそのまま、ってことになるんですがいちいち分岐書いたりちょっと煩わしいですよね。。。

そこで、こんなのはどうでしょうか。

LocalDateTime now = LocalDateTime.now();
int nendo = now.minusMonths(3).getYear();

分岐などは設けず、一律で3ヶ月前の日付から年の値を取得しています。

こうすることで1-3月の場合は前年の値が、4月以降であれば本年度の値が取得できます。

 

 


 

・まとめ

過去のAPIも紹介しつつ、ざっくりと日時操作のあれこれについてまとめました。

 

みなさん、可能な限りjava.timeパッケージのAPI使っていきましょう。

今までの知見がどうとか、過去の遺産がどうとか言っている場合ではないと思いますね。

 

Java7以前を使わなければならない特殊な環境は仕方ないとして、可能な限り新しい技術は取り入れていくべきですね。

The following two tabs change content below.

縞次郎

Java、Android中心に開発やってます。 サーバサイドの開発が多いですが、フロントもそこそこやれると信じているアラサーSE。

最新記事 by 縞次郎 (全て見る)