0

I am getting a string from service, 2 Nov 2019 07:30 pm, the date is in United States Central Time.

Now i need to know how much time is remaining between current time and this date.

I am using following code, but this is not giving accurate difference.

SimpleDateFormat ticketDateFormat = new SimpleDateFormat("MMM d yyyy hh:mm a");
Date parsedDate= null;
try {
    parsedDate= ticketDateFormat.parse(dateTimeString);

    DateFormat formatter = new SimpleDateFormat("MMM d yyyy hh:mm a");
    TimeZone timeZone = TimeZone.getTimeZone("CST");
    formatter.setTimeZone(timeZone);


    parsedDate= ticketDateFormat.parse(formatter.format(parsedDate));


    long totalTimeRemainingInMillis= Math.abs(currentDateTime.getTime()- (parsedDate.getTime()));
    long diffInHours = TimeUnit.MILLISECONDS.toHours(totalTimeRemainingInMillis);



} catch (ParseException e) {
    e.printStackTrace();
}
dev90
  • 7,187
  • 15
  • 80
  • 153
  • As an aside consider throwing away the long outmoded and notoriously troublesome `SimpleDateFormat` and friends, and adding [ThreeTenABP](https://github.com/JakeWharton/ThreeTenABP) to your Android project in order to use `java.time`, the modern Java date and time API. It is so much nicer to work with. – Ole V.V. Oct 11 '19 at 09:38
  • Could you be more precise when you say *not giving accurate difference*, please? Is it 5 % off or 25 % off? Too much or too little? Best to give one or more examples of expected and observed result so we all can see the inaccuracy for ourselves. – Ole V.V. Oct 11 '19 at 09:40
  • Just to give some context, this appears to be a follow-up question to [How to convert a time to UTC and then device local time](https://stackoverflow.com/questions/58327330/how-to-convert-a-time-to-utc-and-then-device-local-time). – Ole V.V. Oct 11 '19 at 09:44
  • 1
    You’re really overcomplicating things. Parsing your datetime string to a `Date`, formatting it to a `String` again and then parsing once more. I’d almost say that’s got to go wrong. And even more so when using the outmoded and troublesome date and time classes. As an aside: Give time zone as America/Chicago rather than CST, the latter is deprecated and also lying since it gives you CDT at this time of year. And specify locale for your formatters so they don’t depend on the default locale. – Ole V.V. Oct 11 '19 at 10:00

4 Answers4

1

Although it is not clear in your question where you are getting current time from, my guess is that the problem is in the way you are using TimeZone. You are setting the TimeZone in the formatter then parsing the date which you say is already in CST.

Here is an alternate way you can do the same thing and then compare your results:

LocalDateTime dateTime = LocalDateTime.now();
DateTimeFormatter fmt = DateTimeFormatter.ofPattern("LLL d yyyy hh:mm a");
LocalDateTime parse = LocalDateTime.parse("Nov 2 2019 07:30 PM", fmt);
System.out.println(Duration.between(dateTime, parse).toHours());
Kaus2b
  • 747
  • 4
  • 12
  • 1
    You should probably stick to `MMM` for month. In most locales it doesn’t make a difference, but if I have understood correctly, in those where it does, `MMM` is preferred when used with day of month and year. – Ole V.V. Oct 11 '19 at 09:38
0

String date "2 Nov 2019 07:30 pm" should be parsed this way:

new SimpleDateFormat("dd MMM yyyy hh:mm a")

Not this way:

new SimpleDateFormat("MMM d yyyy hh:mm a");
Saif
  • 397
  • 1
  • 9
  • Correct, but it doesn’t seem to explain nor alleviate the questioner’s problem: *this is not giving accurate difference* (and I still believe that we should avoid using `SimpleDateFormat`). – Ole V.V. Oct 11 '19 at 10:38
0

Use following code for result

                SimpleDateFormat dateFormat = new SimpleDateFormat("d MMM yyyy hh:mm a");
                TimeZone timeZone = TimeZone.getTimeZone("CST");
                dateFormat.setTimeZone(timeZone);

                Date event_date = dateFormat.parse("2 Nov 2019 07:30 pm");
                Date current_date = new Date();
                long diff = event_date.getTime() - current_date.getTime();
                long Days = diff / (24 * 60 * 60 * 1000);
                long Hours = diff / (60 * 60 * 1000) % 24;
                long Minutes = diff / (60 * 1000) % 60;
                long Seconds = diff / 1000 % 60;

                Log.i(TAG, Hours + "," + Minutes + "," + Seconds);
Mahesh Pandit
  • 348
  • 3
  • 7
0

java.time and ThreeTenABP

This will work on your Android API level:

    DateTimeFormatter formatter = new DateTimeFormatterBuilder()
            .appendPattern("d MMM uuuu hh:mm ")
            .parseCaseInsensitive()
            .appendPattern("a")
            .toFormatter(Locale.US);
    ZoneId zone = ZoneId.of("America/Chicago");

    ZonedDateTime currentDateTime = ZonedDateTime.now(zone);

    String dateTimeString = "2 Nov 2019 07:30 pm";
    ZonedDateTime dateTime = LocalDateTime.parse(dateTimeString, formatter)
            .atZone(zone);

    long diffInHours = ChronoUnit.HOURS.between(currentDateTime, dateTime);
    System.out.println("Difference in hours: " + diffInHours);

When I ran this snippet just now, the output was:

Difference in hours: 541

I am using java.time, the modern Java date and time API. It’s much nicer to work with than the old and poorly designed Date and SimpleDateFormat. On one hand parsing lowercase am and pm requires a little more code lines (since they are normally in uppercase in US locale), on the other hand java.time validates more strictly, which is always good. Advantages we get for free include: We need no time zone conversions, we can do everything in Central Time. The calculation of the difference in hours is built in, just requires one method call.

Specify locale for your formatter, or it will break when some day your code runs on a JVM with a non-English default locale. Specify US Central Time as America/Chicago. Always use this region/city format for time zones. CST is deprecated and also lying since it gives you CDT at this time of year.

Question: Doesn’t java.time require Android API level 26 or higher?

java.time works nicely on both older and newer Android devices. It 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 non-Android 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