OceanusDateUtils.java
/*
* Oceanus: Java Utilities
* Copyright 2026. Tony Washer
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy
* of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package io.github.tonywasher.joceanus.oceanus.date;
import java.time.LocalDate;
import java.time.Month;
/**
* Date utilities.
*/
public final class OceanusDateUtils {
/**
* The Number of months in a Quarter.
*/
private static final int MONTHS_IN_QUARTER = 3;
/**
* Private constructor.
*/
private OceanusDateUtils() {
}
/**
* Obtain the date of the start of the period.
*
* @param pDate the date to adjust
* @param pPeriod the period to adjust by
* @return the adjusted date
*/
public static OceanusDate startPeriod(final OceanusDate pDate,
final OceanusDatePeriod pPeriod) {
return switch (pPeriod) {
case CALENDARMONTH -> startCalendarMonth(pDate);
case CALENDARQUARTER -> startCalendarQuarter(pDate);
case CALENDARYEAR -> startCalendarYear(pDate);
case FISCALYEAR -> startFiscalYear(pDate);
default -> pDate;
};
}
/**
* Obtain the date of the end of the following month.
*
* @param pDate the date to adjust
* @return the date
*/
public static OceanusDate endNextMonth(final OceanusDate pDate) {
/* Move to the first of the current month */
LocalDate myDate = pDate.getDate().withDayOfMonth(1);
/* Add two months and move back a day */
myDate = myDate.plusMonths(2);
myDate = myDate.minusDays(1);
return new OceanusDate(myDate);
}
/**
* Obtain the date of the start of the month.
*
* @param pDate the date to adjust
* @return the date
*/
public static OceanusDate startCalendarMonth(final OceanusDate pDate) {
/* Move to the first of the current month */
final LocalDate myDate = pDate.getDate().withDayOfMonth(1);
return new OceanusDate(myDate);
}
/**
* Obtain the date of the end of the month.
*
* @param pDate the date to adjust
* @return the date
*/
public static OceanusDate endCalendarMonth(final OceanusDate pDate) {
/* Move to the first of the next month and then one day before */
LocalDate myDate = pDate.getDate().withDayOfMonth(1);
myDate = myDate.plusMonths(1);
myDate = myDate.minusDays(1);
return new OceanusDate(myDate);
}
/**
* Obtain the date of the start of the quarter.
*
* @param pDate the date to adjust
* @return the date
*/
public static OceanusDate startCalendarQuarter(final OceanusDate pDate) {
/* Determine the month in quarter */
LocalDate myDate = pDate.getDate();
final int myMiQ = (pDate.getMonth() - 1)
% MONTHS_IN_QUARTER;
/* Move to the first of the current month */
myDate = myDate.withDayOfMonth(1);
/* Move to the first of the quarter */
myDate = myDate.minusMonths(myMiQ);
return new OceanusDate(myDate);
}
/**
* Obtain the date of the start of the year.
*
* @param pDate the date to adjust
* @return the date
*/
public static OceanusDate startCalendarYear(final OceanusDate pDate) {
/* Move to the first of the current year */
LocalDate myDate = pDate.getDate().withDayOfMonth(1);
myDate = myDate.withMonth(Month.JANUARY.getValue());
return new OceanusDate(myDate);
}
/**
* Obtain the date of the end of the year.
*
* @param pDate the date to adjust
* @return the date
*/
public static OceanusDate endCalendarYear(final OceanusDate pDate) {
/* Move to the first of the current year */
LocalDate myDate = pDate.getDate().plusYears(1);
myDate = myDate.withDayOfMonth(1);
myDate = myDate.withMonth(Month.JANUARY.getValue());
myDate = myDate.minusDays(1);
return new OceanusDate(myDate);
}
/**
* Adjust the date to the start of the fiscal year.
*
* @param pDate the date to adjust
* @return the date
*/
public static OceanusDate startFiscalYear(final OceanusDate pDate) {
/* Determine Fiscal year type */
final OceanusFiscalYear myFiscal = OceanusFiscalYear.determineFiscalYear(pDate.getLocale());
final int myFiscalMonth = myFiscal.getFirstMonth().getValue();
final int myFiscalDay = myFiscal.getFirstDay();
/* Access date details */
LocalDate myDate = pDate.getDate();
final int myMonth = pDate.getMonth();
final int myDay = pDate.getDay();
/* Determine which year we are in */
if (myMonth < myFiscalMonth
|| (myMonth == myFiscalMonth && myDay < myFiscalDay)) {
myDate = myDate.minusYears(1);
}
/* Move to the first of the current year */
myDate = myDate.withDayOfMonth(myFiscalDay);
myDate = myDate.withMonth(myFiscalMonth);
return new OceanusDate(myDate);
}
/**
* Calculate the age that someone born on a particular date will be on a given date.
*
* @param pBirthDate the birthDate
* @param pDate the date for which to calculate the age
* @return the age on that date
*/
public static int ageOn(final OceanusDate pBirthDate,
final OceanusDate pDate) {
/* Access dates */
final LocalDate myBirthDate = pBirthDate.getDate();
final LocalDate myDate = pDate.getDate();
/* Calculate the initial age assuming same date in year */
int myAge = myDate.getYear();
myAge -= myBirthDate.getYear();
/* Check whether we are later in the year */
int myDelta = myBirthDate.getMonthValue()
- myDate.getMonthValue();
if (myDelta == 0) {
myDelta = myBirthDate.getDayOfMonth()
- myDate.getDayOfMonth();
}
/* If so then subtract one from the year */
if (myDelta > 0) {
myAge--;
}
/* Return to caller */
return myAge;
}
}