/*
***************************************************************************************
* Copyright (C) 2006 EsperTech, Inc. All rights reserved. *
* http://www.espertech.com/esper *
* http://www.espertech.com *
* ---------------------------------------------------------------------------------- *
* The software in this package is published under the terms of the GPL license *
* a copy of which has been included with this distribution in the license.txt file. *
***************************************************************************************
*/
package com.espertech.esper.epl.datetime.calop;
import com.espertech.esper.client.util.DateTime;
import com.espertech.esper.client.util.TimePeriod;
import com.espertech.esper.epl.expression.time.TimeAbacus;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.Calendar;
public class CalendarOpPlusFastAddHelper {
private final static boolean DEBUG = false;
private static Logger log = LoggerFactory.getLogger(CalendarOpPlusFastAddHelper.class);
public static CalendarOpPlusFastAddResult computeNextDue(long currentTime, TimePeriod timePeriod, Calendar reference, TimeAbacus timeAbacus, long remainder) {
if (timeAbacus.calendarGet(reference, remainder) > currentTime) {
return new CalendarOpPlusFastAddResult(0, reference);
}
// add one time period
Calendar work = (Calendar) reference.clone();
if (DEBUG && log.isDebugEnabled()) {
log.debug("Work date is " + DateTime.print(work));
}
CalendarOpPlusMinus.actionSafeOverflow(work, 1, timePeriod);
long inMillis = timeAbacus.calendarGet(work, remainder);
if (inMillis > currentTime) {
return new CalendarOpPlusFastAddResult(1, work);
}
if (DEBUG && log.isDebugEnabled()) {
log.debug("Work date is " + DateTime.print(work));
}
long factor = 1;
// determine multiplier
long refTime = timeAbacus.calendarGet(reference, remainder);
long deltaCurrentToStart = currentTime - refTime;
long deltaAddedOne = timeAbacus.calendarGet(work, remainder) - refTime;
double multiplierDbl = (deltaCurrentToStart / deltaAddedOne) - 1;
long multiplierRoundedLong = (long) multiplierDbl;
// handle integer max
while (multiplierRoundedLong > Integer.MAX_VALUE) {
CalendarOpPlusMinus.actionSafeOverflow(work, Integer.MAX_VALUE, timePeriod);
factor += Integer.MAX_VALUE;
multiplierRoundedLong -= Integer.MAX_VALUE;
if (DEBUG && log.isDebugEnabled()) {
log.debug("Work date is " + DateTime.print(work) + " factor " + factor);
}
}
// add
int multiplierRoundedInt = (int) multiplierRoundedLong;
CalendarOpPlusMinus.actionSafeOverflow(work, multiplierRoundedInt, timePeriod);
factor += multiplierRoundedInt;
// if below, add more
if (timeAbacus.calendarGet(work, remainder) <= currentTime) {
while (timeAbacus.calendarGet(work, remainder) <= currentTime) {
CalendarOpPlusMinus.actionSafeOverflow(work, 1, timePeriod);
factor += 1;
if (DEBUG && log.isDebugEnabled()) {
log.debug("Work date is " + DateTime.print(work) + " factor " + factor);
}
}
return new CalendarOpPlusFastAddResult(factor, work);
}
// we are over
while (timeAbacus.calendarGet(work, remainder) > currentTime) {
CalendarOpPlusMinus.actionSafeOverflow(work, -1, timePeriod);
factor -= 1;
if (DEBUG && log.isDebugEnabled()) {
log.debug("Work date is " + DateTime.print(work) + " factor " + factor);
}
}
CalendarOpPlusMinus.actionSafeOverflow(work, 1, timePeriod);
if (DEBUG && log.isDebugEnabled()) {
log.debug("Work date is " + DateTime.print(work) + " factor " + factor);
}
return new CalendarOpPlusFastAddResult(factor + 1, work);
}
}