3

I have two epoch timestamps, I am trying to find the number of days between the two timestamps.

This is what I have now:

dateFrom = inputEntry.getValue(inputFields(0).get).asInstanceOf[String].toLong
dateTo =inputEntry.getValue(inputFields(1).get).asInstanceOf[String].toLong

Example:

dateFrom    dateTo      result
1501583232  1501641000  1
1501583232  1501986600  5

I am starting with two epoch dates here

d_luffy_de
  • 967
  • 1
  • 9
  • 24
  • 2
    Possible duplicate of [Get the number of days, weeks, and months, since Epoch in Java](https://stackoverflow.com/questions/6158053/get-the-number-of-days-weeks-and-months-since-epoch-in-java) – Jozef Dúc Aug 01 '17 at 12:16
  • That is not a duplicate. This Question starts with a count of seconds from epoch. – Basil Bourque Aug 01 '17 at 12:18
  • that is true, but it is easily extendable to count days between two dates by subtracting these days from epoch – Jozef Dúc Aug 01 '17 at 12:20
  • 1
    "Easily extendable" does not make for an "exact duplicate" per Stack Overflow requirements. Converting a count of seconds to dates is way too big a challenge to ignore. – Basil Bourque Aug 01 '17 at 12:34

2 Answers2

3

tl;dr

ChronoUnit.DAYS.between( … , … )

Details

This has been covered many times already on Stack Overflow. So briefly here…

For date-time values, use date-time objects. Use java.time classes only, avoid the troublesome legacy date-time classes ( Date, Calendar, etc).

Do you mean a difference of dates or a difference of 24-hour chunks of time?

I'll go with dates here.

First, translate what appears to be number of whole seconds since an epoch reference date of 1970-01-01T00:00:00Z into a point in the timeline in UTC.

Note the L on the end of numeric literal to indicate a long rather than int.

Instant instant = Instant.ofEpochSecond( 1_501_583_232L ) ; 

Assign time zone for which you want to consider dates.

ZoneId z = ZoneId.of( "America/Montreal" ) ;
ZonedDateTime zdt = instant.atZone( z );

Convert to a date-only.

LocalDate ld = zdt.toLocalDate() ;

Get difference.

long days = ChronoUnit.DAYS.between( ld , ld2 ) ;
Basil Bourque
  • 303,325
  • 100
  • 852
  • 1,154
1

To get the results you want, you must define how you're going to calculate the difference.

Taking your first example (difference between 1501583232 and 1501641000 should be 1 day):

The epochs 1501583232 and 1501641000 are the number of seconds since 1970-01-01T00:00Z, so they are equivalent to the following UTC dates:

1501583232: 2017-08-01T10:27:12Z
1501641000: 2017-08-02T02:30:00Z

Note that the difference between them is 16 hours, 2 minutes and 48 seconds (so, less than a day). If you get the difference in days, technically it will be zero.

But if you consider only the dates (2017-08-01 and 2017-08-02) and ignore the time (hour/minute/second), then the difference can be either zero or 1, depending on the timezone you are.

If you consider only the UTC dates (2017-08-01 and 2017-08-02), the difference is 1 day.

But if you take the same UTC dates above in America/Los_Angeles timezone, you'll get:

1501583232: 2017-08-01T03:27:12-07:00
1501641000: 2017-08-01T19:30-07:00

Now the difference is zero days, no matter if you consider only the date (both are 2017-08-01), or the date and time (the difference in hours will be 16, less than a day).

So, you must define how you're going to calculate the difference (consider only the date, or both date and time, and what timezone will be used).


In your case, it seems that you're considering only the date and ignoring the time, but it's not clear what timezone it's using. Anyway, you can use JDK's 8 new java.time API for that (for JDK <= 7 you can use the ThreeTen Backport - The code below works for both. The only difference is the package names (in Java 8 is java.time and in ThreeTen Backport (or Android's ThreeTenABP) is org.threeten.bp), but the classes and methods names are the same).

The code is basically the same of @BasilBourque's answer, because it's very straighforward with the new API (I just wanted to add the insights above).

First you create the Instant's from the epoch values:

Instant instant1 = Instant.ofEpochSecond(1501583232L);
Instant instant2 = Instant.ofEpochSecond(1501641000L);

If you want the difference considering the date and time, you can use:

ChronoUnit.DAYS.between(instant1, instant2);

The result will be zero.

If you want to consider only the dates in UTC (and ignore the time), just do:

// convert to UTC and get just the date (day/month/year)
LocalDate d1 = instant1.atZone(ZoneOffset.UTC).toLocalDate();
LocalDate d2 = instant2.atZone(ZoneOffset.UTC).toLocalDate();
long days = ChronoUnit.DAYS.between(d1, d2);

The result will be 1.

To convert to a different timezone (instead of UTC), use the ZoneId class:

// use a specific timezone
ZoneId zone = ZoneId.of("Asia/Kolkata");
// convert the Instant to a timezone and get only the date
LocalDate d1 = instant1.atZone(zone).toLocalDate();
LocalDate d2 = instant2.atZone(zone).toLocalDate();
long days = ChronoUnit.DAYS.between(d1, d2);

In this case, the difference is 1, but as I said above, different timezones can produce different results (can be either zero or 1 - for example, changing the code above to ZoneId.of("America/Los_Angeles"), the result is zero).


Note that the API uses IANA timezones names (always in the format Region/City, like Asia/Kolkata or Europe/Berlin). Avoid using the 3-letter abbreviations (like CST or IST) because they are ambiguous and not standard.

You can get a list of available timezones (and choose the one that fits best your system) by calling ZoneId.getAvailableZoneIds().

You can also use the system's default timezone with ZoneId.systemDefault(), but this can be changed without notice, even at runtime, so it's better to explicity use a specific one.