5

Java 時間 (1970 年 1 月 1 日 UTC からのミリ秒) があり、Excel が正しく解釈してフォーマットできるように、その時間を csv ファイルに書き込みたいと考えています。私は、Excelがフォーマットとして「シリアル日付時刻」を使用していることを理解しています.

これでタイムゾーンと夏時間の処理を理解できません。

このページでは、Excel エポック (1900 年 1 月 1 日) はローカル (=Excel ファイルを作成するコンピューター?) タイムゾーンに基づいていると述べています。これは、シリアル日付は、それを作成したコンピューターのタイムゾーンに関する情報がなければ、一意の瞬間を示さないことを意味します。私が選んだものではありませんが、OKです。

これを受け入れて、次のJavaコードでJava時間をExcelのシリアル日付に変換できると信じていました(注:私はチューリッヒ、CETタイムゾーンにいます):

private static final long ONE_HOUR= 60L * 60 * 1000;
private static final long ONE_DAY = 24 * ONE_HOUR;
private static final long excelEpoch; 
static{
    Calendar cal;
    cal = Calendar.getInstance(TimeZone.getTimeZone("Europe/Zurich"));
    cal.set(Calendar.YEAR, 1900);
    cal.set(Calendar.DAY_OF_YEAR, 1);
    cal.set(Calendar.HOUR_OF_DAY, 0);
    cal.set(Calendar.MINUTE, 0);
    cal.set(Calendar.SECOND, 0);
    cal.set(Calendar.MILLISECOND, 0);

    excelEpoch = cal.getTimeInMillis();
}
private static String formatForExcel(long time){
    return ""+(time-excelEpoch)/(double)ONE_DAY;
}

これを使用して、数回印刷できます。

public static void main(String[] args) {
    String sep = "\t"; // csv field separator

    SimpleDateFormat fmt = new SimpleDateFormat("HH:mm:ss d/M/yyyy");       
    fmt.setTimeZone(TimeZone.getTimeZone("Europe/Zurich"));


    System.out.println("Time in ms since 1/1/1970 UTC"+ sep + "Time as string" + sep + "Excel serial" + sep + "Excel serial formatted by excel");
    long startTime = 1332630000000L; // 25/3/2012 00:00 CET , shortly before change from winter time to DST
    for (long t = startTime;  t < startTime + 4*ONE_HOUR; t+=ONE_HOUR) {
        System.out.println(t + sep + fmt.format(new Date(t)) + sep + formatForExcel(t) + sep + formatForExcel(t));
    }
}

どちらが返されますか

Time in ms since 1/1/1970 UTC   Time as string  Excel serial    Excel serial formatted by excel
1332630000000   00:00:00 25/3/2012  40991.0 40991.0
1332633600000   01:00:00 25/3/2012  40991.041666666664  40991.041666666664
1332637200000   03:00:00 25/3/2012  40991.083333333336  40991.083333333336
1332640800000   04:00:00 25/3/2012  40991.125   40991.125

冬時間から DST への変更は、これらの時間に発生することに注意してください (2 番目の列を確認してください。時間 2 が欠落しています)。

ここで混乱が生じます。これをExcelに貼り付け、最後の列で「セルの書式設定...」を選択してから「時間」(任意の形式)を選択すると、次のように出力されます。

Time in ms since 1/1/1970 UTC   Time as string  Excel serial    Excel serial formatted by excel
1332630000000   25.03.2012 00:00    40991   0:00:00
1332633600000   25.03.2012 01:00    40991.04167 1:00:00
1332637200000   25.03.2012 03:00    40991.08333 2:00:00
1332640800000   25.03.2012 04:00    40991.125   3:00:00

シリアル日付の書式設定に優れていることに注意してください。DST には変更されません。したがって、これは壁時計の時間ではありません。

簡単に言えば:

Java時間をExcelに変換して機能させるにはどうすればよいですか?

4

2 に答える 2

5

Excelは実際にはタイム ゾーンを考慮していないと思います。考えられるすべての日付/時刻が有効な「現地時間」として扱っているだけだと思います。(Joda Time の用語では「ローカル インスタント」だと思いますが、それがどの程度広く使用されているかはわかりません。)

特定の瞬間を表す方法はないと思います。代わりに、次のことを行う必要があります。

  • 現地時間として表現したい任意の日付/時刻を取ります(例: "2012 年 3 月 25 日、午前 3 時")
  • CalendarそれをUTCを使用するように設定されたに入れます
  • からミリ秒を取るcalendar.getTime().getTime()
  • 1900-01-01T00:00:00Z の「Excel エポック」値を引きます (ここでも、UTC に設定されたカレンダーを介して取得します)。
  • 「ミリ秒/日」で割る

また、1900 年 3 月 1 日より前の日付の処理という点で、Excel には奇妙な点ありますが、それが問題にならないことを願っています。

于 2013-01-23T09:17:51.083 に答える
0

浮動小数点の「シリアル日付/時刻」を「1970/1/1 以降のミル」に変換します

注: daysFrom1900to1970 は Google スプレッドシートの日付で機能しますが、Excel では若干の調整が必要になる場合があります

                            int daysFrom1900to1970 =365*70 + 19; // Or maybe =365*70 + 17 But 19 worked.
                            int millisPerDay = 1000 * 60 * 60 * 24;
                            long millisSince1970 = (long) ((timeToSend.doubleValue() - daysFrom1900to1970) * millisPerDay );

                            Calendar dateTimeToSend = Calendar.getInstance();                               
                            dateTimeToSend.setTimeZone(TimeZone.getTimeZone("GMT"));
                            dateTimeToSend.setTimeInMillis(millisSince1970);
                            System.out.println("timeToSend:"+ new SimpleDateFormat("yyyy.MM.dd HH:mm:ss z").format(dateTimeToSend.getTime()));         
于 2013-04-24T02:58:30.450 に答える