getDynamicDate function

DateTime getDynamicDate(
  1. Frequency freqObject,
  2. DateTime startDt
)

calculates the next Date Time from a Dynamic Frequency object given a zero date time point

Implementation

DateTime getDynamicDate(Frequency freqObject, DateTime startDt) {
  //check utc, if utc, set to local
  startDt = startDt.isUtc ? startDt.toLocal() : startDt;
  DateTime currentDtTm = DateTime.now();

  DateTime retVal = startDt;
  if (freqObject.timesPerDay != null) {
    double intervalseconds = 86400 / freqObject.timesPerDay!;

    DateTime firstDoseNextDay = DateTime(currentDtTm.year, currentDtTm.month,
        currentDtTm.day, startDt.hour, startDt.minute, startDt.second);

    DateTime thirdtDayStart = DateTime(currentDtTm.year, currentDtTm.month,
        currentDtTm.day + 2, startDt.hour, startDt.minute, startDt.second);

    while (firstDoseNextDay.isBefore(thirdtDayStart)) {
      firstDoseNextDay =
          firstDoseNextDay.add(Duration(seconds: intervalseconds.round()));
      if (firstDoseNextDay.isAfter(currentDtTm)) {
        retVal = firstDoseNextDay;
        break;
      }
    }
  } else if (freqObject.timesPerWeek != null) {
    double intervalseconds = (7 * 86400) / freqObject.timesPerWeek!;

    DateTime firstDoseNextDay = startDt;

    DateTime nextWStart = DateTime(currentDtTm.year, currentDtTm.month,
        currentDtTm.day + 7, startDt.hour, startDt.minute, startDt.second);

    while (firstDoseNextDay.isBefore(nextWStart)) {
      firstDoseNextDay =
          firstDoseNextDay.add(Duration(seconds: intervalseconds.round()));
      if (firstDoseNextDay.isAfter(currentDtTm)) {
        retVal = firstDoseNextDay;
        break;
      }
    }
  } else if (freqObject.timesPerMonth != null) {
    double daysInCurrentMonth =
        DateTime(currentDtTm.year, currentDtTm.month + 1, 0).day as double;
    bool isInCurrentMonthFirstHalf =
        currentDtTm.day / daysInCurrentMonth < 0.5 ? true : false;
    if (!isInCurrentMonthFirstHalf) {
      daysInCurrentMonth = (daysInCurrentMonth +
              DateTime(currentDtTm.year, currentDtTm.month + 2, 0).day) /
          2;
    }

    double intervalseconds =
        (daysInCurrentMonth * 86400) / freqObject.timesPerMonth!;

    DateTime nextMStart = DateTime(
        currentDtTm.year,
        currentDtTm.month,
        currentDtTm.day + daysInCurrentMonth.round(),
        startDt.hour,
        startDt.minute,
        startDt.second); //start at 00:00:00

    DateTime nextDose = startDt;

    while (nextDose.isBefore(nextMStart)) {
      //append second day timestamp by substraction from third day

      nextDose = nextDose.add(Duration(seconds: intervalseconds.round()));
      if (nextDose.isAfter(currentDtTm)) {
        retVal = nextDose;
        break;
      }
    }
  } else if (freqObject.timesPerYear != null) {
    int daysInCurrentYear = inLeapYear() ? 366 : 365;

    double intervalseconds =
        (daysInCurrentYear * 86400) / freqObject.timesPerYear!;

    DateTime nextDose = startDt;

    DateTime nextYStart = DateTime(
        currentDtTm.year,
        currentDtTm.month,
        currentDtTm.day + daysInCurrentYear,
        startDt.hour,
        startDt.minute,
        startDt.second);

    while (nextDose.isBefore(nextYStart)) {
      //append second day timestamp by substraction from third day

      nextDose = nextDose.add(Duration(seconds: intervalseconds.round()));
      if (nextDose.isAfter(currentDtTm)) {
        retVal = nextDose;
        break;
      }
    }
  } else {
    throw Exception(
        "insufficient parameters for dynamic frequency, start date will be returned!");
  }

  return retVal;
}