/** * Copyright (C) 2015 - present by OpenGamma Inc. and the OpenGamma group of companies * * Please see distribution for license. */ package com.opengamma.basics.date; import java.time.LocalDate; /** * Utilities for working with {@code LocalDate}. */ final class LocalDateUtils { // First day-of-month minus one for a standard year // array length 13 with element zero ignored, so month 1 to 12 can be queried directly private static final int[] STANDARD = {0, 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334}; // First day-of-month minus one for a leap year // array length 13 with element zero ignored, so month 1 to 12 can be queried directly private static final int[] LEAP = {0, 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335}; /** * Restricted constructor. */ private LocalDateUtils() { } //------------------------------------------------------------------------- /** * Finds the day-of-year of the date. * <p> * Faster than the JDK method. * * @param date the date to query * @return the day-of-year */ static int doy(LocalDate date) { int[] lookup = (date.isLeapYear() ? LEAP : STANDARD); return lookup[date.getMonthValue()] + date.getDayOfMonth(); } /** * Adds a number of days to the date. * <p> * Faster than the JDK method. * * @param date the date to add to * @return the new date */ static LocalDate plusDays(LocalDate date, int daysToAdd) { if (daysToAdd == 0) { return date; } // add the days to the current day-of-month // if it is guaranteed to be in this month or the next month then fast path it // (59th Jan is 28th Feb, 59th Feb is 31st Mar) long dom = date.getDayOfMonth() + daysToAdd; if (dom > 0 && dom <= 59) { int monthLen = date.lengthOfMonth(); int month = date.getMonthValue(); int year = date.getYear(); if (dom <= monthLen) { return LocalDate.of(year, month, (int) dom); } else if (month < 12) { return LocalDate.of(year, month + 1, (int) (dom - monthLen)); } else { return LocalDate.of(year + 1, 1, (int) (dom - monthLen)); } } long mjDay = Math.addExact(date.toEpochDay(), daysToAdd); return LocalDate.ofEpochDay(mjDay); } /** * Returns the number of days between two dates. * <p> * Faster than the JDK method. * * @param firstDate the first date * @param secondDate the second date, after the first * @return the new date */ static long daysBetween(LocalDate firstDate, LocalDate secondDate) { int firstYear = firstDate.getYear(); int secondYear = secondDate.getYear(); if (firstYear == secondYear) { return doy(secondDate) - doy(firstDate); } if ((firstYear + 1) == secondYear) { return (firstDate.lengthOfYear() - doy(firstDate)) + doy(secondDate); } return secondDate.toEpochDay() - firstDate.toEpochDay(); } }