PHP, XML & Prévisions Météo

Eléphant du PHP | 121 Messages

19 avr. 2008, 13:28

On ne sait plus trop comment s'habiller ces jours-ci. Un jour on se ballade poils au vent, caressé par un soleil complice. Le lendemain on rentre du boulot en vélo, arrosé par une pluie moqueuse. Des conditions climatiques perplexes, idéales pour présenter ma dernière classe : WdWeather.

Présentation

Utilisant les services pratiques et connus de weather.com, WdWeather permet d'obtenir les prévisions météorologiques jusqu'à 10 jours (limite imposée par le service). Les informations sont aussi nombreuses que variées. Ainsi pour chaque jour on obtient, en autre, les informations suivantes :

* Les heures de lever et de coucher du soleil
* Les températures les plus basse et les plus hautes

Et pour chaque période de la journée (Jour / Nuit) :

* Le numéro du pictogramme associé au temps.
* Une description du temps en anglais, par exemple : Mostly Sunny.
* La force et la direction du vent.
* Les précipitations.
* Le taux d'humidité.

Bref, il y a de quoi faire.

Je vous invite à découvrir le reste sur mon blog.

En attendant, voici le code:
class WdWeather
{
	var $markup_contents = '([^<]+)';
	
	function getCityCode($search)
	{
		#
		# we create a nice looking URL
		#
		
		$search = explode(',', $search);
		$search = array_map('urlencode', $search);
		$search = implode(',+', $search);
		
		#
		# ask the service about the location
		#
	
		$xml = file_get_contents
		(
			'http://xoap.weather.com/search/search?where=' . $search
		);
		
		#
		# try to get the first result
		#
		
		if (!preg_match('#loc id="([^"]+)#', $xml, $matches))
		{
			return;
		}
		
		return $matches[1];
	}

	function getWeather($city_code, $days)
	{
		$xml = file_get_contents
		(
			'http://xoap.weather.com/weather/local/' . $city_code .
			'?cc=*&unit=s&dayf=' . $days
		);
		
		if (!$xml)
		{
			return;
		}
		
		return $this->parseDays($xml);
	}
	
	function parseDays($xml)
	{
		$days = array();
		
		#
		# split xml by days
		#

		$parts = preg_split('#<day d=[^>]+>#', $xml);

		array_shift($parts);

		$mc = $this->markup_contents;

		foreach ($parts as $xml)
		{
			$days[] = $this->parseDay($xml);
		}
		
		return $days;
	}

	function parseDay($xml)
	{
		$mc = $this->markup_contents;
	
		preg_match
		(
			'#' .
			
			'<hi>' . $mc . '</hi>\s*' .
			'<low>' . $mc . '</low>\s*' .
			'<sunr>' . $mc . '</sunr>\s*' .
			'<suns>' . $mc . '</suns>\s*' .
			'<part p="d">(.*)</part>\s*' .
			'<part p="n">(.*)</part>' .
			
			'#ms',
			
			$xml, $matches
		);
		
		array_shift($matches);
					
		#
		# parse day periods (day / night)
		#
		
		$matches[4] = $this->parseDayPeriod($matches[4]);
		$matches[5] = $this->parseDayPeriod($matches[5]);
		
		#
		#
		#
		
		return array_combine
		(
			array('hi', 'low', 'sunr', 'suns', 'day', 'night'), $matches
		);
	}
	
	function parseDayPeriod($xml)
	{
		$mc = $this->markup_contents;

		preg_match
		(
			'#' .
			
			'<icon>' . $mc . '</icon>\s*' .
			'<t>' . $mc . '</t>\s*' .
			'<wind>(.*)</wind>\s*' .
			'<bt>' . $mc . '</bt>\s*' .
			'<ppcp>' . $mc . '</ppcp>\s*' .
			'<hmid>' . $mc . '</hmid>' .
			
			'#ms',
			
			$xml, $matches
		);
		
		array_shift($matches);
		
		$matches[2] = $this->parseWind($matches[2]);
		
		return array_combine
		(
			array('icon', 't', 'wind', 'bt', 'ppcp', 'hmid'), $matches
		);
	}
	
	function parseWind($xml)
	{
		$mc = $this->markup_contents;

		preg_match
		(
			'#' .
			
			'<s>' . $mc . '</s>\s*' .
			'<gust>' . $mc . '</gust>\s*' .
			'<d>' . $mc . '</d>\s*' .
			'<t>' . $mc . '</t\s*' .
			
			'#ms',
			
			$xml, $matches
		);
		
		array_shift($matches);
		
		return array_combine
		(
			array('s', 'gust', 'd', 't'), $matches
		);
	}

	static function toCelsius($f)
	{
		if (!is_numeric($f))
		{
			return $f;
		}
	
		return round(($f-32) * 5 / 9);
	}
	
	static function to24H($time)
	{
		preg_match('#(\d+)\:(\d+)\s+(AM|PM)?#', $time, $matches);
		
		if ($matches[3] == 'PM')
		{
			$matches[1] += 12;
		}

		return $matches[1] . ':' . $matches[2];
	}
}