configModel = $configModel ?? new ConfigurationModel(); } public function getSchoolYearRange(string $schoolYear): array { $startCfg = (string)($this->configModel->getConfig('fall_semester_start') ?? ''); $endCfg = (string)($this->configModel->getConfig('last_school_day') ?? ''); $start = null; $end = null; try { if ($startCfg !== '') { $start = new DateTimeImmutable($startCfg); } } catch (\Throwable) { $start = null; } try { if ($endCfg !== '') { $end = new DateTimeImmutable($endCfg); } } catch (\Throwable) { $end = null; } if ($start === null || $end === null) { if (preg_match('/^(\d{4})-(\d{4})$/', $schoolYear, $m)) { $y1 = (int)$m[1]; $y2 = (int)$m[2]; if ($start === null) { $start = new DateTimeImmutable($y1 . '-09-01'); } if ($end === null) { $end = new DateTimeImmutable($y2 . '-06-30'); } } else { $currentYear = (int)date('Y'); if ($start === null) { $start = new DateTimeImmutable($currentYear . '-09-01'); } if ($end === null) { $end = new DateTimeImmutable(($currentYear + 1) . '-06-30'); } } } if ($end < $start) { [$start, $end] = [$end, $start]; } return [$start->format('Y-m-d'), $end->format('Y-m-d')]; } public function getSemesterRange(string $schoolYear, string $semester): ?array { if (!preg_match('/^(\\d{4})-(\\d{4})$/', $schoolYear, $m)) { return null; } $y1 = (int)$m[1]; $y2 = (int)$m[2]; $normalized = ucfirst(strtolower(trim($semester))); $fallStartCfg = (string)($this->configModel->getConfig('fall_semester_start') ?? ''); $fallEndCfg = (string)($this->configModel->getConfig('fall_end_date') ?? ''); $springStartCfg = (string)($this->configModel->getConfig('spring_semester_start') ?? ''); $springEndCfg = (string)($this->configModel->getConfig('last_school_day') ?? ''); $md = static fn(string $cfg, int $year, string $fallback): string => $cfg !== '' ? sprintf('%04d-%s', $year, date('m-d', strtotime($cfg))) : $fallback; if ($normalized === 'Fall') { return [ $md($fallStartCfg, $y1, sprintf('%04d-09-21', $y1)), $md($fallEndCfg, $y2, sprintf('%04d-01-18', $y2)), ]; } if ($normalized === 'Spring') { return [ $md($springStartCfg, $y2, sprintf('%04d-01-25', $y2)), $md($springEndCfg, $y2, sprintf('%04d-05-31', $y2)), ]; } return null; } public function normalizeSemester(?string $semester): string { $value = strtolower(trim((string)($semester ?? ''))); if ($value === 'fall') { return 'Fall'; } if ($value === 'spring') { return 'Spring'; } return ''; } public function getSemesterForDate(?string $date = null): string { $fallStartCfg = (string)($this->configModel->getConfig('fall_semester_start') ?? ''); $springStartCfg = (string)($this->configModel->getConfig('spring_semester_start') ?? ''); $lastDayCfg = (string)($this->configModel->getConfig('last_school_day') ?? $this->configModel->getConfig('last_day_of_school') ?? ''); try { $target = new DateTimeImmutable($date ?: 'now'); } catch (\Throwable) { return ''; } try { $fallStart = $fallStartCfg !== '' ? new DateTimeImmutable($fallStartCfg) : null; } catch (\Throwable) { $fallStart = null; } try { $springStart = $springStartCfg !== '' ? new DateTimeImmutable($springStartCfg) : null; } catch (\Throwable) { $springStart = null; } try { $lastDay = $lastDayCfg !== '' ? new DateTimeImmutable($lastDayCfg) : null; } catch (\Throwable) { $lastDay = null; } if ($fallStart === null || $springStart === null || $lastDay === null) { return ''; } $target = $target->setTime(0, 0, 0); $fallStart = $fallStart->setTime(0, 0, 0); $springStart = $springStart->setTime(0, 0, 0); $lastDay = $lastDay->setTime(0, 0, 0); $nextFallStart = $fallStart <= $lastDay ? $fallStart->modify('+1 year') : $fallStart; if (($fallStart <= $target && $target < $springStart) || ($lastDay <= $target && $target < $nextFallStart) ) { return 'Fall'; } if ($springStart <= $target && $target < $lastDay) { return 'Spring'; } return ''; } }