508 lines
17 KiB
Plaintext
Executable File
508 lines
17 KiB
Plaintext
Executable File
package com.fp.persistence.commondb.helper;
|
||
|
||
import java.sql.Date;
|
||
import java.sql.Timestamp;
|
||
import java.text.SimpleDateFormat;
|
||
import java.util.Calendar;
|
||
import java.util.GregorianCalendar;
|
||
|
||
import com.fp.common.helper.CalculationBase;
|
||
import com.fp.common.logger.APPLogger;
|
||
import com.fp.persistence.commondb.exception.CommondbException;
|
||
|
||
/**
|
||
* Clase utilitaria para el manejo de fechas.
|
||
*
|
||
* @author Jorge Vaca
|
||
* @version 2.1
|
||
*/
|
||
public class APPDates implements Comparable {
|
||
|
||
/* Fecha base para las Operaciones */
|
||
private Date date;
|
||
|
||
/* Base de Calculo */
|
||
private CalculationBase base;
|
||
|
||
/* Calendario Encargado de las operaciones con las Fechas */
|
||
private final GregorianCalendar calendar;
|
||
|
||
/* Formateador de Fechas para transporte */
|
||
private final SimpleDateFormat formateador;
|
||
|
||
/**
|
||
* Crea una nueva instancia de Dates
|
||
*
|
||
* @param pDate Fecha base
|
||
* @param pBase Base de Calculo;
|
||
*/
|
||
public APPDates(String pDate, CalculationBase pBase) throws Exception {
|
||
this(new Date(FormatDates.getInstance().getTransportDateFormat().parse(pDate).getTime()), pBase);
|
||
}
|
||
|
||
/**
|
||
* Crea una nueva instancia de Dates
|
||
*
|
||
* @param pDate Fecha base como string formato yyyy-MM-dd
|
||
*/
|
||
public APPDates(String pDate) throws Exception {
|
||
this(pDate, CalculationBase.B360365);
|
||
}
|
||
|
||
/**
|
||
* Crea una nueva instancia de Dates
|
||
*
|
||
* @param pDate Fecha base
|
||
* @param pBase Base de Calculo;
|
||
*/
|
||
public APPDates(Date pDate, CalculationBase pBase) throws Exception {
|
||
this.date = pDate;
|
||
this.base = pBase;
|
||
this.calendar = new GregorianCalendar();
|
||
this.calendar.setTime(this.date);
|
||
this.formateador = FormatDates.getInstance().getTransportDateFormat();
|
||
}
|
||
|
||
/**
|
||
* Crea una nueva instancia de Dates
|
||
*
|
||
* @param pDate Fecha base
|
||
* @param pBase Base de Calculo;
|
||
*/
|
||
public APPDates(Date pDate, CalculationBase pBase, SimpleDateFormat sdf) throws Exception {
|
||
this.date = pDate;
|
||
this.base = pBase;
|
||
this.calendar = new GregorianCalendar();
|
||
this.calendar.setTime(this.date);
|
||
this.formateador = sdf;
|
||
}
|
||
|
||
/**
|
||
* Crea una nueva instancia de Dates con base 360/365
|
||
*
|
||
* @param pDate Fecha base
|
||
*/
|
||
public APPDates(Date pDate) throws Exception {
|
||
this(pDate, CalculationBase.B360365);
|
||
}
|
||
|
||
/**
|
||
* Entrega el Valor de date.
|
||
*
|
||
* @return Date
|
||
*/
|
||
public Date getDate() {
|
||
return this.date;
|
||
}
|
||
|
||
/**
|
||
* Entrega el Valor de date.
|
||
*
|
||
* @return Timestamp
|
||
*/
|
||
public Timestamp getTimestamp() {
|
||
return new Timestamp(this.date.getTime());
|
||
}
|
||
|
||
/**
|
||
* Metodoq ue resta un mes a una fecha y le pone el ultimo dia del mes en la misma.
|
||
*
|
||
* @throws Exception
|
||
*/
|
||
public void substractOneMonth365() throws Exception {
|
||
this.calendar.add(Calendar.MONTH, -1);
|
||
int max1 = this.calendar.getActualMaximum(Calendar.DAY_OF_MONTH);
|
||
this.calendar.set(Calendar.DAY_OF_MONTH, max1);
|
||
this.date = new Date(this.calendar.getTimeInMillis());
|
||
}
|
||
|
||
/**
|
||
* Clase que se encarga de restar dos fechas, a la fecha mayor se resta una fecha menor.
|
||
*
|
||
* @param pInicialdate Feinicial a restar de una fecha final.
|
||
* @return int
|
||
* @throws Exception
|
||
*/
|
||
public int substract(APPDates pInicialdate) throws Exception {
|
||
int days = 0;
|
||
if (pInicialdate.getDate().after(this.date)) {
|
||
throw new CommondbException("COMMONDB-0001", "FECHA A RESTAR: {0,date,yyyy-MM-dd} ES MAYOR A: {1,date,yyyy-MM-dd}",
|
||
pInicialdate.getDate(), this.date);
|
||
}
|
||
if (pInicialdate.getDate().compareTo(this.date) == 0) {
|
||
return 0;
|
||
}
|
||
if (this.base.getMonthBase() == 365) {
|
||
days = this.substract365(pInicialdate);
|
||
} else {
|
||
days = this.substract360(pInicialdate);
|
||
}
|
||
return days;
|
||
}
|
||
|
||
/**
|
||
* Metodo que resta fechas en base cuando la base es 365/xxx
|
||
*
|
||
* @param pInicialdate Fecha inicia a restar.
|
||
* @return int
|
||
* @throws Exception
|
||
*/
|
||
private int substract365(APPDates pInicialdate) throws Exception {
|
||
int days = 0;
|
||
GregorianCalendar cal1 = new GregorianCalendar();
|
||
cal1.setTime(pInicialdate.getDate());
|
||
do {
|
||
cal1.add(Calendar.DATE, 1);
|
||
days++;
|
||
} while (this.date.compareTo(cal1.getTime()) != 0);
|
||
return days;
|
||
}
|
||
|
||
/**
|
||
* Metodo que se encarga de restar dos fehcas en base 360.
|
||
*
|
||
* @param pInicialdate
|
||
* @return
|
||
* @throws Exception
|
||
*/
|
||
private int substract360(APPDates pInicialdate) throws Exception {
|
||
int days = 0;
|
||
int nYears = this.getField(Calendar.YEAR) - pInicialdate.getField(Calendar.YEAR);
|
||
int nMonths = this.getField(Calendar.MONTH) - pInicialdate.getField(Calendar.MONTH);
|
||
int dayone = this.getField(Calendar.DAY_OF_MONTH);
|
||
if (dayone == 31) {
|
||
dayone = 30;
|
||
}
|
||
int daytwo = pInicialdate.getField(Calendar.DAY_OF_MONTH);
|
||
if (daytwo == 31) {
|
||
daytwo = 30;
|
||
}
|
||
int nMonth = this.getField(Calendar.MONTH);
|
||
if (nMonth == 1) { // 0 enero, 1 febrero , 2 marzo
|
||
// si el dia de la fecha es igual al maximo dia del mes
|
||
if (this.getField(Calendar.DAY_OF_MONTH) == this.calendar.getActualMaximum(Calendar.DAY_OF_MONTH)) {
|
||
int day = pInicialdate.getField(Calendar.DAY_OF_MONTH);
|
||
if ((day == 30) || (day == 31)) {
|
||
dayone = 30;
|
||
}
|
||
}
|
||
}
|
||
nMonth = pInicialdate.getField(Calendar.MONTH);
|
||
if (nMonth == 1) { // 0 enero, 1 febrero , 2 marzo
|
||
// si el dia de la fecha es igual al maximo dia del mes
|
||
if (pInicialdate.getField(Calendar.DAY_OF_MONTH) == pInicialdate.calendar.getActualMaximum(Calendar.DAY_OF_MONTH)) {
|
||
int day = this.getField(Calendar.DAY_OF_MONTH);
|
||
if ((day == 30) || (day == 31)) {
|
||
daytwo = 30;
|
||
}
|
||
}
|
||
}
|
||
nYears = nYears * 12 * 30;
|
||
nMonths = nMonths * 30;
|
||
days = dayone - daytwo;
|
||
days = nYears + nMonths + days;
|
||
/* v_dias_resultado := (nvl(v_anios,0) * 12 * 30) + (nvl(v_meses,0) * 30) + (nvl(v_dia1,0) - nvl(v_dia2,0)); */
|
||
return days;
|
||
}
|
||
|
||
/**
|
||
* Aniadir dias a una Fecha
|
||
*
|
||
* @param days Numero de dias a aniadir
|
||
*/
|
||
public void addYearBased(int days) throws Exception {
|
||
if (this.base.getYearBase() == 365) {
|
||
this.calendar.add(Calendar.DATE, days);
|
||
} else {
|
||
if (Math.abs(days) >= 30) {
|
||
int month = (int) Math.floor(days / 30);
|
||
this.calendar.add(Calendar.MONTH, month);
|
||
this.calendar.add(Calendar.DATE, days % 30);
|
||
} else {
|
||
this.calendar.add(Calendar.DATE, days);
|
||
}
|
||
}
|
||
this.date = new Date(this.calendar.getTime().getTime());
|
||
}
|
||
|
||
/**
|
||
* Aniadir dias a una Fecha, amteniendo un dia fijo en la fecha.
|
||
*
|
||
* @param days Numero de dias a adicionar.
|
||
* @param payDay Fecha de pago.
|
||
* @throws Exception
|
||
*/
|
||
public void addDaysBased(int days, Integer payDay) throws Exception {
|
||
if (this.base.getMonthBase() == 365) {
|
||
/*
|
||
* if( days == 31 || this.calendar.getActualMaximum(Calendar.DAY_OF_MONTH) >= days){
|
||
* this.calendar.add(Calendar.MONTH,1); }else{ this.calendar.add(Calendar.DATE, days); }
|
||
*/
|
||
this.calendar.add(Calendar.DATE, days);
|
||
} else {
|
||
if (Math.abs(days) >= 30) {
|
||
int diff = 0;
|
||
if (this.calendar.get(Calendar.MONTH) == Calendar.FEBRUARY) {
|
||
if (this.calendar.get(Calendar.DATE) >= 28) {
|
||
if ((payDay != null) && (this.calendar.getActualMaximum(Calendar.DAY_OF_MONTH) < payDay)) {
|
||
// diff= (this.calendar.getActualMaximum(Calendar.DAY_OF_MONTH)==29)?1:2;
|
||
diff = payDay - this.calendar.getActualMaximum(Calendar.DAY_OF_MONTH);
|
||
}
|
||
}
|
||
}
|
||
int month = (int) Math.floor(days / 30);
|
||
this.calendar.add(Calendar.MONTH, month);
|
||
int d = days % 30;
|
||
this.calendar.add(Calendar.DATE, d);
|
||
if (diff > 0) {
|
||
this.calendar.add(Calendar.DATE, diff);
|
||
}
|
||
} else {
|
||
this.calendar.add(Calendar.DATE, days);
|
||
}
|
||
}
|
||
this.date = new Date(this.calendar.getTime().getTime());
|
||
}
|
||
|
||
/**
|
||
* Aniadir dias a una Fecha
|
||
*
|
||
* @param days Numero de dias a aniadir
|
||
*/
|
||
public void addMonthBased(int days) throws Exception {
|
||
if (this.base.getMonthBase() == 365) {
|
||
this.calendar.add(Calendar.DATE, days);
|
||
} else {
|
||
if (Math.abs(days) >= 30) {
|
||
int diff = 0;
|
||
if (this.calendar.get(Calendar.MONTH) == Calendar.FEBRUARY) {
|
||
if (this.calendar.get(Calendar.DATE) >= 28) {
|
||
diff = (this.calendar.getActualMaximum(Calendar.DAY_OF_MONTH) == 29) ? 1 : 2;
|
||
}
|
||
}
|
||
int month = (int) Math.floor(days / 30);
|
||
this.calendar.add(Calendar.MONTH, month);
|
||
this.calendar.add(Calendar.DATE, days % 30);
|
||
if (diff > 0) {
|
||
this.calendar.add(Calendar.DATE, diff);
|
||
}
|
||
} else {
|
||
this.calendar.add(Calendar.DATE, days);
|
||
}
|
||
}
|
||
this.date = new Date(this.calendar.getTime().getTime());
|
||
}
|
||
|
||
/**
|
||
* Entrega el Valor de base de calculo.
|
||
*
|
||
* @return CalculationBase.
|
||
*/
|
||
public CalculationBase getBase() {
|
||
return this.base;
|
||
}
|
||
|
||
/**
|
||
* Fija el valor de base de calculo
|
||
*
|
||
* @param base Nuevo valor de base.
|
||
*/
|
||
public void setBase(CalculationBase base) {
|
||
this.base = base;
|
||
}
|
||
|
||
/*
|
||
* (non-Javadoc)
|
||
*
|
||
* @see java.lang.Object#toString()
|
||
*/
|
||
@Override
|
||
public String toString() {
|
||
return this.formateador.format(this.date).toString();
|
||
}
|
||
|
||
public int getField(int pField) throws Exception {
|
||
return this.calendar.get(pField);
|
||
}
|
||
|
||
/**
|
||
* Entrega el Valor de calendar.
|
||
*
|
||
* @return GregorianCalendar.
|
||
*/
|
||
public GregorianCalendar getGregorianCalendar() {
|
||
return this.calendar;
|
||
}
|
||
|
||
public APPDates dateFrecuency(Frequency pFrecuency) throws Exception {
|
||
this.calendar.add(Calendar.DATE, pFrecuency.getNumDays(this.getDate(), this.formateador));
|
||
return new APPDates(new Date(this.calendar.getTime().getTime()));
|
||
}
|
||
|
||
public APPDates nextDateofSequence(Frequency pFrecuency, int pDay) throws Exception {
|
||
int days = pFrecuency.getNumDays(this.getDate(), this.formateador);
|
||
if (days > 31) {
|
||
// TODO Incluiy las frecuanias superiores a mensual
|
||
throw new CommondbException("COMMONDB-0002", "LA FRECUENCIA DEBE SER MENOR O IGUAL A MENSUAL");
|
||
}
|
||
if (pDay > days) {
|
||
if ((pFrecuency == Frequency.MONTHLY) && (pDay == 31)) {
|
||
pDay = days;
|
||
} else {
|
||
throw new CommondbException("COMMONDB-0003", "El DIA {0} NO PUEDE MAYOR AL NUMEOR DE DIAS DE LA FRECUENCIA{1}", pDay, days);
|
||
}
|
||
}
|
||
GregorianCalendar cal = new GregorianCalendar();
|
||
cal.setTime(this.date);
|
||
if (pFrecuency == Frequency.WEEKLY) {
|
||
while (cal.get(Calendar.DAY_OF_WEEK) != pDay) {
|
||
cal.add(Calendar.DAY_OF_WEEK, 1);
|
||
}
|
||
return new APPDates(new Date(cal.getTime().getTime()));
|
||
}
|
||
cal.set(Calendar.DATE, pDay);
|
||
APPLogger.getLogger().debug("Calendario base ==> " + cal.getTime());
|
||
APPLogger.getLogger().debug("Maximo dia del mes ==> " + cal.getActualMaximum(Calendar.DAY_OF_MONTH));
|
||
while (cal.getTime().before(this.date)) {
|
||
cal.add(Calendar.DATE, days);
|
||
}
|
||
while ((cal.get(Calendar.MONTH) != this.getField(Calendar.MONTH)) && (pDay != cal.get(Calendar.DATE))) {
|
||
cal.add(Calendar.DATE, -1);
|
||
}
|
||
if ((cal.get(Calendar.DATE) == 30) && (cal.getActualMaximum(Calendar.DAY_OF_MONTH) == 31)) {
|
||
cal.add(Calendar.DATE, 1);
|
||
}
|
||
return new APPDates(new Date(cal.getTime().getTime()));
|
||
}
|
||
|
||
public int getJulianDate() throws Exception {
|
||
GregorianCalendar c = new GregorianCalendar();
|
||
c.setTime(this.date);
|
||
return this.toJulian(c.get(Calendar.YEAR), c.get(Calendar.MONTH), c.get(Calendar.DATE));
|
||
}
|
||
|
||
private int toJulian(int year, int month, int day) throws Exception {
|
||
int julianYear = year;
|
||
if (year < 0) {
|
||
julianYear++;
|
||
}
|
||
int julianMonth = month;
|
||
if (month > 2) {
|
||
julianMonth++;
|
||
} else {
|
||
julianYear--;
|
||
julianMonth += 13;
|
||
}
|
||
|
||
double julian = (java.lang.Math.floor(365.25 * julianYear) + java.lang.Math.floor(30.6001 * julianMonth) + day + 1720995.0);
|
||
|
||
if ((day + (31 * (month + (12 * year)))) >= JGREG) {
|
||
int ja = (int) (0.01 * julianYear);
|
||
julian += (2 - ja) + (0.25 * ja);
|
||
}
|
||
return (int) Math.floor(julian);
|
||
}
|
||
|
||
public static final int JGREG = 15 + (31 * (10 + (12 * 1582)));
|
||
|
||
/**
|
||
* Adiciona anios, meses, dias, semanas ..Etc a una fecha.
|
||
*
|
||
* @param field Constante de anio, mes, dia...Etc
|
||
* @param value Numero de anios, dias, meses a adicionar puese der un valor negativo.
|
||
* @throws Exception
|
||
*/
|
||
public void addField(int field, int value) throws Exception {
|
||
getGregorianCalendar().add(field, value);
|
||
this.date = new Date(getGregorianCalendar().getTimeInMillis());
|
||
}
|
||
|
||
/**
|
||
* Adiciona anios, meses, dias, semanas ..Etc a una fecha.
|
||
*
|
||
* @param field Constante de anio, mes, dia...Etc
|
||
* @param value Numero de anios, dias, meses a adicionar puese der un valor negativo.
|
||
* @throws Exception
|
||
*/
|
||
public void setField(int field, int value) throws Exception {
|
||
if (field == Calendar.DAY_OF_MONTH) {
|
||
int maxday = getGregorianCalendar().getActualMaximum(Calendar.DAY_OF_MONTH);
|
||
if (value > maxday) {
|
||
value = maxday;
|
||
}
|
||
}
|
||
getGregorianCalendar().set(field, value);
|
||
this.date = new Date(getGregorianCalendar().getTimeInMillis());
|
||
}
|
||
|
||
/**
|
||
* Compara dos Dates.
|
||
*
|
||
* @param o
|
||
* @return
|
||
*/
|
||
@Override
|
||
public int compareTo(Object o) {
|
||
if (!(o instanceof APPDates)) {
|
||
return -1;
|
||
}
|
||
APPDates d = (APPDates) o;
|
||
return this.date.compareTo(d.date);
|
||
}
|
||
|
||
/**
|
||
* Entrega el dia del anio al correspondiente a la Fecha
|
||
*
|
||
* @return Dia del Anio
|
||
* @throws Exception
|
||
*/
|
||
public int getDayOfYear() throws Exception {
|
||
GregorianCalendar gcal = new GregorianCalendar();
|
||
gcal.setTime(this.date);
|
||
return gcal.get(Calendar.DAY_OF_YEAR);
|
||
}
|
||
|
||
/**
|
||
* Entrega lso dias del mes correspondiente a la fecha.
|
||
*
|
||
* @return int
|
||
* @throws Exception
|
||
*/
|
||
public int getDaysOfMonth() throws Exception {
|
||
if (this.base.getMonthBase() == 360) {
|
||
return 30;
|
||
}
|
||
GregorianCalendar gcal = new GregorianCalendar();
|
||
gcal.setTime(this.date);
|
||
return gcal.getActualMaximum(Calendar.DAY_OF_MONTH);
|
||
}
|
||
|
||
/**
|
||
* Fija el ultimo dia del mes corespondiente a la fecha.
|
||
*
|
||
* @return
|
||
* @throws Exception
|
||
*/
|
||
public void setLastDateOfMonth() throws Exception {
|
||
Calendar gcal = new GregorianCalendar();
|
||
gcal.setTime(this.date);
|
||
gcal.set(Calendar.DAY_OF_MONTH, this.getDaysOfMonth());
|
||
this.date = new Date(gcal.getTimeInMillis());
|
||
}
|
||
|
||
/**
|
||
* Entrega el mes del a<>o correspondiente a la Fecha
|
||
*
|
||
* @return mes del a<>o
|
||
* @throws Exception
|
||
*/
|
||
public String getMonthOfYear() throws Exception {
|
||
int month = this.getField(Calendar.MONTH) + 1;
|
||
if (month < 10) {
|
||
return "0" + month;
|
||
} else {
|
||
return "" + month;
|
||
}
|
||
}
|
||
}
|