-1

We have to do some security check for which we are getting some date from some part of our code and then we are calculating the difference in days

String userDate = EncryptUtil.getInstance().decrypt(Constants.USER_DATE);
String currentDate = new SimpleDateFormat("dd/MM/yyyy").format(calendar.getTime());

long startTime = new Date(userDate).getTime();
long presentTime = new Date(currentDate).getTime();
long diffTime = presentTime - startTime;
long diffDays = diffTime / (1000 * 60 * 60 * 24);

The userDate value is coming 03/06/2017 and currentDate is 07/06/2017, both are correct, but when I'm calculating day difference (diffDays) it is giving a difference of 122, where it should be actually 4. I don't understand why? Can anybody help.

Arun Sudhakaran
  • 2,167
  • 4
  • 27
  • 52
  • 6
    This looks _very_ dodgy to me `EncryptUtil.getInstance().decrypt`. In any case, **don't** use `Date` with the `String` constructor. In fact **don't** use the old API at all. Use a [`DateTimeFormatter `](https://docs.oracle.com/javase/8/docs/api/java/time/format/DateTimeFormatter.html) to get a [`ZonedDateTime`](https://docs.oracle.com/javase/8/docs/api/java/time/ZonedDateTime.html) then calculate a [`Duration`](https://docs.oracle.com/javase/8/docs/api/java/time/Duration.html). This code is awful. – Boris the Spider Jun 07 '17 at 06:59
  • @Boris the Spider can you please tell me from which package should I import DateTimeFormatter – Arun Sudhakaran Jun 07 '17 at 07:05
  • I think Joda time is the way to go, please if this helps https://stackoverflow.com/questions/17940200/how-to-find-the-duration-of-difference-between-two-dates-in-java – sanoj mathew Jun 07 '17 at 07:09
  • @sanojmathew can we please stop blanket recommending Joda time! The Java 8 Date/Time API is based on JodaTime and there are very few circumstances where such recommendation are now helpful. Oh if only comments had downvotes... – Boris the Spider Jun 07 '17 at 07:12
  • 2
    Whatever you do, don't convert milliseconds into days by dividing by `(1000 * 60 * 60 * 24)`. You'll get an error of one day when your date range spans the start of daylight savings time. Remember, that if you're in a zone that uses daylight savings, there's a 23-hour day and a 25-hour day every year; and that makes a real difference to the result of this calculation. You _must_ rely on one of the date-based libraries for this calculation - you _will_ get it wrong if you do it yourself. – Dawood ibn Kareem Jun 07 '17 at 07:53
  • From [the Joda-Time homepage](http://www.joda.org/joda-time/): “Users are now asked to migrate to `java.time` (JSR-310).” – Ole V.V. Jun 07 '17 at 08:05

3 Answers3

4

Avoid the use the of the old Date API.

public static void main(String args[]) throws Exception {
    final DateTimeFormatter formatter = DateTimeFormatter.ofPattern("dd/MM/yyyy");
    LocalDate userDate = LocalDate.parse("03/06/2017", formatter);
    LocalDate currentDate = LocalDate.parse("07/06/2017", formatter);

    long days = ChronoUnit.DAYS.between(userDate, currentDate);

    System.out.printf("%s days have passed%n", days);
}

Your actual issue is that you are assuming that Date parses ddMMyyyy which is not correct, that's the European date format rather than then US one.

From the JavaDoc for Date.parse (which is used by the Deprecated(!!) String constructor):

If the number is followed by a slash, it is regarded as a month (it is decreased by 1 to produce a number in the range 0 to 11), unless a month has already been recognized, in which case it is regarded as a day of the month.

i.e. it tries to parse a month first, then a day.

Boris the Spider
  • 59,842
  • 6
  • 106
  • 166
  • but I can't import DateTimeFormatter, LocalDate, ChronoUnit as well, we are using JDK 6.0 – Arun Sudhakaran Jun 07 '17 at 07:12
  • @ArunSudhakaran then you're not on Java 8. You probably should be - public updates for Java 7 ended a long time ago! But feel free to go with [Jesper's suggestion](https://stackoverflow.com/a/44405764/2071828) for people using horribly out of date versions of Java. – Boris the Spider Jun 07 '17 at 07:13
  • sorry, but its not my place for suggestions, this is all what we are given. Thanks any ways – Arun Sudhakaran Jun 07 '17 at 07:18
  • Yes, you can import the classes in Java 6, but it requires you to know how. Get [the ThreeTen Backport](http://www.threeten.org/threetenbp/) and import the classes from the `org.threeten.bp` package (with subpackage `format`) (that’s Threeten for JSR-310). – Ole V.V. Jun 07 '17 at 08:09
1

It seems that your date is parsed not as ddMMyyyy, but as MMddyyyy format. That's why difference in days give you ~4 months, instead of 4 days.

You can stop using Deprecated API (new Date(String) is deprecated since Java 1.1) and start using fresh java time classes https://docs.oracle.com/javase/8/docs/api/java/time/package-summary.html

1

Don't rely on the constructor of java.util.Date that takes a string. It's deprecated, so you should not be using it anyway. Parse the string using SimpleDateFormat:

DateFormat fmt = new SimpleDateFormat("dd/MM/yyyy");
long startTime = fmt.parse(userDate).getTime();

Also, what you are doing with currentDate is an unnecessarily complicated and roundabout way to get the timestamp in milliseconds from calendar. You could just do this:

long presentTime = calendar.getTime().getTime();

No need for the variable currentDate.

Better yet would be to use the Java 8 date and time API (package java.time) instead of the old java.util.Date and java.util.Calendar classes.

Jesper
  • 202,709
  • 46
  • 318
  • 350
  • thats right I can get current date from Calendar, but what about the other String date? How will I calculate the time for that – Arun Sudhakaran Jun 07 '17 at 07:07
  • 1
    @ArunSudhakaran Parse the string into a `Date` object by calling `parse()` on a `SimpleDateFormat`. When you have a `Date` object, call `getTime()` on it to get the timestamp in milliseconds. – Jesper Jun 07 '17 at 08:33