LoginSignup
2
1

More than 1 year has passed since last update.

java.sql.Dateをシリアル値に、シリアル値をjava.sql.Dateに変換してみた

Last updated at Posted at 2022-08-30

タイトルの通り、java.sql.Dateをシリアル値に、シリアル値をjava.sql.Dateに変換してみようと思います。

まずはjava.sql.Date -> シリアル値

日付のシリアル値は
・1900年1月1日を 1
・1900年1月2日を 2
・1900年1月3日を 3
と、毎日1づつ増加していくので、1899-12-30からシリアル値にしたい日付までの日数を求めれば、シリアル値を求めることができます。

↓java.sql.Date -> シリアル値に変換するコード

/**
 * 引数の日付をシリアル値に変換
 *
 * @param date 日付
 * @return シリアル値取得
 */
public static Double convertToSerialNumber(Date date) {
    if (date == null) {
        return null;
    }

    final var requestLocalDate = date.toLocalDate();
    final var baseLocalDate = Date.valueOf("1899-12-30").toLocalDate();

    return (double) ChronoUnit.DAYS.between(baseLocalDate, requestLocalDate);
}

出力結果:

log.debug(convertToSerialNumber(Date.valueOf("2022-08-30"))  // 44803

次にシリアル値→java.sql.Date

これはコード内で説明していこうと思います。

/**
 * シリアル値を日付に変換する。
 *
 * @param serialNumber シリアル値
 * @return 日付
 */
public static String parseExcelSerialNumber(String serialNumber) {
    if (serialNumber == null) {
        return null;
    }

    // 1900/1/1のシリアル値が1なので、加算する値は日付にしたいシリアル値-1になる
    int serial = new BigDecimal(serialNumber).intValue() - 1;
    // 1900/2/29は存在しないがエクセル内では存在しているらしいのでその日付以降であればさらに-1をする
    serial -= (serial > 60 ? 1 : 0);
    // Windowsでのデフォルトでは1900/1/1 12:00:00AMからなので,その時刻を表すCalendarクラスのインスタンス
    Calendar cal = Calendar.getInstance();
    cal.set(1900, 0, 1, 12, 0, 0);
    // 基準日に加算
    cal.add(Calendar.DATE, serial);

    return new Date(cal.getTime().getTime());
}

出力結果:

log.debug(parseExcelSerialNumber(Date.valueOf("44803"))  // 2022-08-30

最後に

コード上に何か疑問点があればご指摘いただけると幸いです。

2
1
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
2
1