Holy Trinity Church, MI Weather Maps °F °C°F °C Michigan Map Options Temperatures Weather Dew Point Wind Speeds Barometric Pressure Heat Index Wind Chill Temperatures Weather Dew Point Wind Speeds Barometric Pressure Heat Index Wind Chill Humidity UTC Time: 9/12/2026, 13:39 Your Time: Holy Trinity Church, Michigan Hour by Hour Forcast Aeronautical Observation: Automated synoptic observations via NWS Gateway. Auto-refresh in: 5:02 Holy Trinity Church, MI Regional Weather Expires:202609121400;;326050 ASUS43 KDTX 121310 RWRMI MICHIGAN HOURLY REGIONAL WEATHER ROUNDUP NATIONAL WEATHER SERVICE DETROIT/PONTIAC MI 900 AM EDT SAT SEP 12 2026 NOTE: "FAIR" INDICATES FEW OR NO CLOUDS BELOW 12,000 FEET WITH NO SIGNIFICANT WEATHER AND/OR OBSTRUCTION TO VISIBILITY. MIZ004>006-011>014-085-121400- CENTRAL UPPER MICHIGAN CITY SKY/WX TMP DP RH WIND PRES REMARKS MANISTIQUE CLOUDY 66 64 94 S9 29.72F TC 19 ESCANABA CLOUDY 67 63 87 SW12G21 29.74R TC 19 MENOMINEE CLOUDY 68 64 87 SW12 29.74F TC 20 SAWYER-GWINN SUNNY 63 59 88 S14 29.71R TC 17 MUNISING N/A 68 60 75 S8 29.70S TC 20 $$ SKY/WX - Weather TMP - Temperature DP - Dew Point RH - HumidityWIND - Wind Direction/Speed PRES - Barometric Pressure VSB - VisibilityWCI - Wind Chill Index E13G22 Wind - East Wind 13 mph/Gusts of 22 mph Michigan Weather Map Michigan Wind Speeds Map Michigan Humidity Map Michigan Barometric Pressure Map 2026-09-12 09:39:14 %%CODE $stateCode = 'ne'; $cwaKey = 'oax'; $currentCity = 'omaha'; $refLat = 41.26390; $refLon = -96.01170; $refZone = 'NEZ052'; $targetLimit = 30; $enableMissingLinkLogging = true; $stateCode = !empty($GET['state']) ? $GET['state'] : (!empty($stateCode) ? $stateCode : 'ct'); $cwaKey = !empty($GET['cwa']) ? $GET['cwa'] : (!empty($cwaKey) ? $cwaKey : 'box'); $stateCode = strtolower(preg_replace('/[^a-z]/i', '', $stateCode)); $cwaKey = strtolower(preg_replace('/[^a-z0-9]/i', '', $cwaKey)); if (!function_exists('getWxDbConnection')) { function getWxDbConnection() { static $pdo = null; if ($pdo === null) { $dbConfigFile = '/home/wxworld/public_html/database.ini.php'; if (file_exists($dbConfigFile)) { require $dbConfigFile; try { $dsn = "mysql:host={$dbserver};dbname={$dbdatabase};charset=utf8mb4"; $pdo = new PDO($dsn, $dbuser, $dbpassword, array( PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION, PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC, PDO::ATTR_EMULATE_PREPARES => true, )); } catch (PDOException $e) { error_log("WeatherWorld DB Connection Error: " . $e->getMessage()); return null; } } } return $pdo; } } if (!function_exists('getNwsConditionMap')) { function getNwsConditionMap() { return array( 'SUNNY' => array('label' => 'Sunny', 'icon' => 'wi-day-sunny'), 'CLEAR' => array('label' => 'Clear', 'icon' => 'wi-day-sunny'), 'PTCLDY' => array('label' => 'Partly Cloudy', 'icon' => 'wi-day-cloudy'), 'MOCLDY' => array('label' => 'Mostly Cloudy', 'icon' => 'wi-day-cloudy-high'), 'CLOUDY' => array('label' => 'Cloudy', 'icon' => 'wi-cloudy'), 'HAZE' => array('label' => 'Haze', 'icon' => 'wi-day-haze'), 'WINDY' => array('label' => 'Windy', 'icon' => 'wi-day-windy'), 'DRZL' => array('label' => 'Drizzle', 'icon' => 'wi-day-sprinkle'), 'DRIZZLE' => array('label' => 'Drizzle', 'icon' => 'wi-day-sprinkle'), 'SPRINKLES' => array('label' => 'Sprinkles', 'icon' => 'wi-day-sprinkle'), 'RAIN' => array('label' => 'Rain', 'icon' => 'wi-day-rain'), 'SHWRS' => array('label' => 'Rain Showers', 'icon' => 'wi-day-showers'), 'RNSNOW' => array('label' => 'Rain & Snow Mix', 'icon' => 'wi-day-rain-mix'), 'SNOW' => array('label' => 'Snow', 'icon' => 'wi-day-snow'), 'SNOSHWR' => array('label' => 'Snow Showers', 'icon' => 'wi-day-snow'), 'SNOWSHWRS' => array('label' => 'Snow Showers', 'icon' => 'wi-day-snow'), 'SLEET' => array('label' => 'Sleet', 'icon' => 'wi-day-sleet'), 'TSTRMS' => array('label' => 'Thunderstorms', 'icon' => 'wi-day-thunderstorm'), 'TSTMS' => array('label' => 'Thunderstorms', 'icon' => 'wi-day-thunderstorm'), 'VRYHOT' => array('label' => 'Very Hot', 'icon' => 'wi-hot') ); } } if (!function_exists('renderSftAreaForecast')) { function renderSftAreaForecast($parsedDataCollection, $defaultStateCode = 'ct') { global $refLat, $refLon, $refZone, $targetLimit, $currentCity, $stateCode, $enableMissingLinkLogging; $map = getNwsConditionMap(); $pdo = getWxDbConnection(); $maxLimit = isset($targetLimit) ? intval($targetLimit) : 30; $lLat = !empty($refLat) ? floatval($refLat) : 45.18400; $lLon = !empty($refLon) ? floatval($refLon) : -84.95670; $zoneAliasMap = array( 'COZ040' => 'COZ038', ); $resolvedRefZone = !empty($refZone) ? strtoupper(trim($refZone)) : ''; if (isset($zoneAliasMap[$resolvedRefZone])) { $resolvedRefZone = $zoneAliasMap[$resolvedRefZone]; } $forcedState = !empty($stateCode) ? strtolower($stateCode) : strtolower($defaultStateCode); $forcedCityName = !empty($currentCity) ? trim($currentCity) : ''; $masterZones = array(); foreach ($parsedDataCollection as $parsedData) { if (isset($parsedData['zones']) && is_array($parsedData['zones'])) { foreach ($parsedData['zones'] as $zKey => $zVal) { $zKeyUpper = strtoupper(trim($zKey)); if (!isset($masterZones[$zKeyUpper])) { $masterZones[$zKeyUpper] = $zVal; } } } } if (empty($masterZones)) { return 'No regional zone data found in cache payloads.'; } $dbZoneCoords = array(); $targetZones = array_keys($masterZones); if ($pdo && !empty($targetZones)) { $chunkedZones = array_chunk($targetZones, 50); foreach ($chunkedZones as $chunk) { $placeholders = array(); $params = array(); foreach ($chunk as $i => $zKey) { $ph = ":z_" . md5($zKey) . "{$i}"; $placeholders[] = $ph; $params[$ph] = strtoupper(trim($zKey)); } $sql = "SELECT UPPER(a.wxzone) AS wxzone_raw, p.lat, p.lon, p.name, p.state, " . "(3959 * ACOS(COS(RADIANS(:currentLat)) * COS(RADIANS(p.lat)) * COS(RADIANS(p.lon) - RADIANS(:currentLon)) + SIN(RADIANS(:currentLat)) * SIN(RADIANS(p.lat)))) AS distance " . "FROM places p " . "JOIN alt_zone_info a ON p.places_id = a.places_id " . "WHERE UPPER(TRIM(a.wxzone)) IN (" . implode(',', $placeholders) . ") " . "ORDER BY distance ASC"; $stmt = $pdo->prepare($sql); $execParams = array_merge(array(':currentLat' => $lLat, ':currentLon' => $lLon), $params); $stmt->execute($execParams); while ($row = $stmt->fetch()) { $zUpper = strtoupper($row['wxzone_raw']); if (!isset($dbZoneCoords[$zUpper])) { $dbZoneCoords[$zUpper] = array( 'lat' => floatval($row['lat']), 'lon' => floatval($row['lon']), 'nearest_place' => $row['name'] . ', ' . $row['state'] ); } } } } $tempRankedZones = array(); foreach ($masterZones as $zoneKey => $zoneData) { $zKeyUpper = strtoupper(trim($zoneKey)); $zStatePrefix = strtolower(substr($zKeyUpper, 0, 2)); $isRef = ($zKeyUpper === $resolvedRefZone); $zoneState = !empty($zoneData['state_code']) ? strtolower($zoneData['state_code']) : $zStatePrefix; if (!preg_match('/^[a-z]{2}$/', $zoneState)) { $zoneState = $forcedState; } $closestCity = ''; if (!empty($zoneData['cities'][0])) { $closestCity = trim($zoneData['cities'][0]) . ', ' . strtoupper($zoneState); } elseif (!empty($zoneData['primary_name'])) { $closestCity = trim($zoneData['primary_name']) . ', ' . strtoupper($zoneState); } elseif (!empty($zoneData['zone_name'])) { $closestCity = trim($zoneData['zone_name']) . ', ' . strtoupper($zoneState); } elseif (!empty($zoneData['name'])) { $closestCity = trim($zoneData['name']) . ', ' . strtoupper($zoneState); } else { $closestCity = trim($zKeyUpper) . ', ' . strtoupper($zoneState); } if ($isRef) { if ($forcedCityName !== '') { $formattedRefCity = ucwords(strtolower($forcedCityName)); $closestCity = $formattedRefCity . ', ' . strtoupper($forcedState); } $zoneState = $forcedState; } $distance = 9999.0; $zoneLat = null; $zoneLon = null; if (isset($dbZoneCoords[$zKeyUpper])) { $zoneLat = $dbZoneCoords[$zKeyUpper]['lat']; $zoneLon = $dbZoneCoords[$zKeyUpper]['lon']; } elseif (isset($zoneData['lat']) && isset($zoneData['lon'])) { $zoneLat = floatval($zoneData['lat']); $zoneLon = floatval($zoneData['lon']); } if ($zoneLat !== null && $zoneLon !== null) { $theta = $lLon - $zoneLon; $dist = sin(deg2rad($lLat)) * sin(deg2rad($zoneLat)) + cos(deg2rad($lLat)) * cos(deg2rad($zoneLat)) * cos(deg2rad($theta)); $dist = acos(min(1.0, max(-1.0, $dist))); $distance = rad2deg($dist) * 69.09; } if ($isRef) { $distance = -1.0; } $parts = explode(',', $closestCity); $cleanCityName = trim($parts[0]); $displayState = isset($parts[1]) ? trim($parts[1]) : strtoupper($zoneState); $citySignature = strtolower($cleanCityName) . '|' . strtolower($displayState); if (!isset($tempRankedZones[$citySignature])) { $tempRankedZones[$citySignature] = array( 'zoneKey' => $zoneKey, 'zoneData' => $zoneData, 'zoneState' => $zoneState, 'cleanCityName' => $cleanCityName, 'displayState' => $displayState, 'distance' => $distance, 'is_ref' => $isRef ); } else { if ($isRef || (!$tempRankedZones[$citySignature]['is_ref'] && $distance < $tempRankedZones[$citySignature]['distance'])) { $tempRankedZones[$citySignature] = array( 'zoneKey' => $zoneKey, 'zoneData' => $zoneData, 'zoneState' => $zoneState, 'cleanCityName' => $cleanCityName, 'displayState' => $displayState, 'distance' => $distance, 'is_ref' => $isRef ); } } } $rankedZones = array_values($tempRankedZones); usort($rankedZones, 'sft_sort_ranked_zones'); $existingPlacesMap = array(); if ($pdo && !empty($rankedZones)) { $uniquePairs = array(); foreach ($rankedZones as $item) { $pairKey = strtolower($item['cleanCityName']) . '|' . strtolower($item['displayState']); if ($item['is_ref']) { $existingPlacesMap[$pairKey] = true; } else { $uniquePairs[$pairKey] = array( 'name' => $item['cleanCityName'], 'state' => $item['displayState'] ); } } if (!empty($uniquePairs)) { $pairChunks = array_chunk(array_values($uniquePairs), 50); foreach ($pairChunks as $chunk) { $tuples = array(); $params = array(); $idx = 0; foreach ($chunk as $p) { $namePlaceholder = ":pname{$idx}"; $statePlaceholder = ":pstate_{$idx}"; $tuples[] = "({$namePlaceholder}, {$statePlaceholder})"; $params[$namePlaceholder] = $p['name']; $params[$statePlaceholder] = $p['state']; $idx++; } $sql = "SELECT DISTINCT name, state FROM places WHERE (name, state) IN (" . implode(',', $tuples) . ")"; $stmt = $pdo->prepare($sql); $stmt->execute($params); while ($row = $stmt->fetch()) { $mapKey = strtolower(trim($row['name'])) . '|' . strtolower(trim($row['state'])); $existingPlacesMap[$mapKey] = true; } } } } $cityCounter = 0; $html = ''; foreach ($rankedZones as $item) { if ($cityCounter >= $maxLimit) { break; } $zoneKey = $item['zoneKey']; $zoneData = $item['zoneData']; $cleanCityName = $item['cleanCityName']; $displayState = $item['displayState']; $zoneState = $item['zoneState']; $cityCounter++; $displayTitle = $cleanCityName . ', ' . strtoupper($displayState); $citySlug = strtolower(str_replace(' ', '+', $cleanCityName)); $forecastUrl = 'https://www.weatherworld.com/14dayweather/' . strtolower($displayState) . '/' . $citySlug . '.html'; $warningUrl = 'https://www.weatherworld.com/stormwarnings/' . strtolower($displayState) . '/' . $citySlug . '.html'; $pairKey = strtolower($cleanCityName) . '|' . strtolower($displayState); $placeExistsInDb = isset($existingPlacesMap[$pairKey]) || $item['is_ref']; if ($placeExistsInDb) { $titleContent = '' . htmlspecialchars($displayTitle) . ''; } else { $titleContent = htmlspecialchars($displayTitle); if (!empty($enableMissingLinkLogging)) { $logMessage = sprintf("[%s] Unlinked place: %s (Zone: %s) not found in database.\n", date('Y-m-d H:i:s'), $displayTitle, $zoneKey); @error_log($logMessage, 3, '/home/wxworld/public_html/php-includes/missing_links.log'); } } $forecastPeriods = array(); if (isset($zoneData['forecast_periods']) && is_array($zoneData['forecast_periods'])) { $forecastPeriods = $zoneData['forecast_periods']; } elseif (isset($zoneData['periods']) && is_array($zoneData['periods'])) { $forecastPeriods = $zoneData['periods']; } elseif (isset($zoneData['properties']['periods']) && is_array($zoneData['properties']['periods'])) { $forecastPeriods = $zoneData['properties']['periods']; } $activeAlerts = array(); if (!empty($zoneData['active_alert'])) { if (is_array($zoneData['active_alert'])) { $activeAlerts = $zoneData['active_alert']; } else { $splitAlerts = preg_split('/(?=...[A-Z])/', $zoneData['active_alert']); foreach ($splitAlerts as $sa) { $trimmed = trim($sa); if ($trimmed !== '') $activeAlerts[] = $trimmed; } } } $columns = array(); foreach ($forecastPeriods as $period) { $pName = trim(isset($period['period']) ? $period['period'] : (isset($period['name']) ? $period['name'] : '')); $rawDate = isset($period['day_date']) ? $period['day_date'] : (isset($period['startTime']) ? substr($period['startTime'], 0, 10) : ''); $pDate = $rawDate !== '' ? date('m-d', strtotime($rawDate)) : ''; $temp = isset($period['hi_lo_temp']) ? $period['hi_lo_temp'] : (isset($period['temperature']) ? $period['temperature'] : ''); $cond = isset($period['condition']) ? $period['condition'] : (isset($period['shortForecast']) ? $period['shortForecast'] : ''); $icon = isset($period['condition_icon']) ? $period['condition_icon'] : (isset($period['icon']) ? $period['icon'] : ''); $popRaw = isset($period['pop']) ? $period['pop'] : (isset($period['probabilityOfPrecipitation']['value']) ? $period['probabilityOfPrecipitation']['value'] : ''); $pop = ($popRaw !== '' && $popRaw !== null) ? intval($popRaw) : 0; $desc = isset($period['day_night_zone_text']) ? $period['day_night_zone_text'] : (isset($period['detailed_forecast']) ? $period['detailed_forecast'] : (isset($period['detailedForecast']) ? $period['detailedForecast'] : '')); $isDaytimeFlag = isset($period['isDaytime']) ? $period['isDaytime'] : null; $pNameLower = strtolower($pName); if (strpos($pNameLower, 'early this morning') !== false || strpos($pNameLower, 'this morning') !== false) { $pName = 'This Morning'; } elseif (strpos($pNameLower, 'today') !== false && strpos($pNameLower, 'tonight') === false) { $pName = 'Today'; } $isNight = ($isDaytimeFlag !== null) ? !$isDaytimeFlag : (stripos($pName, 'night') !== false); if ($isNight) { $matched = false; foreach ($columns as &$col) { if (isset($col['full_date']) && $col['full_date'] === $rawDate && $col['low'] === '') { $col['low'] = $temp; $col['night_pop'] = $pop; if (!empty($desc)) $col['night_desc'] = $desc; $matched = true; break; } } unset($col); if ($matched) continue; } $columns[] = array( 'day' => $pName, 'date' => $pDate, 'full_date' => $rawDate, 'high' => !$isNight ? $temp : '', 'low' => $isNight ? $temp : '', 'condition' => $cond, 'condition_icon' => $icon, 'day_pop' => !$isNight ? $pop : 0, 'night_pop' => $isNight ? $pop : 0, 'day_desc' => !$isNight ? ($desc !== '' ? $desc : ($pName . ': ' . $cond)) : '', 'night_desc' => $isNight ? ($desc !== '' ? $desc : ($pName . ': ' . $cond)) : '' ); } $html .= ''; $html .= ' ' . $titleContent . ''; if (!empty($activeAlerts)) { foreach ($activeAlerts as $alertText) { $cleanAlert = trim($alertText, '. '); if ($cleanAlert !== '') { $html .= ''; $html .= ' ' . htmlspecialchars(strtoupper($cleanAlert)) . ''; $html .= ''; } } } $html .= ''; $colIndex = 0; foreach ($columns as $col) { $rawWx = strtoupper($col['condition_icon'] !== '' ? $col['condition_icon'] : $col['condition']); $cond = isset($map[$rawWx]) ? $map[$rawWx] : array('label' => ($col['condition'] !== '' ? $col['condition'] : $rawWx), 'icon' => 'wi-cloud'); $displayPop = max($col['day_pop'], $col['night_pop']); $activeClass = ($colIndex === 0) ? ' active' : ''; $targetId = 'desc-' . md5($zoneKey . $cleanCityName) . '-' . $colIndex; $rawDayName = trim($col['day']); $cleanDayName = preg_replace('/]fa-moon[^>]>.?/i', 'Night', $rawDayName); if (stripos($cleanDayName, 'night') !== false || preg_match('/(/|to|thru|through|and|-)/i', $cleanDayName)) { $daysRegex = '/\b(Sunday|Monday|Tuesday|Wednesday|Thursday|Friday|Saturday)\b/i'; $cleanDayName = preg_replace_callback($daysRegex, 'sft_ucfirst_substr', $cleanDayName); $cleanDayName = preg_replace('/\s[/-]\s*/', '-', $cleanDayName); } $html .= ''; $html .= '' . str_replace('','', $cleanDayName) . ''; $html .= ''; $html .= '' . htmlspecialchars($cond['label']) . ''; $html .= ''; if ($col['high'] !== '' && $col['low'] !== '') { $fHigh = (int)$col['high']; $fLow = (int)$col['low']; $cHigh = round(($fHigh - 32) * 5 / 9); $cLow = round(($fLow - 32) * 5 / 9); $html .= '' . $fHigh . '°/ ' . $fLow . '° '; $html .= '' . $cHigh . '°/ ' . $cLow . '°'; } elseif ($col['high'] !== '') { $fHigh = (int)$col['high']; $cHigh = round(($fHigh - 32) * 5 / 9); $html .= '' . $fHigh . '°' . $cHigh . '°'; } elseif ($col['low'] !== '') { $fLow = (int)$col['low']; $cLow = round(($fLow - 32) * 5 / 9); $html .= '' . $fLow . '°' . $cLow . '°'; } $html .= ''; $isPrecip = (stripos($col['condition'], 'rain') !== false || stripos($col['condition'], 'showers') !== false || stripos($col['condition'], 'snow') !== false || stripos($col['condition'], 'thunderstorm') !== false); if ($displayPop > 0) { $html .= ' ' . $displayPop . '%'; } elseif ($isPrecip) { $html .= 'N/A'; } else { $html .= '0%'; } $html .= ''; $colIndex++; } $html .= ''; $html .= ''; $colIndex = 0; foreach ($columns as $col) { $displayStyle = ($colIndex === 0) ? 'display: block;' : 'display: none;'; $targetId = 'desc-' . md5($zoneKey . $cleanCityName) . '-' . $colIndex; $html .= ''; $hasDay = !empty($col['day_desc']); $hasNight = !empty($col['night_desc']); if ($hasDay && $hasNight) { $html .= ' Day: ' . htmlspecialchars($col['day_desc']) . ''; $html .= ' Night: ' . htmlspecialchars($col['night_desc']) . ''; } elseif ($hasDay) { $html .= ' Day: ' . htmlspecialchars($col['day_desc']) . ''; } elseif ($hasNight) { $html .= ' Night: ' . htmlspecialchars($col['night_desc']) . ''; } else { $html .= '' . $col['day'] . ': ' . $col['condition'] . ''; } $html .= ''; $colIndex++; } $html .= ''; $html .= ''; } $html .= ''; return $html; } } if (!function_exists('sft_sort_ranked_zones')) { function sft_sort_ranked_zones($a, $b) { if ($a['is_ref'] && !$b['is_ref']) return -1; if (!$a['is_ref'] && $b['is_ref']) return 1; if ($a['distance'] == $b['distance']) return 0; return ($a['distance'] < $b['distance']) ? -1 : 1; } } if (!function_exists('sft_ucfirst_substr')) { function sft_ucfirst_substr($m) { return ucfirst(substr($m[1], 0, 3)); } } $cacheDir = '/home/wxworld/public_html/cachezone/sftcache/'; $primaryFile = $cacheDir . $cwaKey . '.json'; if (file_exists($primaryFile)) { $jsonContent = file_get_contents($primaryFile); $parsedPrimary = json_decode($jsonContent, true); if ($parsedPrimary && is_array($parsedPrimary)) { $parsedDataCollection = array($parsedPrimary); if (!empty($parsedPrimary['adjoining_cwas']) && is_array($parsedPrimary['adjoining_cwas'])) { foreach ($parsedPrimary['adjoining_cwas'] as $adjKey) { $adjFile = $cacheDir . strtolower(trim($adjKey)) . '.json'; if (file_exists($adjFile)) { $adjContent = file_get_contents($adjFile); $adjData = json_decode($adjContent, true); if ($adjData && is_array($adjData)) { $parsedDataCollection[] = $adjData; } } } } echo renderSftAreaForecast($parsedDataCollection, $stateCode); } else { echo 'Invalid JSON structure or decode failure in primary cache file.'; } } else { echo 'Source JSON cache file not found: ' . htmlspecialchars($primaryFile) . ''; } CODE%%
Holy Trinity Church Radar Loop Use the map search tool if you want to place a location marker on the radar map...