Repository: mermaid-js/mermaid
File: packages/mermaid/src/diagrams/gantt/ganttDb.js (JavaScript)

Code before:
    for (const id of afterStatement.groups.ids.split(' ')) {
      let task = findTaskById(id);
      if (task !== undefined && (!latestTask || task.endTime > latestTask.endTime)) {
        latestTask = task;
      }
    }

    if (latestTask) {
      return latestTask.endTime;
    }
    const today = new Date();
    today.setHours(0, 0, 0, 0);
    return today;
  }

  // Check for actual date set
  let mDate = dayjs(str, dateFormat.trim(), true);
  if (mDate.isValid()) {
    return mDate.toDate();
  } else {
    log.debug('Invalid date:' + str);
    log.debug('With date format:' + dateFormat.trim());

    // Only allow fallback for formats that are simple timestamps (x, X)
    // which represent Unix timestamps. For all other formats, if dayjs
    // strict parsing fails - throws an error.
    const isTimestampFormat = dateFormat.trim() === 'x' || dateFormat.trim() === 'X';

    if (!isTimestampFormat) {
      log.debug(`Invalid date: "${str}" does not match format "${dateFormat.trim()}".`);
    }

    const d = new Date(str);
    if (
      d === undefined ||
      isNaN(d.getTime()) ||
      // WebKit browsers can mis-parse invalid dates to be ridiculously
      // huge numbers, e.g. new Date('202304') gets parsed as January 1, 202304.
      // This can cause virtually infinite loops while rendering, so for the
      // purposes of Gantt charts we'll just treat any date beyond 10,000 AD/BC as
      // invalid.
      d.getFullYear() < -10000 ||
      d.getFullYear() > 10000
    ) {
      throw new Error('Invalid date:' + str);
    }
    return d;
  }
};

/**

Review comment (bug):
The comment on lines 304-307 states "if dayjs strict parsing fails - throws an error" but the code doesn't actually throw an error at this point. The error is only thrown later (line 325) after additional validation checks. The comment should be clarified to indicate that for non-timestamp formats, the code will eventually throw an error if the fallback `new Date(str)` parsing also fails.
```suggestion
    // strict parsing fails, the code will attempt to parse with new Date(str)
    // and only throws an error if that also fails.
```

Code after:
  }
  // Test for after
  const afterRePattern = /^after\s+(?<ids>[\d\w- ]+)/;
  const afterStatement = afterRePattern.exec(str);

  if (afterStatement !== null) {
    // check all after ids and take the latest
    let latestTask = null;
    for (const id of afterStatement.groups.ids.split(' ')) {
      let task = findTaskById(id);
      if (task !== undefined && (!latestTask || task.endTime > latestTask.endTime)) {
        latestTask = task;
      }
    }

    if (latestTask) {
      return latestTask.endTime;
    }
    const today = new Date();
    today.setHours(0, 0, 0, 0);
    return today;
  }

  // Check for actual date set using dayjs strict parsing
  let mDate = dayjs(str, dateFormat.trim(), true);
  if (mDate.isValid()) {
    return mDate.toDate();
  } else {
    log.debug('Invalid date:' + str);
    log.debug('With date format:' + dateFormat.trim());

    // Timestamp formats can fall back to new Date()
    const d = new Date(str);
    if (
      d === undefined ||
      isNaN(d.getTime()) ||
      // WebKit browsers can mis-parse invalid dates to be ridiculously
      // huge numbers, e.g. new Date('202304') gets parsed as January 1, 202304.
      // This can cause virtually infinite loops while rendering, so for the
      // purposes of Gantt charts we'll just treat any date beyond 10,000 AD/BC as
      // invalid.
      d.getFullYear() < -10000 ||
      d.getFullYear() > 10000
    ) {
      throw new Error('Invalid date:' + str);
    }
    return d;
  }
};

/**