The source 7day weather forecast graphic is missing. http://dig.abclocal.go.com/wabc/weather/web7day.jpg

How to query api.weather.gov, forecast.weather.gov and ipgeolocation.io and display weather and astronomical json data using Windows, PHP and Javascript. Crop and resize image with PHP and GD Library.

NWS New York, NY

The weather data is provided by the National Weather Service. The astronomical data is provided by ipgeolocation.io   forecast.weather.gov updates in minute 53. Sun/Moon updates at midnight. Refresh the page. See Legend.
Time: 22 Jul 04:23 pm EDT

api.weather.gov:
This Afternoon: 77°F
Tonight: 71°F
Wednesday: 81°F

forecast.weather.gov:
HI: 79°F
CURRENT: 74°F
LOW: 69°F

LINK: Sun / Moon data ipgeolocation.io
LINK: Sun / Moon data ipgeolocation.io local.

SUN:       06:14am      09:21pm
MOON:  03:13am      08:20pm

Legend

<!DOCTYPE html><html lang='en'><head><title>How to query api.weather.gov, forecast.weather.gov and ipgeolocation.io and display weather and astronomical json data using Windows, PHP and Javascript. Crop and resize image with PHP and GD Library.</title><meta content="text/html; charset=utf-8" http-equiv="Content-Type"><meta content="width=device-width, initial-scale=1.0" name="viewport"><style>a{text-decoration: none;}}</style></head>	

	<?php

	// Save as a php file.
	// Creates file: weatherData7dayForecastGraphic'.date('mdy').'.webp e.g. weatherData7dayForecastGraphic110123.webp
	// Query the NWS and USNO too often (NWS > once/hour. USNO > once/day. ipgeolocation.io > 30K requests per month OR > 1K per day.) and data might not be returned.
	// See https://www.weather.gov/documentation/services-web-api
	// Find your lat/long in xx.xxxx/yy.yyyy format
	// https://api.weather.gov/points/40.7766,-73.9713
	// Fetch weather data from the forecast URL: https://api.weather.gov/gridpoints/OKX/33,35/forecast
	// Fetch weather data from https://forecast.weather.gov/MapClick.php?lat=40.7766&lon=-73.9713&unit=0&lg=english&FcstType=json
	// See https://ipgeolocation.io/astronomy-api.html  Create apiKey and replace apiKey=?????????????????????????????????
	// https://api.ipgeolocation.io/astronomy?apiKey=?????????????????????????????????&lat=40.7766&long=-73.9713
	// See https://aa.usno.navy.mil/data/api   Create ID and replace ID=yourID e.g. ID=MYcharID
	// https://aa.usno.navy.mil/api/rstt/oneday?date=2023-11-1&coords=40.7766,-73.9713&tz=-4&dst=false&ID=yourID (USNO)
	// https://aa.usno.navy.mil/.... is harder to implement, more robust?, and free. Do not query > once per day.
	// Thanks to https://abc7ny.com/weather/ for the 7-day weather forecast graphic.

	date_default_timezone_set('America/New_York');
	if (date('I', time())) {$zdst='true';} else {$zdst='false';}// true=DaylightSavingsTime false=Standard Time. USNO query.
	$ztimezone=str_replace('0', '', date('O'));// Timezone offset stripped of 0 e.g. -0400 to -4    e.g. -0500 to -5. USNO query.
	$zurl="http://dig.abclocal.go.com/wabc/weather/web7day.jpg"; // Source image
	$zfilename='weatherData7dayForecastGraphic'.date('mdy').'.webp'; // Source image edited

	// zprocessImage1($zurl,$zfilename,72,166,1207,672,0,0,480,196,100);       

	// BEGIN Crop and resize image with PHP GD Library
	function zprocessImage1($zurl,$zfilename,$x1,$y1,$x2,$y2,$dst_x,$dst_y,$zFinalWidth,$zFinalHeight,$zcompression){
	$src_image = imagecreatefromjpeg($zurl); // get the source image.

	/* 
	if(!isset ($src_image)){
	echo '<p>zprocessImage1 failed. The imageType is '.$zimageType.'</p>';}
	only display above if imagecreatefromwebp displays: "is not a valid JPEG file"
	*/

	$dst_image = imagecreatetruecolor($zFinalWidth,$zFinalHeight); // Create a truecolor canvas to draw on the size of $zFinalWidth,$zFinalHeight. e.g. 480 x 196

	/*
	$x2 = 1166; $y2 = 560; // BottomRight X,Y
	$x1 = 0034; $y1 = 134; // TopLeft X,Y

	$x2-$x1 = CROP WIDTH
	$y2-$y1 = CROP HEIGHT
	
	$dst_x = 0; $dst_y = 0; = Where in the output image do you want the crop paste to begin.
	*/ 

	// Crop and resize
	imagecopyresampled($dst_image, $src_image, $dst_x, $dst_y, $x1, $y1, $zFinalWidth, $zFinalHeight, $x2-$x1, $y2-$y1); // arguments must be in this order

	// Output to file
	imagewebp ($dst_image,$zfilename,$zcompression); // output $resized with no compression (100 = none)
	// END Crop and resize image with PHP


	}// END Crop and resize image with PHP GD Library


	if(!file_exists('weatherData7dayForecastGraphic'.date('mdy').'.webp')){
	
	/*
	Crop, resize and output to file.
	Arguments must be in this order:
	zurl,zfilename,x1,y1,x2,y2,0,0,final width,final height,zcompression (100 = none. 75 is the default.)
	*/ 
	
	zprocessImage1($zurl,$zfilename,72,166,1207,672,0,0,480,196,100); 


	/*
	CLEAN UP 
	DELETE 7DAY WEATHER FORECAST GRAPHIC >= 2 days old
	*/
	
	$files = glob('weatherData7dayForecastGraphic[0-9]*.webp');
	$threshold = strtotime('-2 day');

	foreach ($files as $file) {
	if (is_file($file)) {
		if ($threshold >= filemtime($file)) {
			unlink($file).'<br>';
		}
	  }
	} // END CLEANUP


	} // END if(!file_exists('weather'.date('mdy').'BoiseID.webp')){

	
	?>
	
	
	<body style="font-size:18px;font-family:Segoe UI Semibold,Arial,Sans-Serif;">
	<div class="page" style="max-width:1360px;margin:0 auto;position:relative;background-color:#fff;padding:.5em;li{list-style-type: none;">
		<a href="http://dig.abclocal.go.com/wabc/weather/web7day.jpg"><img alt='The source 7day weather forecast graphic is missing. http://dig.abclocal.go.com/wabc/weather/web7day.jpg' height='196px' src="weatherData7dayForecastGraphic<?php echo date('mdy');?>.webp" width='480px'></a>
		<h3>How to query api.weather.gov, forecast.weather.gov and ipgeolocation.io and display weather and astronomical json data using Windows, PHP and Javascript. Crop and resize image with PHP and GD Library.
		<p>NWS New York, NY</p>
		</h3>
		<p>The weather data is provided by the National Weather Service. The astronomical data is provided by ipgeolocation.io. forecast.weather.gov updates in minute 53. Sun/Moon updates at midnight. Refresh the page. See Legend.<br />Time: <?php echo date('d M h:i a T');?></p>
		<p><a href="https://api.weather.gov/gridpoints/OKX/33,35/forecast" title="Weather data in .json format"><strong>api.weather.gov:</strong></a><br />
		<span id="z1"></span><br />
		<span id="z2"></span><br />
		<span id="z3"></span></p>
		<p><a href="https://forecast.weather.gov/MapClick.php?lat=40.7766&lon=-73.9713&unit=0&lg=english&FcstType=json" title="Weather data in .json format"><strong>forecast.weather.gov:</strong></a><br />
		<span id="zhi"></span><br />
		<span id="ztemp"></span><br />
		<span id="zlow"></span></p>
		
		
		
		
		
	

	
<script>








//https://stackoverflow.com/a/62734322/8826818
fetch("https://api.weather.gov/gridpoints/OKX/33,35/forecast", {
    method: "GET",

})
    .then(response => {
        if (!response.ok) {
            return Promise.reject(response);
        }
        return response.json();
    })
    .then(data => {
        console.log("Success");
        //console.log(data);
		document.getElementById("z1").innerHTML=data.properties.periods[0].name+': '+data.properties.periods[0].temperature+"°F";
		document.getElementById("z2").innerHTML=data.properties.periods[1].name+': '+data.properties.periods[1].temperature+"°F";
		document.getElementById("z3").innerHTML=data.properties.periods[2].name+': '+data.properties.periods[2].temperature+"°F";
    })
    .catch(error => {
        if (typeof error.json === "function") {
            error.json().then(jsonError => {
                console.log("Json error from API");
                console.log(jsonError);
            }).catch(genericError => {
                console.log("Generic error from API");
                console.log(error.statusText);
            });
        } else {
  
            console.log(error);
			document.getElementById("z1").innerHTML="https://api.weather.gov/gridpoints/OKX/33,35/forecast failed at "+new Date().toLocaleString()+"<br /><a href=mailto:nco.ops@noaa.gov?Subject=https://api.weather.gov/gridpoints/OKX/33,35/forecast failed at "+new Date().toLocaleDateString().replace(', ','')+" "+new Date().toLocaleTimeString().replace(' ','')+"&Body=https://api.weather.gov/gridpoints/OKX/33,35/forecast failed at "+new Date().toLocaleDateString().replace(', ','')+" "+new Date().toLocaleTimeString().replace(' ','')+">Report query failure.</a>" ;
        }
    });
	
	

fetch("https://forecast.weather.gov/MapClick.php?lat=40.7766&lon=-73.9713&unit=0&lg=english&FcstType=json", {
    method: "GET",

})
    .then(response => {
        if (!response.ok) {
            return Promise.reject(response);
        }
        return response.json();
    })
    .then(data => {
        console.log("Success");
        //console.log(data);
		if(data.time.tempLabel[0].match(/High/)){var zhi=0;var zlow=1;}else{var zlow=0;var zhi=1;}
		document.getElementById("zhi").innerHTML="HI: "+Math.ceil(data.data.temperature[zhi])+"°F";
		document.getElementById("ztemp").innerHTML="CURRENT: "+ Math.floor(data.currentobservation.Temp)+"°F";
		document.getElementById("zlow").innerHTML="LOW: "+ Math.floor(data.data.temperature[zlow])+"°F";
    })
    .catch(error => {
        if (typeof error.json === "function") {
            error.json().then(jsonError => {
                console.log("Json error from API");
                console.log(jsonError);
            }).catch(genericError => {
                console.log("Generic error from API");
                console.log(error.statusText);
            });
        } else {
            console.log("forecast.weather.gov is down");
            console.log(error);
			document.getElementById("zhi").innerHTML="forecast.weather.gov is down";
        }
    });





			
			
			
			
			
			
			


</script>






	
	
		<p>
			<a href="https://api.ipgeolocation.io/astronomy?apiKey=?????????????????????????????????&lat=40.7766&long=-73.9713">LINK: Sun / Moon data</a>
		</p>
		
	<?php

			$z56sunMoon=json_decode(file_get_contents("https://api.ipgeolocation.io/astronomy?apiKey=?????????????????????????????????&lat=40.7766&long=-73.9713"));

			// BEGIN SUN RISE/SET in 12hr format.
			echo 'SUN</a>:       '.(new DateTime($z56sunMoon->sunrise))->format("h:ia").'      '.(new DateTime($z56sunMoon->sunset))->format("h:ia");
			// END SUN RISE/SET in 12hr format.


			// 	BEGIN MOON RISE/SET in 12hr format. Not everyday has both a moonrise and moonset
			if($z56sunMoon->moonrise !== '-:-' && $z56sunMoon->moonset !== '-:-'){echo '<br>MOON</a>:   '.(new DateTime($z56sunMoon->moonrise))->format('h:ia').'      '.(new DateTime($z56sunMoon->moonset))->format('h:ia');}else{
			if($z56sunMoon->moonrise == '-:-'){echo '<br>MOON</a>:     N/A         '.(new DateTime($z56sunMoon->moonset))->format('h:ia');}else{echo '<br>MOON</a>:  '.(new DateTime($z56sunMoon->moonrise))->format('h:ia').'       N/A';}
			}// END MOON RISE/SET in 12hr format. Not everyday has both a moonrise and moonset


	?>
	
	
			<p>Make this:</p>
			<!--
			BEGIN Get x,y coordinates on graphic to plug into GD library
			https://github.com/makeuseofcode/x-y-coordinates-tooltip/tree/main
			changed .tooltip { position: absolute} to .tooltip { position: fixed}
			 -->
			<style>.container {position: relative;display: inline-block;}.tooltip { position: fixed;top: -30px; left: 0; display: none;	padding: 5px; background-color: #fff; color: #000; font-size: 24px;	border: .2em solid green; text-align:center }</style>
			<p>
			<div class="container" style="height:720px; width:1280px;" >
			<img id="myImgId" src="weatherData7dayForecastGraphicMakeThis.jpg" class="image" height=720px width=1280px alt="Complete the task at hand to display the weather 7day forecast graphic." />
			<div class="tooltip"></div>
			</div>
			</p>
			<script>const image = document.querySelector(".image");const tooltip = document.querySelector(".tooltip");image.addEventListener("mousemove", (e) => {
			tooltip.style.left = e.clientX + "px";tooltip.style.top = e.clientY - tooltip.offsetHeight - 10 + "px";tooltip.textContent = `X: ${e.offsetX}, Y: ${e.offsetY}`;});image.addEventListener("mouseover", () => {tooltip.style.display = "block";});image.addEventListener("mouseout", () => {		tooltip.style.display = "none";});</script>
			<!--
			END Get x,y coordinates on graphic to plug into GD library
			 -->
			Into this:<br />
			<img alt='The source 7day weather forecast graphic is missing. http://dig.abclocal.go.com/wabc/weather/web7day.jpg' width='480px' height='196px' title='Thanks to https://abc7ny.com/weather/ for the 7-day weather forecast graphic.' src="weatherData7dayForecastGraphicIntoThis.jpg">
		</div>
	</body>
</html>

Make this:

Complete the task at hand to display the weather 7day forecast graphic.

Into this:
The source 7day weather forecast graphic is missing. http://dig.abclocal.go.com/wabc/weather/web7day.jpg