/**
* Axelor Business Solutions
*
* Copyright (C) 2016 Axelor (<http://axelor.com>).
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License, version 3,
* as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.axelor.apps.tool.date;
import org.joda.time.Days;
import org.joda.time.LocalDate;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class DateTool{
private static final Logger LOG = LoggerFactory.getLogger(DateTool.class);
public static int daysBetween(LocalDate date1, LocalDate date2, boolean days360) {
int days = 0;
if (days360) {
if (date1.isBefore(date2)) { days = days360Between(date1, date2); }
else { days = -days360Between(date2, date1); }
}
else {
days = daysBetween(date1, date2);
}
LOG.debug("Nombre de jour entre {} - {} (mois de 30 jours ? {}) : {}", new Object[] {date1, date2, days360, days});
return days;
}
private static int daysBetween(LocalDate date1, LocalDate date2) {
if (date2.isBefore(date1)) { return Days.daysBetween(date1, date2).getDays() - 1; }
else { return Days.daysBetween(date1, date2).getDays() + 1; }
}
private static int days360Between(LocalDate startDate, LocalDate endDate) {
int nbDayOfFirstMonth = 0;
int nbDayOfOthersMonths = 0;
int nbDayOfLastMonth = 0;
LocalDate start = startDate;
if (endDate.getMonthOfYear() != startDate.getMonthOfYear() || endDate.getYear() != startDate.getYear()) {
// First month :: if the startDate is not the last day of the month
if (!startDate.isEqual(startDate.dayOfMonth().withMaximumValue())) {
nbDayOfFirstMonth = 30 - startDate.getDayOfMonth();
}
// The startDate is included
nbDayOfFirstMonth = nbDayOfFirstMonth + 1;
// Months between the first one and the last one
LocalDate date1 = startDate.plusMonths(1).dayOfMonth().withMinimumValue();
while (endDate.getMonthOfYear() != date1.getMonthOfYear() || endDate.getYear() != date1.getYear()) {
nbDayOfOthersMonths = nbDayOfOthersMonths + 30;
date1 = date1.plusMonths(1);
}
// Last Month
start = endDate.dayOfMonth().withMinimumValue();
}
if (endDate.isEqual(endDate.dayOfMonth().withMaximumValue())) { nbDayOfLastMonth = 30 - start.getDayOfMonth(); }
else { nbDayOfLastMonth = endDate.getDayOfMonth() - start.getDayOfMonth(); }
// The endDate is included
nbDayOfLastMonth = nbDayOfLastMonth + 1;
return nbDayOfFirstMonth + nbDayOfOthersMonths + nbDayOfLastMonth;
}
public static int days360MonthsBetween(LocalDate startDate, LocalDate endDate){
if (startDate.isBefore(endDate)) { return days360Between(startDate, endDate) / 30; }
else { return -days360Between(endDate, startDate) / 30 ; }
}
public static boolean isProrata(LocalDate dateFrame1, LocalDate dateFrame2, LocalDate date1, LocalDate date2) {
if (date2 == null && (date1.isBefore(dateFrame2)||date1.isEqual(dateFrame2))) { return true; }
else if (date2 == null) { return false; }
if (
(
(
date1.isAfter(dateFrame1) || date1.isEqual(dateFrame1)
)
&&
(
date1.isBefore(dateFrame2) || date1.isEqual(dateFrame2)
)
)
||
(
(
date2.isAfter(dateFrame1) || date2.isEqual(dateFrame1)
)
&&
(
date2.isBefore(dateFrame2) || date2.isEqual(dateFrame2)
)
)
||
(
date1.isBefore(dateFrame1) && date2.isAfter(dateFrame2)
)
) {
return true;
}
return false;
}
public static boolean isBetween(LocalDate dateFrame1, LocalDate dateFrame2, LocalDate date) {
if (dateFrame2 == null && (date.isAfter(dateFrame1) || date.isEqual(dateFrame1))) { return true; }
else if (dateFrame2 != null && (date.isAfter(dateFrame1) || date.isEqual(dateFrame1)) && (date.isBefore(dateFrame2) || date.isEqual(dateFrame2))) { return true; }
else { return false; }
}
/**
* Calculer la date de la prochaine occurence d'un évènement suivant le calcul suivant :
* Supprimer autant de fois que possible la fréquence en mois à la date visée
* tout en étant supérieure à la date de début
*
* @param startDate
* La date de début
*
* @param goalDate
* La date visée
*
* @param frequencyInMonth
* Nombre de mois représentant la fréquence de l'évènement
*/
public static LocalDate nextOccurency(LocalDate startDate, LocalDate goalDate, int frequencyInMonth) {
if (frequencyInMonth == 0){
LOG.debug("La fréquence ne doit pas etre égale à 0.");
return null;
}
else {
if (startDate == null && goalDate == null) { return null; }
else {
if (startDate.isAfter(goalDate)) { return goalDate; }
return minusMonths(goalDate, days360MonthsBetween(startDate.plusDays(1), goalDate.minusDays(1)) / frequencyInMonth * frequencyInMonth);
}
}
}
/**
* Calculer la date de la prochaine occurence d'un évènement suivant le calcul suivant :
* Supprimer autant de fois que possible la fréquence en mois à la date visée
* tout en étant supérieure ou égale à la date de début
*
* @param startDate
* La date de début
*
* @param goalDate
* La date visée
*
* @param frequencyInMonth
* Nombre de mois représentant la fréquence de l'évènement
*/
public LocalDate nextOccurencyStartDateIncluded(LocalDate startDate, LocalDate goalDate, int frequencyInMonth) {
if (frequencyInMonth == 0){
LOG.debug("La fréquence ne doit pas etre égale à 0.");
return null;
}
else {
if (startDate == null && goalDate == null) { return null; }
else {
if (startDate.isAfter(goalDate)) { return goalDate; }
return minusMonths(goalDate, days360MonthsBetween(startDate, goalDate.minusDays(1)) / frequencyInMonth * frequencyInMonth);
}
}
}
/**
* Calculer la date de la dernière occurence d'un évènement suivant le calcul suivant :
* Ajouter autant de fois que possible la fréquence en mois à la date de début
* tout en étant inférieure ou égale à la date de fin
* @param startDate
* La date de début
*
* @param endDate
* La date de fin
*
* @param frequencyInMonth
* Nombre de mois représentant la fréquence de l'évènement
*/
public static LocalDate lastOccurency(LocalDate startDate, LocalDate endDate, int frequencyInMonth) {
if (frequencyInMonth == 0){
LOG.debug("La fréquence ne doit pas etre égale à 0.");
return null;
}
else {
if ((startDate == null && endDate == null) || startDate.isAfter(endDate)) { return null; }
else {
return plusMonths(startDate, days360MonthsBetween(startDate, endDate) / frequencyInMonth * frequencyInMonth);
}
}
}
public static LocalDate minusMonths(LocalDate date, int nbMonths){
return date.plusDays(1).minusMonths(nbMonths).minusDays(1);
}
public static LocalDate plusMonths(LocalDate date, int nbMonths){
return date.plusDays(1).plusMonths(nbMonths).minusDays(1);
}
/**
* Procédure permettant de tester si aujourd'hui nous sommes dans une période particulière
*
* @param date
* La date à tester
* @param dayBegin
* Le jour du début de la période
* @param monthBegin
* Le mois de début de la période
* @param dayEnd
* Le jour de fin de la période
* @param monthEnd
* Le mois de fin de la période
* @return
* Sommes-nous dans la période?
*/
public static boolean dateInPeriod(LocalDate date, int dayBegin, int monthBegin, int dayEnd, int monthEnd) {
if(monthBegin > monthEnd) {
if((date.getMonthOfYear() == monthBegin && date.getDayOfMonth()>= dayBegin)
|| (date.getMonthOfYear() > monthBegin)
|| (date.getMonthOfYear() < monthEnd)
|| (date.getMonthOfYear() == monthEnd && date.getDayOfMonth() <= dayEnd))
{
return true;
}
else {
return false;
}
}
else if(monthBegin == monthEnd) {
if((date.getMonthOfYear() == monthBegin && date.getDayOfMonth()>= dayBegin && date.getDayOfMonth()<= dayEnd))
{
return true;
}
else {
return false;
}
}
else {
if((date.getMonthOfYear() == monthBegin && date.getDayOfMonth()>= dayBegin)
|| (date.getMonthOfYear() > monthBegin && date.getMonthOfYear() < monthEnd)
|| (date.getMonthOfYear() == monthEnd && date.getDayOfMonth() <= dayEnd))
{
return true;
}
else {
return false;
}
}
}
}