SimpleDateFormat フォーマッタを Calendar オブジェクトで初期化していないため、デフォルトのフォーマッタを使用してマッピングを行っています。このデフォルトのカレンダーは DST を認識していると思います。これは、DST 調整が減算で相殺されるため、datetimes を .parse() した場合には明らかになりません。
結果を HMS 形式に変換すると、フォーマッタは DST 調整を再度適用します。このステップでは減算がないため、結果に表示されます。
誰かが日付計算の質問をするときはいつでも、ラバースタンプ、ひざまずいた反射反応は「JodaTime を使用してください」であるように私には思えます。私たちは皆、JodaTime が大好きです。これはよくできた API です。しかし、それを使用することは依然として外部依存であり、必要でない限り使用しないでください。私の意見では、この状況では JodaTime はまったく必要ありません...必要なのは、日時を日付に解析するための Java Calendar API だけです。そして、それはあなたがそれを必要とするすべてです。
ミリ秒単位で違いが得られたら、フォーマッターを使用して結果を元に戻すことは避けてください。単純な算術演算を使用すると、はるかにパフォーマンスが向上します。
private static final SimpleDateFormat DATE_FORMAT =
new SimpleDateFormat("d MMM yyyy HH:mm:ss.SSS");
private static final int DAYS = 0;
private static final int HOURS = 1;
private static final int MINUTES = 2;
private static final int SECONDS = 3;
private static final int MILLIS = 4;
private final int[] result = new int[MILLIS];
public String calculateDuration(String startDateStr, String endDateStr){
try {
Date startDate = DATE_FORMAT.parse(startDateStr);
Date endDate = DATE_FORMAT.parse(endDateStr);
} catch (Exception e) { /* exception processing */ }
long diff = endDate.getTime() - startDate.getTime();
double d;
for (int i = DAYS; i <= MILLIS; i++) {
switch(i) {
case DAYS:
d = ((double) diff) / (86400.0 * 1000.0);
break;
case HOURS:
d = d * 24.0; break;
case MINUTES: case SECONDS:
d = d * 60.0; break;
case MILLIS:
d = d * 1000.0; break;
}
result[i] = (int) Math.floor(d);
d = d - (double) result[i];
}
この最後のfor
ループの終わりに、配列result
には、日付の減算から得られた DAYS、HOURS、MINUTES、SECONDS、および MILLIS の数に対応する整数が含まれます。この結果を得るために、オブジェクトを作成、割り当て、または呼び出す必要はありません。String.format()
関数を使用して、これらの整数を選択した文字列形式に簡単に変換できるようになりました。