Actually because of the nature of Cron expression that it works in advancing chronological order, i think their is no solution, but using a brute force technique it is possible to do it with minimal code execution.
public virtual DateTimeOffset? GetTimeBefore(DateTimeOffset beforeTimeUtc)
{
DateTimeOffset? nextFireTimeValid = GetTimeAfter(beforeTimeUtc);
DateTimeOffset? nextFireTime = nextFireTimeValid;
string[] expression = cronExpressionString.Split(' ');
int incrementBy = 6;/*by default use years*/
for (int j = 0; j < expression.Length; j++)
{
if (expression[j]=="*")
{
incrementBy = j;
break;
}
}
nextFireTime = nextFireTime.Value.AddSeconds(-1);
switch (incrementBy)
{
case 0://[0]SEC
break;
case 1://[1]MIN
nextFireTime = nextFireTime.Value.AddMinutes(-1);
break;
case 2://[2]HOUR
nextFireTime = nextFireTime.Value.AddHours(-1);
break;
case 4://[4]MONTH
nextFireTime = nextFireTime.Value.AddMonths(-1);
break;
case 3://[3]DAYOFMONTH
case 5://[5]DAYOFWEEK
nextFireTime = nextFireTime.Value.AddYears(-1);
break;
case 6://[6]YEAR
default:
nextFireTime = nextFireTime.Value.AddYears(-1);
break;
}
DateTimeOffset? output = GetTimeAfter(nextFireTime.Value);
DateTimeOffset? tmp;
bool searching = true;
while (searching)
{
tmp = GetTimeAfter(output.Value);
if (!tmp.HasValue)
return null;
if (tmp.Value == nextFireTimeValid.Value)
{
searching = false;
}
else
{
output = GetTimeAfter(output.Value);
}
}
return output;