LoginSignup
17
14

More than 5 years have passed since last update.

エポックタイムの扱いでハマった話

Last updated at Posted at 2015-08-21

ちょっとエポックタイムを使った比較を作った時にハマったので備忘録としてまとめ。

とりあえず説明よりも以下のコードと実行結果を見てほしい。

普通にjava.util.Dateを引数0で初期化

EpochTest1.java
import java.text.SimpleDateFormat;
import java.util.Date;

public class EpochTest1 {

    public static void main(String[] args) {
        SimpleDateFormat fmt = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        // 0指定で初期化
        Date epoch = new Date(0);

        System.out.println(fmt.format(epoch));
    }
}
実行結果
1970-01-01 09:00:00

あれ?9時間ずれてる・・・
9時間ってことはタイムゾーンの関係なんだろう。
めんどくさいけどCalendar使うか・・

java.util.Calendarを使ってみる

EpochTest2.java
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.TimeZone;

public class EpochTest2 {

    public static void main(String[] args) {
        SimpleDateFormat fmt = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        // Calendarをタイムゾーン指定して作成
        Calendar cal = Calendar.getInstance(TimeZone.getTimeZone("UTC"));
        // 0ミリ秒を設定
        cal.setTimeInMillis(0);
        Date epoch = cal.getTime();

        System.out.println(fmt.format(epoch));
    }
}

実行結果
1970-01-01 09:00:00

あり?Calendar使ってもずれてる・・・

DateFormatのタイムゾーン設定

EpochTest3.java
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.TimeZone;

public class EpochTest3 {

    public static void main(String[] args) {
        SimpleDateFormat fmt = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        // Dateformatのタイムゾーン設定
        fmt.setTimeZone(TimeZone.getTimeZone("UTC"));

        // 0指定で初期化
        Date epoch = new Date(0);

        System.out.println(fmt.format(epoch));
    }
}

実行結果
1970-01-01 00:00:00

というわけでDateFormatのタイムゾーンの設定の問題でした。
内部的にはDate epoch = new Date(0);とかでちゃんとエポック秒になっている。
でも文字列として変換する際にUTCエポック秒はJSTでは+09:00なので
SimpleDateFormatとかで変換すると1970-01-01 09:00:00になってしまう。

ただこれがちょっと問題で、テンプレートエンジンとかで
dateformatのタイムゾーンとかがいじりにくい場合、
日付の生成にミリ秒を使うと意図せずずれることがある。

なのでデフォルトロケールの"1970-01-01 00:00:00"を作成する方法も知っとくとハマらない。

文字列から初期化

EpochTest4.java
import java.sql.Timestamp;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;

public class EpochTest4 {

    public static void main(String[] args) throws ParseException {
        SimpleDateFormat fmt = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

        // DateFormat使って作成すればOK(当たり前
        Date epoch = fmt.parse("1970-01-01 00:00:00");
        System.out.println(fmt.format(epoch));

        // java.sql.TimestampはvalueOfを使うとDateFormatとか作らなくても狙った時間の初期化ができる。
        // ただしフォーマットはyyyy-mm-dd hh:mm:ss[.fffffffff]固定。
        System.out.println(fmt.format(Timestamp.valueOf("1970-01-01 00:00:00")));
    }
}
実行結果
1970-01-01 00:00:00
1970-01-01 00:00:00

結局表示に使うのであれば文字列としての日付型をparseする方法がベターなのかな?

17
14
2

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
17
14