// 2. 気象庁公式データ(年間ファイル管理対応ローダー) function getOfficialTideData($dateStr) { $dt = new DateTime($dateStr); $year = $dt->format('Y'); // index.phpと同じ階層にある tide_data/2026.json を確実に指定 $tideFile = __DIR__ . '/tide_data/' . $year . '.json'; if (file_exists($tideFile)) { $json = file_get_contents($tideFile); $data = json_decode($json, true); if (is_array($data) && isset($data[$dateStr])) { $dayData = $data[$dateStr]; // 月齢計算 $utcRef = gmmktime(18, 0, 0, 1, 6, 2000); $targetUtc = gmmktime(0, 0, 0, (int)$dt->format('m'), (int)$dt->format('d'), (int)$dt->format('Y')); $days = ($targetUtc - $utcRef) / (60 * 60 * 24); $newMoonCycle = 29.53058867; $moonAge = fmod(fmod($days, $newMoonCycle) + $newMoonCycle, $newMoonCycle); $lunarDay = (int)floor($moonAge) + 1; $illumination = round((1 - cos(2 * M_PI * ($moonAge / $newMoonCycle))) / 2 * 100); $moonIcon = ($illumination <= 5) ? '🌑' : (($illumination >= 95) ? '🌕' : '🌔'); $tideType = ($lunarDay <= 3 || ($lunarDay >= 13 && $lunarDay <= 17)) ? '大潮' : (($lunarDay >= 7 && $lunarDay <= 10) ? '小潮' : '中潮'); return [ 'lunarDay' => $lunarDay, 'moonAge' => number_format($moonAge, 1), 'illumination' => $illumination, 'moonIcon' => $moonIcon, 'tideType' => $tideType, 'highs' => $dayData['highs'], 'lows' => $dayData['lows'], 'curve' => $dayData['curve'] ]; } } // 万が一データが見つからない場合のフォールバック return [ 'lunarDay' => 1, 'moonAge' => '1.0', 'illumination' => 0, 'moonIcon' => '🌑', 'tideType' => '中潮', 'highs' => [['h' => '05:30', 'v' => 180]], 'lows' => [['h' => '11:30', 'v' => 50]], 'curve' => [] ]; }