public virtual double seasonalityFactor(Date to)
{
Date from = seasonalityBaseDate();
Frequency factorFrequency = frequency();
int nFactors = seasonalityFactors().Count;
Period factorPeriod = new Period(factorFrequency);
int which = 0;
if (from==to)
{
which = 0;
}
else
{
// days, weeks, months, years are the only time unit possibilities
int diffDays = Math.Abs(to - from); // in days
int dir = 1;
if(from > to)dir = -1;
int diff;
if (factorPeriod.units() == TimeUnit.Days)
{
diff = dir*diffDays;
}
else if (factorPeriod.units() == TimeUnit.Weeks)
{
diff = dir * (diffDays / 7);
}
else if (factorPeriod.units() == TimeUnit.Months)
{
KeyValuePair<Date,Date> lim = Utils.inflationPeriod(to, factorFrequency);
diff = diffDays / (31*factorPeriod.length());
Date go = from + dir*diff*factorPeriod;
while ( !(lim.Key <= go && go <= lim.Value) )
{
go += dir*factorPeriod;
diff++;
}
diff=dir*diff;
}
else if (factorPeriod.units() == TimeUnit.Years)
{
throw new ApplicationException(
"seasonality period time unit is not allowed to be : " + factorPeriod.units());
}
else
{
throw new ApplicationException("Unknown time unit: " + factorPeriod.units());
}
// now adjust to the available number of factors, direction dependent
if (dir==1)
{
which = diff % nFactors;
}
else
{
which = (nFactors - (-diff % nFactors)) % nFactors;
}
}
return seasonalityFactors()[which];
}