Excel に日付列がありますが、Java アプリケーションでそれを読み取ると、値が数値として取得されます。
例
エクセル日付
1/1/2013
私はそれを
41275.00
Java アプリケーションで数値を日付に変換する方法は?
Excel の日付を Java の日付に変換する最小限の実例を次に示します。
Date javaDate= DateUtil.getJavaDate((double) 41275.00);
System.out.println(new SimpleDateFormat("MM/dd/yyyy").format(javaDate));
返す
01/01/2013
次のパッケージもインポートする必要があります。
java.text.SimpleDateFormat
java.util.Date
Apache POI には、そのhttp://poi.apache.org/apidocs/org/apache/poi/ss/usermodel/DateUtil.html、特にhttp://poi.apache.org/apidocs/org/apache/用のユーティリティがいくつかあります。 poi/ss/usermodel/DateUtil.html#getJavaDate(double)
メモ Excel では、日付は 1900 年 (場合によっては 1904 年から) からの日数 (および小数点以下の日数) として保存されます。http://support.microsoft.com/kb/180162を参照してください。
多くのユーザーがすでに指摘しているように、Excel は日付と時刻を1900 年 1 月 0日からの日数と 24 時間の 1 日の小数部分を表す数値として格納しますddddd.tttttt
。
これは、シリアル日付またはシリアル日付/時間と呼ばれます。
ただし、ここでの回答は、既存のライブラリからすぐに使用できるメソッドを指摘することを除いて、ストーリーの一部にすぎません。
Microsoft からのリンクされたドキュメントでは、これ以上明確になりません。
MS DATEVALUE 関数は次のように述べています。
Excel では、計算に使用できるように、日付を連番として保存します。デフォルトでは、1900 年 1 月 1 日はシリアル番号 1 で、2008 年 1 月 1 日は 1900 年 1 月 1 日から 39,447 日後なのでシリアル番号 39448 です。
さて、私はこの声明をチェックするつもりです:
LocalDate testDate = LocalDate.of(1900, Month.JANUARY, 1).plusDays(39447);
System.out.println(testDate);// prints 2008-01-02
1900 年 1 月 1日から 39,447 日後、実に2008 年 1 月 2 日です。
何故ですか?
Excel の日付がエポック(1899 年 12 月 30 日または 1900 年または 1904 年 1 月 1 日など)から始まる日数で表されるという事実は、話の一部にすぎません。
私はここで究極の答えを見つけました: Dates And Times In Excel (何人かの神または誰がこれらの人を祝福するかもしれません)。
Excel で日付ルーチンを実装した開発者は、 Lotus 1-2-3の同じ既知の問題との互換性のために、意図的にバグを導入しました。
彼らは 1900 年をうるう年として扱いましたが、そうではありません。したがって、1900 年 1 月 28 日を超える日付は実際の日付よりも 1 日多くなります。
これが、Excel が2008 年 1 月 1 日を数値 39448 で表していると考える理由です。これは、1900 年 1 月 0 日から 39,448 単位であるためです(はい、Excelはゼロと見なします) 。
Excel では、シリアル日付の日付部分を 1904 年 1 月 0 日からの日数として扱うこともできます。このモードは1904 モードまたは1904 システムと呼ばれ、Macintosh システムとの互換性のために使用されます。
Excel の日付にはタイム ゾーン情報が含まれていないため (数字のみ)、LocalDate
/などの Java クラスを使用LocalDateTime
して、タイム ゾーン情報なしでそのような値を表現することをお勧めします。
実際には、今日の日付については、1900 年 12 月 30 日から始まる Excel エポックを計算できるかもしれませんが、そうではありません。
Excel のデモ- 日付形式はdd/mm/yyyy
日付は左側の数字として挿入されます
必要な変換に適したクラス:
public class SerialDate {
//days from 1899-12-31 to Instant.EPOCH (1970-01-01T00:00:00Z)
public static final long EPOCH = -25568L;
private long serialDays;
private double serialTime;
private long epochDays;
private long daySeconds;
/**
* @param date number of Excel-days since <i>January 0, 1899</i>
*/
public SerialDate(long date) {
serialDays = date;
if (date > 59)//Lotus123 bug
--date;
epochDays = EPOCH + date;
}
/**
* @param date number of days since <i>January 0, 1899</i> with a time fraction
*/
public SerialDate(double date) {
this((long)date);
serialTime = date - serialDays;
daySeconds = Math.round(serialTime * 24 * 60 * 60);
}
/**
* @return days since 1970-01-01
*/
public long toEpochDays() {
return epochDays;
}
/**
* @return seconds of the day for this SerialDate
*/
public long toDaySeconds() {
return daySeconds;
}
/**
* @return a value suitable for an Excel date
*/
public double getSerialDate() {
return serialTime + serialDays;
}
}
使用例:
LocalDate dt = LocalDate.ofEpochDay(new SerialDate(41275).toEpochDays());
System.out.println(dt);//prints 2013-01-01
SerialDate sd = new SerialDate(33257.415972222225);
LocalDateTime dt = LocalDateTime.of(
LocalDate.ofEpochDay(sd.toEpochDays()),
LocalTime.ofSecondOfDay(sd.toDaySeconds()));
System.out.println(dt);//prints 1991-01-19T09:59