[java] 2020 년 3 월 30 일과 2020 년 3 월 1 일의 차이로 인해 29 일 대신 28 일이 잘못되는 이유는 무엇입니까?

TimeUnit.DAYS.convert(
   Math.abs(
      new SimpleDateFormat("dd-MM-yyyy HH:mm:ss").parse("30-03-2020 00:00:00").getTime() -
      new SimpleDateFormat("dd-MM-yyyy HH:mm:ss").parse("1-03-2020 00:00:00").getTime()
   ),
   TimeUnit.MILLISECONDS)

결과는 28이지만 29 여야합니다.

시간대 / 위치가 문제가 될 수 있습니까?



답변

문제는 2020 년 3 월 8 일 일요일의 일광 절약 시간제 변경으로 인해 해당 날짜 사이에 28 일 및 23 시간 이 있다는 것입니다. TimeUnit.DAYS.convert(...) 깎다결과를 28 일로 .

문제를 보려면 (미국 동부 표준시입니다) :

SimpleDateFormat fmt = new SimpleDateFormat("dd-MM-yyyy HH:mm:ss");
long diff = fmt.parse("30-03-2020 00:00:00").getTime() -
            fmt.parse("1-03-2020 00:00:00").getTime();

System.out.println(diff);
System.out.println("Days: " + TimeUnit.DAYS.convert(Math.abs(diff), TimeUnit.MILLISECONDS));
System.out.println("Hours: " + TimeUnit.HOURS.convert(Math.abs(diff), TimeUnit.MILLISECONDS));
System.out.println("Days: " + TimeUnit.HOURS.convert(Math.abs(diff), TimeUnit.MILLISECONDS) / 24.0);

산출

2502000000
Days: 28
Hours: 695
Days: 28.958333333333332

수정하려면 DST가없는 시간대 (예 : UTC)를 사용하십시오 .

SimpleDateFormat fmt = new SimpleDateFormat("dd-MM-yyyy HH:mm:ss");
fmt.setTimeZone(TimeZone.getTimeZone("UTC"));
long diff = fmt.parse("30-03-2020 00:00:00").getTime() -
            fmt.parse("1-03-2020 00:00:00").getTime();

산출

2505600000
Days: 29
Hours: 696
Days: 29.0


답변

이 문제의 원인은 Andreas의 답변 에 이미 언급되어 있습니다.

문제는 무엇을 정확하게 계산합니다. 실제 차이가 28이 아니라 29 여야한다고 말하고 “위치 / 지역 시간이 문제가 될 수 있는지 묻는 것은 실제로 계산하고자하는 내용을 나타냅니다. 분명히 시간대 차이를 없애고 싶습니다.

시간과 시간대없이 요일 만 계산하려고한다고 가정합니다.

자바 8

아래에서 사이의 일 수를 올바르게 계산하는 방법의 예에서 나는 시간과 시간대가없는 날짜 –를 정확하게 나타내는 클래스를 사용하고 LocalDate있습니다.

DateTimeFormatter formatter = DateTimeFormatter.ofPattern("d-MM-yyyy HH:mm:ss");
LocalDate start = LocalDate.parse("1-03-2020 00:00:00", formatter);
LocalDate end = LocalDate.parse("30-03-2020 00:00:00", formatter);

long daysBetween = ChronoUnit.DAYS.between(start, end);

그 주 ChronoUnit, DateTimeFormatter그리고 LocalDate받는 사람에 따라, 당신에게 사용할 수없는 자바 8, 적어도이 필요합니다 태그를. 그러나 아마도 미래의 독자들에게 해당 될 것입니다.

Ole VV에서 언급했듯이 Java 8 Date and Time API 기능을 Java 6 및 7로 백 포트 하는 ThreeTen Backport 도 있습니다 .


답변