4

Using LocalDate, I got the difference expressed in a Period instance. For example:

LocalDate born = LocalDate.of(1990, Month.SEPTEMBER, 30);
Period myAge = Period.between(born, LocalDate.now());
System.out.println("My age is: "+myAge.getYears()+" years "+myAge.getMonths()+" months "+myAge.getDays()+" days.");

Output:

My age is: 26 years 6 months 23 days

So, I was using period to get the age in years, months and days.

I would like to do the same with ZoneDateTime using two time zones (US/Pacific and Australia/Melbourne). For example:

ZonedDateTime now = ZonedDateTime.now(); // US/Pacific

LocalDate date = LocalDate.of(1990, Month.SEPTEMBER, 30);
LocalTime time = LocalTime.of(23, 55);
ZoneId zone = ZoneId.of("Australia/Melbourne");
ZonedDateTime born = ZonedDateTime.of(date, time, zone);

I would like to get the same output as I got with LocalDate. What should I do? Does it make sense?

Expected output:

My age is: 26 years 6 months 24 days

Basil Bourque
  • 303,325
  • 100
  • 852
  • 1,154
jmgoyesc
  • 2,677
  • 1
  • 18
  • 16
  • 2
    The issue is you will need to decide things like rounding of hours to days, and in which time zone to count; because of different DST rules, the counts in the two zones may not agree. – Ole V.V. Apr 22 '17 at 01:09

3 Answers3

4

The first line of Period documentation state that it is a date based amount of time in ISO-8601 format. It is not meant to be used with XXXTime.

However, ZonedDateTime offer you an until method which will return the number of a given ChronoUnit until another Temporal (now in your case).

For example :

born.until(now, ChronoUnit.YEARS);

would return 26.

One trick is to add the difference retrieved to the starting date and then process the next ChronoUnit

For example :

long years = born.until(now, ChronoUnit.YEARS);
born = born.plusYears(years);

long months = born.until(now, ChronoUnit.MONTHS);
born = born.plusMonths(months);

long days = born.until(now, ChronoUnit.DAYS);

And then you can print your variables.

Basil Bourque
  • 303,325
  • 100
  • 852
  • 1,154
Jean-François Savard
  • 20,626
  • 7
  • 49
  • 76
3

Rather than using a ZonedDateTime for a birth date, I'd recommend storing a LocalDate and a ZoneId (ie. in separate fields/columns).

The simple answer to getting the Period from two LocalDate instances is to call toLocalDate() on both. As you'll realise, there is the problem that those ZonedDateTime instances might be in different time-zones, which might require work to normalize. But again, I'd stress that the better storage for this data is two fields - LocalDate and a ZoneId.

Period p = Period.between(born.toLocalDate(), now.toLocalDate());
// warning! the above ignores time-zones, assuming both are the same

If you need the difference between the two in Period plus Duration (for the remaining seconds), you can use this:

Period p = Period.between(born.toLocalDate(), now.toLocalDate());
Duration d = Duration.between(born.with(now.toLocalDate()), now);

The final option is to use ThreeTen-Extra. The soon to be released v1.1 will contain a class PeriodDuration that combines a Period and a Duration and allows the amount of time between two LocalDateTime instances to be stored.

JodaStephen
  • 60,927
  • 15
  • 95
  • 117
0

The primary reason you should use LocalDate to represent birthday is because everyone observes their birthday the same way, or put another way, everyone observes their birthday using the clock according to where they are currently at. If you were born in France, and right now are living in the US which has a different timezone offset, you wouldn't celebrate your birthday by observing France's current date, you would instead check the date where you are currently which is local to you. Temporal classes with timezone support should be used for events that span regions, for example, flight arrivals and departures tracking software. So using ZonedDateTime to describe birthday is not wrong, it is semantically incorrect.

Also, Period implements TemporalAmount which obviously represents a span of time. So using it to represent birthday is (again) not wrong, but it makes your intention less clear. Birthday is an exact moment on the timeline, not a duration, so all in all, LocalDate is the best choice

Trash Can
  • 6,608
  • 5
  • 24
  • 38