I'm using openjdk version 1.8.0_112-release for development but will need to support previous JDK versions too (pre-Java-8) - so can't use java.time
.
I am writing a utitily class to calculate the date to see if a saved date is before the current date which means its expired.
However, I am not sure I have done this the correct way. I am using LocalDate
class to calculate the days. The expiration is counted starting from the date and time the user clicked save. That date will be saved and a check will be done against this saved date and time and the current date and time i.e. when the user logs in.
Is this the best way to do it? I would like to keep to the LocalDate
class.
import org.threeten.bp.LocalDate;
public final class Utilities {
private Utilities() {}
public static boolean hasDateExpired(int days, LocalDate savedDate, LocalDate currentDate) {
boolean hasExpired = false;
if(savedDate != null && currentDate != null) {
/* has expired if the saved date plus the specified days is still before the current date (today) */
if(savedDate.plusDays(days).isBefore(currentDate)) {
hasExpired = true;
}
}
return hasExpired;
}
}
I'm using the class like this:
private void showDialogToIndicateLicenseHasExpired() {
final LocalDate currentDate = LocalDate.now();
final int DAYS_TO_EXPIRE = 3;
final LocalDate savedDate = user.getSavedDate();
if(hasDateExpired(DAYS_TO_EXPIRE, savedDate, currentDate)) {
/* License has expired, warn the user */
}
}
I am looking a solution that will take in account time zones. If a license was set to expire in 3 days, and the user was to travel to a different time zone. i.e. they could be ahead or behind based on hours. The license should still expire.
You can use
ChronoUnit.DAYS
(inorg.threeten.bp.temporal
package, or injava.time.temporal
if you use java 8 native classes) to calculate the number of days between the 2LocalDate
objects:Edit (after bounty explanation)
For this test, I'm using threetenbp version 1.3.4
As you want a solution that works even if the user is in a different timezone, you shouldn't use
LocalDate
, because this class doesn't handle timezone issues.I think the best solution is to use the
Instant
class. It represents a single point in time, no matter in what timezone you are (at this moment, everybody in the world are in the same instant, although the local date and time might be different depending on where you are).Actually
Instant
is always in UTC Time - a standard indepedent of timezone, so very suitable to your case (as you want a calculation independent of what timezone the user is in).So both your
savedDate
andcurrentDate
must beInstant
's, and you should calculate the difference between them.Now, a subtle detail. You want the expiration to happen after 3 days. For the code I did, I'm making the following assumptions:
The second assumption is important for the way I implemented the solution. I'm considering the following cases:
currentDate
is less than 72 hours aftersavedDate
- not expiredcurrentDate
is exactly 72 hours aftersavedDate
- not expired (or expired? see comments below)currentDate
is more than 72 hours aftersavedDate
(even by a fraction of a second) - expiredThe
Instant
class has nanosecond precision, so in case 3 I'm considering that it's expired even if it's 1 nanosecond after 72 hours:Note that I used
ChronoUnit.DAYS.getDuration().toNanos()
to get the number of nanoseconds in a day. It's better to rely on the API instead of having hardcoded big error-prone numbers.I've made some tests, using dates in the same timezone and in different ones. I used
ZonedDateTime.toInstant()
method to convert the dates toInstant
:PS: for case 2 (
currentDate
is exactly 72 hours after savedDate - not expired) - if you want this to be expired, just change theif
above to use>=
instead of>
:If you don't want nanosecond precision and just want to compare the days between the dates, you can do as in @Ole V.V's answer. I believe our answers are very similar (and I suspect that the codes are equivalent, although I'm not sure), but I haven't tested enough cases to check if they differ in any particular situation.