I'm looking for a way to compare instances of LocalDate
and ZonedDateTime
in js-joda
, but those classes are not compatible. I'm willing to accept, that LocalDate
is a ZonedDateTime
with time and timezone set to zero.
What would be the easiest way to compare those two objects?
A LocalDate
has only a date (day, month and year), while the ZonedDateTime
also has a time (hour, minute, second and nanosecond) and a timezone. To compare them, you must choose which one will be converted to the other's type.
As @Dummy's answer already explains, one way is to convert the ZonedDateTime
to a LocalDate
. Supposing we have:
var z = ZonedDateTime.now(); // 2017-08-23T13:12:24.856-03:00[America/Sao_Paulo]
var dt = LocalDate.now(); // 2017-08-23
You can use the methods equals
, isBefore
or isAfter
to check if the local date (day/month/year) is the same, before or after the other
z.toLocalDate().equals(dt); // true
z.toLocalDate().isBefore(dt); // false
z.toLocalDate().isAfter(dt); // false
You can also use compareTo
, which can return -1
, 0
or 1
if the first date is before, equals or after the second one.
As told in the comments, calling toLocalDate()
discards the time and timezone information, keeping just the date (day/month/year). But as the LocalDate
has only these fields, you don't need the others to do the comparison.
To do the opposite (convert the LocalDate
to a ZonedDateTime
), you'll have to make some assumptions. The same date can represent a different instant depending on the timezone you are (right now is August 23th in São Paulo, but in Tokyo is August 24th - the timezone you choose might affect the final result).
And you'll also need to define at what time (hour/minute/second/nanosecond) this date will be. You told you can assume that LocalDate is a ZonedDateTime with time and timezone set to zero. This means that the time will be midnight (00:00) and the timezone will be UTC (offset zero):
// consider LocalDate = ZonedDateTime with time and timezone set to zero (midnight in UTC)
var z2 = dt.atStartOfDay(ZoneOffset.UTC); // 2017-08-23T00:00Z
Then you can compare:
z2.equals(z); // false: check if all fields are the same (date/time/timezone)
z2.isEqual(z); // false: check if both represent the same instant (even if timezones are different)
z2.isBefore(z); // true
z2.isAfter(z); // false
z2.compareTo(z); // -1
Note that equals
checks if all fields are the same (date, time and timezone), while all other methods compare the equivalent Instant
(even if the timezones are different, the corresponding Instant
is used to do the comparison).
In this case, z2
is 2017-08-23T00:00Z
(August 23th 2017 at midnight in UTC), while z
is 2017-08-23T13:12:24.856-03:00[America/Sao_Paulo]
, which is equivalent in UTC to 2017-08-23T16:12:24.856Z
(August 23th 2017 at 16:12:24.856 in UTC).
So, equals
returns false
because the time and timezone are different and isEquals
returns false
because they don't represent the same instant (even when converting to UTC, they're are different). isBefore
returns true
because z2
is actually before z
(midnight < 16:12) and so on.
If you want to use another timezone instead of UTC, you must use js-joda-timezone and the ZoneId
class:
// get this date at midnight in London timezone
dt.atStartOfDay(ZoneId.of("Europe/London"));
The API uses IANA timezones names (always in the format Region/City
, like America/Sao_Paulo
or Europe/Berlin
).
Avoid using the 3-letter abbreviations (like CST
or PST
) 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 will be system/browser dependent, so it's better to explicity use a specific one.