Calculating the middle of the month – Working with Date and Time

79. Calculating the middle of the month

Let’s imagine that we have a LocalDate and we want to calculate from it another LocalDate representing the middle of the month. This can be achieved in seconds if we know that the LocalDate API has a method named lengthOfMonth() which returns an integer representing the length of the month in days. So, all we have to do is to calculate lengthOfMonth()/2 as in the following code:

public static LocalDate middleOfTheMonth(LocalDate date) {
  return LocalDate.of(date.getYear(), date.getMonth(),
    date.lengthOfMonth() / 2);      
}

In the bundled code, you can see a solution based on the Calendar API.

80. Getting the number of quarters between two dates

This is just another problem that requires us to have a deep grasp of the Java Date/Time API. This time, we talk about java.time.temporal.IsoFields which has been introduced in Problem x. One of the ISO fields is QUARTER_YEARS, which is a temporal unit representing the concept of a quarter-year. So, having two LocalDate, we can write this:

public static long nrOfQuarters(
    LocalDate startDate, LocalDate endDate) {
  return IsoFields.QUARTER_YEARS.between(startDate, endDate);
}

Feel free to challenge yourself to provide a solution for java.util.Date/Calendar.

81. Converting Calendar to LocalDateTime

In Problem x, you saw that converting a java.util.Date (date) to a LocalTime can be done as follows:

LocalTime lt = date.toInstant().atZone(zoneId).toLocalTime();

In the same manner, we can convert a java.util.Date to a LocalDateTime (here, zoneId was replaced with ZoneId.systemDefault()):

LocalDateTime ldt = date.toInstant().atZone(
  ZoneId.systemDefault()).toLocalDateTime();

We also know that we can obtain a java.util.Date from a Calendar via the getTime() method. So, by gluing the pieces of the puzzle we obtain the following code:

public static LocalDateTime
       toLocalDateTime(Calendar calendar) {
  Date date = calendar.getTime();
  return date.toInstant().atZone(
         ZoneId.systemDefault()).toLocalDateTime();
}

The same result but following a shorter path can be obtained like this:

return LocalDateTime.ofInstant(Instant.ofEpochMilli(
  calendar.getTimeInMillis()), ZoneId.systemDefault());

Or, even shorter, like this:

return LocalDateTime.ofInstant(
  calendar.toInstant(), ZoneId.systemDefault());

But, this code assumes that the time zone of the given Calendar is the default time zone. If the calendar has a different time zone (for instance, Asia/Calcutta) then we might expect back a ZonedDateTime instead of a LocalDateTime. This means that we should adjust the previous code accordingly:

public static ZonedDateTime
       toZonedDateTime(Calendar calendar) {
  Date date = calendar.getTime();
  return date.toInstant().atZone(
    calendar.getTimeZone().toZoneId());
}

Again, some shorter versions are available:

return ZonedDateTime.ofInstant(
  Instant.ofEpochMilli(calendar.getTimeInMillis()),        
    calendar.getTimeZone().toZoneId());
return ZonedDateTime.ofInstant(calendar.toInstant(),              
    calendar.getTimeZone().toZoneId());

Done!

82. Getting the number of weeks between two dates

If the given two dates are instances of LocalDate(Time) then we can rely on java.time.temporal.ChronoUnit. This API exposes a set of units useful to manipulate a date, time, or date-time and we have used it before in Problem 73. This time, let’s use it again to compute the number of weeks between two dates:

public static long nrOfWeeks(
    LocalDateTime startLdt1, LocalDateTime endLdt2) {
  return Math.abs(ChronoUnit.WEEKS.between(
    startLdt1, endLdt2));
}

On the other hand, if the given dates are java.util.Date then you can choose to convert them to LocalDateTime and use the previous code or to rely on the Calendar API. Using the Calendar API is about looping from the start date to the end date while incrementing the calendar date week-by-week:

public static long nrOfWeeks(Date startDate, Date endDate) {
  Calendar calendar = Calendar.getInstance();
  calendar.setTime(startDate);
  int weeks = 0;
  while (calendar.getTime().before(endDate)) {
    calendar.add(Calendar.WEEK_OF_YEAR, 1);
    weeks++;
  }
  return weeks;
}

When the calendar date is after the end date, we have the number of weeks.

Summary

Mission accomplished! I hope you enjoyed this short chapter filled to the brim with tips and tricks about manipulating date-time in real word applications. I strongly encourage you to also read the homologous chapter from Java Coding Problems, First Edition, which also contains 20 problems covering date-time topics.

Leave a Reply

Your email address will not be published. Required fields are marked *

© 2024 nickshade Please read our Terms and Privacy Policy. We also use Cookies.