In continuation of this post covering the temporal classes – LocalDate, LocalTime and LocalDateTime, today we’ll be covering the Period class which is also on the OCA Java 8 Exam.
Period class also belongs to java.time package. It represents a date-based amount of time in terms of years, months, and days eg : ‘P2Y4M8D‘ signifies 2 years, 4 months and 8 days.Much like all other temporal classes, it is immutable and hence thread-safe. It also exposes static of() method for instantiating its objects along with some other available options.The values can be positive or negative.
static Period of(int years, int months, int days) static Period ofYears(int years) static Period ofMonths(int months) static Period ofWeeks(int weeks) static Period ofDays(int days) //Example usage of above methods : Period p = Period.of(3, 5, 12); System.out.println(p);//P3Y5M12D- represents 3yrs, 5months & 12days Period p1 = Period.ofYears(10); //P10Y - represents 10yrs Period p2 = Period.ofMonths(14);//P14M - represents 14 months Period p3 = Period.ofDays(40);//P40D - represents 40 days Period p4 = Period.ofWeeks(2); //P14D - represents 14 days static Period between(LocalDate startDateInclusive, LocalDate endDateExclusive) //Example usage of between() method LocalDate d1 = LocalDate.of(2017, 3, 2); LocalDate d2 = LocalDate.of(2018, 3, 2); Period period12 = Period.between(d1, d2); // P1Y Period period21 = Period.between(d2, d1); // P-1Y //throws DateTimeParseException if text cannot be parsed as a Period static Period parse(CharSequence text) //Example usage of parse() method Period period2 = Period.parse("P1Y17M20D"); // 1 year, 17 months, 20 days Period period3 = Period.parse("P40D");// 40 days Period period4 = Period.parse("P5W");// 35 days (5 weeks) Period period5 = Period.parse("P-5W");// -35 days Period period4 = Period.parse("-P2Y5D");// same as 'P-2Y-5D',-2 years & -5 days Period pX = Period.parse("P24H"); // java.time.format.DateTimeParseException
The parse() method accepts strings of the format PnYnMnD or PnW where n represents a number and letters P,Y,M,D,W represents period, year, month, day and week respectively.The letters can exist in lower or upper-case. Each string must start with ‘P’ or ‘p’ and must include at-least one of the four sections – year, month, day or week.
As you know, period values can be negative. The parse() method allows to parse such a value. If you precede the complete argument value with ‘- ‘sign, it will be applied to all the values.
Another noteworthy point is that chaining of methods ofYears(),ofMonths(),ofDays() etc doesn’t produces the required result. Try it out.
Period period = Period.ofYears(5).ofMonths(10).ofDays(35); // P35D. Logical error. System.out.println(period);
Following are some methods exposed by the API for querying purposes. They do exactly what their name suggest so we’ll avoid to discuss about them in much detail.
//Determines if any of the date based values is negative boolean isNegative() //Determines whether all date-based values are zero boolean isZero() //Compares a Period object with any other object boolean equals(Object obj) //Returns total number of months including year and month values,day value is simply ignored long toTotalMonths() //Returns specific date-based value int getYears() int getMonths() int getDays()
Period class overrides equals() method from Object class. It is important to remember that this method compares each date-based value individually and they must match for this method to return true.For instance, periods ‘P1Y5M’ is not equal to ‘P17M’ and likewise.
Period p1 = Period.of(1, 14, 0); Period p2 = Period.ofMonths(26); System.out.println(p1.equals(p2)); // false
Period class provides withXXX() methods to return a modified copy of this object (as a new object, of-course, Remember : Period is immutable).
//sets specific date unit to the specified value Period withYears(int years) Period withMonths(int months) Period withDays(int days)
Below are some temporal arithmetic methods you need to know for OCA Java 8 Exam.
//only alters that specific date based value, leaving rest of it as-is Period minusYears/plusYears(long years) Period minusMonths/plusMonths(long months) Period minusDays/plusDays(long days) //TemporalAmount is an interface implemented by Period //This method throw DateTimeException is operation fails //It doesn't performs any normalization Period minus/plus(TemporalAmount amount) //Returns a copy of the Period with month and years normalized, no impact on days Period normalized() //returns a new period with all date-based values negated Period negated() //returns a new Period with each date based value multiplied by scalar Period multipliedBy(int scalar)
LocalDate & LocalDateTime also provides methods plus() and minus() which takes a Period argument and performs the manipulation based on the specified argument.
LocalDate date = LocalDate.of(2018, 01, 31); System.out.println(date.plus(Period.ofDays(1)));// 2018-02-01 LocalDateTime dateTime = LocalDateTime.parse("2018-01-31T12:15:30"); System.out.println(dateTime.plus(Period.ofMonths(1)));//2018-02-28T12:15:30 LocalDate date = LocalDate.of(2018, 01, 31); System.out.println(date.minus(Period.ofWeeks(4)));//2018-01-03
LocalTime cannot be used along with Period as it doesn’t contains any date-based value.
I know this article is a little too packed, covering a lot of details. But with a little practice, you are all set to answer any question on this topic. Keep on reviewing the concepts till you get it all. I am planning to cover DateTimeFormatter in the next blog post. Stay tuned!