0

Below is giving me 279 days in local but in different server it is giving me 278 why this happening ?

String sDate = "10-11-2017";
String eDate = "16-08-2018";
Date startDate = new SimpleDateFormat(MsmConstants.DATE_FORMAT).parse(sDate);
Date endDate = new SimpleDateFormat(MsmConstants.DATE_FORMAT).parse(eDate);
long difference = startDate.getTime() - endDate.getTime();
return Math.abs(difference / (1000 * 60 * 60 * 24));
dpr
  • 10,591
  • 3
  • 41
  • 71

3 Answers3

1

This is probably coming from some kind of rounding combined with a difference in timezones.

Since both operands on the left and right of your / operator are integral types, you are actually losing precision with that operator.

If you change your expression to: (double) difference / (1000 * 60 * 60 * 24) you will notice that the result is actually: -278.9583333333333

The reason it is not exact days is because of daylight savings and similar date/time adjustments.

If on your PC you have different regional settings from the server, which do not have the same daylight savings, then you might have got a different number, which exceeded 279.

As a sidenote, the Java 7 and earlier date/time API was very buggy. SimpleDateFormat wasn't even thread safe, and there were lots of issues with daylight savings and similar situations. You should really move to Java 8. What you are doing would simply become: Duration.between(startDate, endDate) and the calculation would be done correctly for you.

String sDate = "10-11-2017";
String eDate = "16-08-2018";
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("dd-MM-yyyy");
LocalDateTime startDate = LocalDate.parse(sDate, formatter).atTime(0, 0);
LocalDateTime endDate = LocalDate.parse(eDate, formatter).atTime(0, 0);

return Duration.between(startDate, endDate).toDays();

You will see that this actually gives you 279.

jbx
  • 21,365
  • 18
  • 90
  • 144
  • Rounding is indeed imprecise due to how floating point numbers are represented internally. However, while imprecise, it is *deterministic*. The same input will yield the same output across all JVMs, or even across all IEEE 754 implementations. – Robby Cornelissen May 08 '19 at 10:23
  • 1
    @RobbyCornelissen Yes the rounding is the same across JVMs. But if the timezone is different, then that little difference in the result could result in the precision truncated to 278 in 279. – jbx May 08 '19 at 10:29
1

jbx has already in another answer explained nicely what went wrong. 10 November is in winter on the Northern hemisphere, and 16 August is in summer. Between those two dates summer time (DST) begins, which causes one day to be just 23 hours, so the difference you calculate is 1 hour short of being 279 days at you had expected and had observed locally.

java.time

Date and time math is too complicated and error-prone to do yourself the way you tried. You should always leave it to a well-proven library. Here’s the correct and modern solution.

    DateTimeFormatter dateFormatter = DateTimeFormatter.ofPattern("d-MM-uuuu");
    String sDate = "10-11-2017";
    String eDate = "16-08-2018";
    LocalDate startDate = LocalDate.parse(sDate, dateFormatter);
    LocalDate endDate = LocalDate.parse(eDate, dateFormatter);
    long difference = ChronoUnit.DAYS.between(startDate, endDate);
    System.out.println(Math.abs(difference));

Output is the expected:

279

Since your date strings haven’t got time of day, there is no reason to use LocalDateTime. LocalDate is the correct class to use. It also makes sure that no number truncation can happen since there is always a whole number of days between two dates.

Question: Will that work on Java 7?

Yes, java.time just requires at least Java 6.

  • In Java 8 and later and on newer Android devices (from API level 26) the modern API comes built-in.
  • In Java 6 and 7 get the ThreeTen Backport, the backport of the modern classes (ThreeTen for JSR 310; see the links at the bottom).
  • On (older) Android use the Android edition of ThreeTen Backport. It’s called ThreeTenABP. And make sure you import the date and time classes from org.threeten.bp with subpackages.

Links

Ole V.V.
  • 81,772
  • 15
  • 137
  • 161
0

SimpleDataFormat uses the JVM's default timezone to create Date objects. In case of daylight saving time, this might result in a +/- 1 day difference between two dates.

You have a couple of options:

  1. Explicitly set the timezone of your SimpleDateFormat objects to GMT/UTC.
  2. Explicitly set the timezone of your JVM to GMT/UTC.
  3. In Java 8, use the new java.time API; in earlier versions of Java use an alternative like Joda Time.
Robby Cornelissen
  • 91,784
  • 22
  • 134
  • 156