Source for file Common.php
Documentation is available at Common.php
/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4 foldmethod=marker: */
* PEAR::Services_Weather_Common
* Copyright (c) 2005-2011, Alexander Wirtz
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* o Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* o Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* o Neither the name of the software nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
* @package Services_Weather
* @author Alexander Wirtz <alex@pc4p.net>
* @copyright 2005-2011 Alexander Wirtz
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
* @link http://pear.php.net/package/Services_Weather
require_once "Services/Weather.php";
// {{{ natural constants and measures
define("SERVICES_WEATHER_RADIUS_EARTH", 6378.15 );
// {{{ default values for the sun-functions
define("SERVICES_WEATHER_SUNFUNCS_DEFAULT_LATITUDE", 31.7667 );
define("SERVICES_WEATHER_SUNFUNCS_DEFAULT_LONGITUDE", 35.2333 );
define("SERVICES_WEATHER_SUNFUNCS_SUNRISE_ZENITH", 90.83 );
define("SERVICES_WEATHER_SUNFUNCS_SUNSET_ZENITH", 90.83 );
// {{{ class Services_Weather_Common
* Parent class for weather-services. Defines common functions for unit
* conversions, checks for cache enabling and does other miscellaneous
* @package Services_Weather
* @author Alexander Wirtz <alex@pc4p.net>
* @copyright 2005-2011 Alexander Wirtz
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
* @version Release: 1.4.7
* @link http://pear.php.net/package/Services_Weather
* Format of the units provided (standard/metric/custom)
* @var string $_unitsFormat
* Custom format of the units
* @var array $_customUnitsFormat
var $_customUnitsFormat = array (
* Options for HTTP requests
* @var array $_httpOptions
var $_httpOptions = array ();
* Format of the used dates
* @var string $_dateFormat
var $_dateFormat = "m/d/y";
* Format of the used times
* @var string $_timeFormat
var $_timeFormat = "G:i A";
* Object containing the location-data
* @var object stdClass $_location
* Object containing the weather-data
* @var object stdClass $_weather
* Object containing the forecast-data
* @var object stdClass $_forecast
* Cache, containing the data-objects
* @var object Cache $_cache
* Provides check for Cache
* @var bool $_cacheEnabled
var $_cacheEnabled = false;
function Services_Weather_Common ($options, &$error)
// Set some constants for the case when PHP4 is used, as the
// date_sunset/sunrise functions are not implemented there
if (!defined("SUNFUNCS_RET_TIMESTAMP")) {
define("SUNFUNCS_RET_TIMESTAMP", 0 );
define("SUNFUNCS_RET_STRING", 1 );
define("SUNFUNCS_RET_DOUBLE", 2 );
// Set options accordingly
if (isset ($options["cacheType"])) {
if (isset ($options["cacheOptions"])) {
$status = $this->setCache($options["cacheType"], $options["cacheOptions"]);
$status = $this->setCache($options["cacheType"]);
if (isset ($options["unitsFormat"])) {
if (isset ($options["customUnitsFormat"])) {
$this->setUnitsFormat($options["unitsFormat"], $options["customUnitsFormat"]);
if (isset ($options["httpTimeout"])) {
if (isset ($options["httpProxy"])) {
if (isset ($options["dateFormat"])) {
if (isset ($options["timeFormat"])) {
* Enables caching the data, usage strongly recommended
* Requires Cache to be installed
* @param string $cacheType
* @param array $cacheOptions
* @return PEAR_Error|bool
* @throws PEAR_Error::SERVICES_WEATHER_ERROR_CACHE_INIT_FAILED
function setCache($cacheType = "file", $cacheOptions = array ())
if ($cacheType == "lite") {
if ((@include_once "Cache/Lite.php") == false ) {
$cacheOptions["automaticSerialization"] = true;
$cacheOptions["pearErrorMode"] = CACHE_LITE_ERROR_RETURN;
$cacheOptions["lifeTime"] = null;
@$cache = new Cache_Lite ($cacheOptions);
// The error handling in Cache is a bit crummy (read: not existent)
// so we have to do that on our own...
if ((@include_once "Cache.php") === false ) {
@$cache = new Cache ($cacheType, $cacheOptions);
$this->_cacheEnabled = true;
$this->_cacheEnabled = false;
* Wrapper to retrieve cached data
* Requires Cache to be installed
function _getCache ($id, $type)
if ($this->_cacheEnabled) {
$cache = $this->_cache->get ($id, $type);
$cache = $this->_cache->get ($id, $type);
* Wrapper to retrieve cached user-data
* Requires Cache to be installed
function _getUserCache ($id, $type)
if ($this->_cacheEnabled) {
$cache = $this->_cache->get ($id, $type. "_user");
$cache = $this->_cache->getUserdata ($id, $type);
* Wrapper to save data to cache
* Requires Cache to be installed
function _saveCache ($id, $data, $userData, $type)
if ($this->_cacheEnabled) {
$this->_cache->setLifeTime (null );
return ($this->_cache->save ($data, $id, $type) && $this->_cache->save ($userData, $id, $type. "_user"));
return $this->_cache->extSave ($id, $data, $userData, constant("SERVICES_WEATHER_EXPIRES_". strtoupper($type)), $type);
* Changes the representation of the units (standard/metric)
* @param string $unitsFormat
* @param array $customUnitsFormat
if (!isset ($acceptedFormats)) {
$acceptedFormats = array (
"temp" => array ("c", "f"),
"vis" => array ("m", "km", "ft", "sm"),
"height" => array ("m", "ft"),
"wind" => array ("mph", "kmh", "kt", "mps", "fps", "bft"),
"pres" => array ("in", "hpa", "mb", "mm", "atm"),
"rain" => array ("in", "mm")
$this->_unitsFormat = strtolower($unitsFormat{0 });
if ($this->_unitsFormat == "c" && is_array($customUnitsFormat)) {
foreach ($customUnitsFormat as $key => $value) {
$this->_customUnitsFormat[$key] = $value;
} elseif ($this->_unitsFormat == "c") {
$this->_unitsFormat = "s";
* Sets an option for usage in HTTP_Request objects
if (is_string($varName) && $varName != "" && !empty ($varValue)) {
$this->_httpOptions[$varName] = $varValue;
* Sets the timeout in seconds for HTTP requests
* @param int $httpTimeout
$this->_httpOptions["timeout"] = $httpTimeout;
* Sets the proxy for HTTP requests
* @param string $httpProxy
if (($proxy = parse_url($httpProxy)) !== false && $proxy["scheme"] == "http") {
if (isset ($proxy["user"]) && $proxy["user"] != "") {
$this->_httpOptions["proxy_user"] = $proxy["user"];
if (isset ($proxy["pass"]) && $proxy["pass"] != "") {
$this->_httpOptions["proxy_pass"] = $proxy["pass"];
if (isset ($proxy["host"]) && $proxy["host"] != "") {
$this->_httpOptions["proxy_host"] = $proxy["host"];
if (isset ($proxy["port"]) && $proxy["port"] != "") {
$this->_httpOptions["proxy_port"] = $proxy["port"];
* Returns the selected units format
* @param string $unitsFormat
$unitsFormat = $this->_unitsFormat;
$c = $this->_customUnitsFormat;
// {{{ setDateTimeFormat()
* Changes the representation of time and dates (see http://www.php.net/date)
* @param string $dateFormat
* @param string $timeFormat
$this->_dateFormat = $dateFormat;
$this->_timeFormat = $timeFormat;
// {{{ convertTemperature()
* Convert temperature between f and c
* @param float $temperature
if ($temperature == "N/A") {
"f" => $temperature, "c" => ($temperature - 32 ) / 1.8
"f" => 1.8 * $temperature + 32 , "c" => $temperature
return $result[$from][$to];
* Convert speed between mph, kmh, kt, mps, fps and bft
* Function will return "false" when trying to convert from
* Beaufort, as it is a scale and not a true measurement
* @link http://www.spc.noaa.gov/faq/tornado/beaufort.html
"mph" => 1 , "kmh" => 1.609344 , "kt" => 0.8689762 , "mps" => 0.44704 , "fps" => 1.4666667
"mph" => 0.6213712 , "kmh" => 1 , "kt" => 0.5399568 , "mps" => 0.2777778 , "fps" => 0.9113444
"mph" => 1.1507794 , "kmh" => 1.852 , "kt" => 1 , "mps" => 0.5144444 , "fps" => 1.6878099
"mph" => 2.2369363 , "kmh" => 3.6 , "kt" => 1.9438445 , "mps" => 1 , "fps" => 3.2808399
"mph" => 0.6818182 , "kmh" => 1.09728 , "kt" => 0.5924838 , "mps" => 0.3048 , "fps" => 1
// Beaufort scale, measurements are in knots
} elseif ($to == "bft") {
$speed = round($speed * $factor[$from]["kt"], 0 );
for ($i = 0; $i < sizeof($beaufort); $i++ ) {
if ($speed <= $beaufort[$i]) {
return ($speed * $factor[$from][$to]);
* Convert pressure between in, hpa, mb, mm and atm
"in" => 1 , "hpa" => 33.863887 , "mb" => 33.863887 , "mm" => 25.4 , "atm" => 0.0334213
"in" => 0.02953 , "hpa" => 1 , "mb" => 1 , "mm" => 0.7500616 , "atm" => 0.0009869
"in" => 0.02953 , "hpa" => 1 , "mb" => 1 , "mm" => 0.7500616 , "atm" => 0.0009869
"in" => 0.0393701 , "hpa" => 1.3332239 , "mb" => 1.3332239 , "mm" => 1 , "atm" => 0.0013158
"in" => 29 ,921258 , "hpa" => 1013.2501 , "mb" => 1013.2501 , "mm" => 759.999952 , "atm" => 1
return ($pressure * $factor[$from][$to]);
* Convert distance between km, ft and sm
"m" => 1 , "km" => 1000 , "ft" => 3.280839895 , "sm" => 0.0006213699
"m" => 0.001 , "km" => 1 , "ft" => 3280.839895 , "sm" => 0.6213699
"m" => 0.3048 , "km" => 0.0003048 , "ft" => 1 , "sm" => 0.0001894
"m" => 0.0016093472 , "km" => 1.6093472 , "ft" => 5280.0106 , "sm" => 1
return ($distance * $factor[$from][$to]);
// {{{ calculateWindChill()
* Calculate windchill from temperature and windspeed (enhanced formula)
* Temperature has to be entered in deg F, speed in mph!
* @param float $temperature
* @link http://www.nws.noaa.gov/om/windchill/
return (35.74 + 0.6215 * $temperature - 35.75 * pow($speed, 0.16 ) + 0.4275 * $temperature * pow($speed, 0.16 ));
// {{{ calculateHumidity()
* Calculate humidity from temperature and dewpoint
* This is only an approximation, there is no exact formula, this
* one here is called Magnus-Formula
* Temperature and dewpoint have to be entered in deg C!
* @param float $temperature
* @link http://www.faqs.org/faqs/meteorology/temp-dewpoint/
// First calculate saturation steam pressure for both temperatures
$tempSSP = 6.1078 * pow(10 , ($a * $temperature) / ($b + $temperature));
$dewSSP = 6.1078 * pow(10 , ($a * $dewPoint) / ($b + $dewPoint));
return (100 * $dewSSP / $tempSSP);
// {{{ calculateDewPoint()
* Calculate dewpoint from temperature and humidity
* This is only an approximation, there is no exact formula, this
* one here is called Magnus-Formula
* Temperature has to be entered in deg C!
* @param float $temperature
* @link http://www.faqs.org/faqs/meteorology/temp-dewpoint/
// First calculate saturation steam pressure for temperature
$SSP = 6.1078 * pow(10 , ($a * $temperature) / ($b + $temperature));
$SP = $humidity / 100 * $SSP;
$v = log($SP / 6.1078 , 10 );
return ($b * $v / ($a - $v));
* Convert polar coordinates to cartesian coordinates
* @param float $longitude
return array ($x, $y, $z);
// {{{ calculateMoonPhase()
* Calculates the moon age and phase
* The algorithms for this functions were taken from the German Wikipedia
* entry on Julian Daycount for getting the accurate JD to the second and
* the overall moon calculation were done according to
* Stephen R. Schmitt's website, which is cited multiple times on the web
* for this kind of calculation.
* The date has to be entered as a timestamp!
* @return PEAR_Error|array
* @throws PEAR_Error::SERVICES_WEATHER_ERROR_MOONFUNCS_DATE_INVALID
* @link http://de.wikipedia.org/wiki/Julianisches_Datum
* @link http://mysite.verizon.net/res148h4j/javascript/script_moon_phase.html
// Date must be timestamp for now
$year = date("Y", $date);
$month = date("n", $date);
$hour = date("G", $date);
$age = 0.0; // Moon's age in days from New Moon
$distance = 0.0; // Moon's distance in Earth radii
$latitude = 0.0; // Moon's ecliptic latitude in degrees
$longitude = 0.0; // Moon's ecliptic longitude in degrees
$phase = ""; // Moon's phase
$zodiac = ""; // Moon's zodiac
$icon = ""; // The icon to represent the moon phase
// Calculate Julian Daycount to the second
$HH = $hour/24 + $min/1440 + $sec/86400;
// Check for Gregorian date and adjust JD appropriately
if (($year*10000 + $month*100 + $day) >= 15821015 ) {
$B = 2 - $A + floor($A/4 );
$JD = floor(365.25* ($YY+4716 )) + floor(30.6001* ($MM+1 )) + $DD + $HH + $B - 1524.5;
// Calculate moon's age in days
$IP = ($JD - 2451550.1 ) / 29.530588853;
if (($IP = $IP - floor($IP)) < 0 ) $IP++;
$age = $IP * 29.530588853;
$phase = "Waxing Crescent"; break;
$phase = "First Quarter"; break;
$phase = "Waxing Gibbous"; break;
$phase = "Waning Gibbous"; break;
$phase = "Last Quarter"; break;
$phase = "Waning Crescent"; break;
// Convert phase to radians
// Calculate moon's distance
$DP = ($JD - 2451562.2 ) / 27.55454988;
if (($DP = $DP - floor($DP)) < 0 ) $DP++;
$distance = 60.4 - 3.3 * cos($DP) - 0.6 * cos(2 * $IP - $DP) - 0.5 * cos(2 * $IP);
// Calculate moon's ecliptic latitude
$NP = ($JD - 2451565.2 ) / 27.212220817;
if (($NP = $NP - floor($NP)) < 0 ) $NP++;
$latitude = 5.1 * sin($NP);
// Calculate moon's ecliptic longitude
$RP = ($JD - 2451555.8 ) / 27.321582241;
if (($RP = $RP - floor($RP)) < 0 ) $RP++;
$longitude = 360 * $RP + 6.3 * sin($DP) + 1.3 * sin(2 * $IP - $DP) + 0.7 * sin(2 * $IP);
if ($longitude >= 360 ) $longitude -= 360;
case ($longitude < 33.18 ):
$zodiac = "Pisces"; break;
case ($longitude < 51.16 ):
$zodiac = "Aries"; break;
case ($longitude < 93.44 ):
$zodiac = "Taurus"; break;
case ($longitude < 119.48 ):
$zodiac = "Gemini"; break;
case ($longitude < 135.30 ):
$zodiac = "Cancer"; break;
case ($longitude < 173.34 ):
case ($longitude < 224.17 ):
$zodiac = "Virgo"; break;
case ($longitude < 242.57 ):
$zodiac = "Libra"; break;
case ($longitude < 271.26 ):
$zodiac = "Scorpio"; break;
case ($longitude < 302.49 ):
$zodiac = "Sagittarius"; break;
case ($longitude < 311.72 ):
$zodiac = "Capricorn"; break;
case ($longitude < 348.58 ):
$zodiac = "Aquarius"; break;
$moon["age"] = round($age, 2 );
$moon["distance"] = round($distance, 2 );
$moon["latitude"] = round($latitude, 2 );
$moon["longitude"] = round($longitude, 2 );
$moon["zodiac"] = $zodiac;
$moon["icon"] = (floor($age) - 1 ). "";
// {{{ calculateSunRiseSet()
* Calculates sunrise and sunset for a location
* The sun position algorithm taken from the 'US Naval Observatory's
* Almanac for Computers', implemented by Ken Bloom <kekabloom[at]ucdavis[dot]edu>
* for the zmanim project, converted to C by Moshe Doron <mosdoron[at]netvision[dot]net[dot]il>
* and finally taken from the PHP5 sources and converted to native PHP as a wrapper.
* The date has to be entered as a timestamp!
* @param float $longitude
* @param float $gmt_offset
* @return PEAR_Error|mixed
* @throws PEAR_Error::SERVICES_WEATHER_ERROR_SUNFUNCS_DATE_INVALID
* @throws PEAR_Error::SERVICES_WEATHER_ERROR_SUNFUNCS_RETFORM_INVALID
* @throws PEAR_Error::SERVICES_WEATHER_ERROR_UNKNOWN_ERROR
function calculateSunRiseSet($date, $retformat = null , $latitude = null , $longitude = null , $zenith = null , $gmt_offset = null , $sunrise = true )
// Date must be timestamp for now
// Check for proper return format
if ($retformat === null ) {
$retformat = SUNFUNCS_RET_STRING;
} elseif (!in_array($retformat, array (SUNFUNCS_RET_TIMESTAMP , SUNFUNCS_RET_STRING , SUNFUNCS_RET_DOUBLE )) ) {
// Set default values for coordinates
if ($latitude === null ) {
$latitude = SUNFUNCS_DEFAULT_LATITUDE;
$latitude = (float) $latitude;
if ($longitude === null ) {
$longitude = SUNFUNCS_DEFAULT_LONGITUDE;
$longitude = (float) $longitude;
$zenith = SUNFUNCS_SUNRISE_ZENITH;
$zenith = SUNFUNCS_SUNSET_ZENITH;
$zenith = (float) $zenith;
// Default value for GMT offset
if ($gmt_offset === null ) {
$gmt_offset = date("Z", $date) / 3600;
$gmt_offset = (float) $gmt_offset;
// If we have PHP5, then act as wrapper for the appropriate functions
return date_sunrise($date, $retformat, $latitude, $longitude, $zenith, $gmt_offset);
return date_sunset($date, $retformat, $latitude, $longitude, $zenith, $gmt_offset);
// Apparently we have PHP4, so calculate the neccessary steps in native PHP
// Step 1: First calculate the day of the year
$N = date("z", $date) + 1;
// Step 2: Convert the longitude to hour value and calculate an approximate time
$lngHour = $longitude / 15;
// Use 18 for sunset instead of 6
$t = $N + ((6 - $lngHour) / 24 );
$t = $N + ((18 - $lngHour) / 24 );
// Step 3: Calculate the sun's mean anomaly
$M = (0.9856 * $t) - 3.289;
// Step 4: Calculate the sun's true longitude
assert($Lx != $L); // askingtheguru: really needed?
assert($Lx != $L); // askingtheguru: really needed?
// Step 5a: Calculate the sun's right ascension
assert($RAx != $RA); // askingtheguru: really needed?
assert($RAx != $RA); // askingtheguru: really needed?
// Step 5b: Right ascension value needs to be in the same quadrant as L
$Lquadrant = floor($L / 90 ) * 90;
$RAquadrant = floor($RA / 90 ) * 90;
$RA = $RA + ($Lquadrant - $RAquadrant);
// Step 5c: Right ascension value needs to be converted into hours
// Step 6: Calculate the sun's declination
// Step 7a: Calculate the sun's local hour angle
// XXX: What's the use of this block.. ?
// if (sunrise && cosH > 1 || !sunrise && cosH < -1) {
// Step 7b: Finish calculating H and convert into hours
// Step 8: Calculate local mean time
$T = $H + $RA - (0.06571 * $t) - 6.622;
// Step 9: Convert to UTC
assert($UTx != $UT); // askingtheguru: really needed?
assert($UTx != $UT); // askingtheguru: really needed?
// Now bring the result into the chosen format and return
case SUNFUNCS_RET_TIMESTAMP:
return intval($date - $date % (24 * 3600 ) + 3600 * $UT);
case SUNFUNCS_RET_STRING:
case SUNFUNCS_RET_DOUBLE:
* Gets a number corresponding to a weather icon.
* These numbers just happen to correspond with the icons that you get with
* the weather.com SDK, but open versions of them have been created. Input
* must be in standard units. For the icons that include day/night, we use
* the present time and the provided lat/lon to determine if the sun is up.
* A complete set of icon descriptions can be found here:
* http://sranshaft.wincustomize.com/Articles.aspx?AID=60165&u=0
* There are a number of icon sets here:
* http://www.desktopsidebar.com/forums/index.php?showtopic=2441&st=0
* http://www.desktopsidebar.com/forums/index.php?showtopic=819
* @param string $condition The condition.
* @param array $clouds The clouds at various levels.
* @param float $wind Wind speed in mph.
* @param float $temperature Temperature in deg F.
* @param float $latitude Point latitude.
* @param float $longitude Point longitude.
* @param int $reportTime The time when the weather report was generated.
* @author Seth Price <seth@pricepages.org>
function getWeatherIcon($condition, $clouds = array (), $wind = 5 , $temperature = 70 , $latitude = -360 , $longitude = -360 , $reportTime = "")
// Search for matches that don't use the time of day
$hail = (bool) stristr($condition, "hail");
$dust = (bool) stristr($condition, "dust") || (bool) stristr($condition, "sand");
$smoke = (bool) stristr($condition, "smoke") || (bool) stristr($condition, "volcanic ash");
// Slightly more complex matches that might or might not use the time of day
$near = (bool) stristr($condition, "vicinity") || (bool) stristr($condition, "recent");
$light = (bool) stristr($condition, "light");
$heavy = (bool) stristr($condition, "heavy");
$ice = (bool) stristr($condition, "ice") || (bool) stristr($condition, "pellets");
// Have to add a space to prevent matching on "snow grains"
$rain = (bool) stristr($condition, " rain");
$snow = (bool) stristr($condition, "snow");
$fog = (bool) stristr($condition, "fog") || (bool) stristr($condition, "spray") || (bool) stristr($condition, "mist");
$haze = (bool) stristr($condition, "haze");
$ts = (bool) stristr($condition, "thunderstorm");
$freezing = (bool) stristr($condition, "freezing");
$wind = (bool) stristr($condition, "squall") || $wind > 25;
$nsw = (bool) stristr($condition, "no significant weather");
$hot = $temperature > 95;
$frigid = $temperature < 5;
// Get some of the dangerous conditions fist
if ($rain && $snow && ($ice || $freezing)) {
return 7; // Icy/Clouds Rain-Snow
if (($ts || $rain) && ($ice || $freezing)) {
if (($fog || $haze) && ($ice || $freezing)) {
return 8; // Icy/Haze Rain
return 5; // Cloudy/Snow-Rain Mix
// Get the maximum coverage of the clouds at any height. For most
// people, overcast at 1000ft is the same as overcast at 10000ft.
// 0 == clear, 1 == hazey, 2 == partly cloudy, 3 == mostly cloudy, 4 == overcast
foreach ($clouds as $layer) {
if ($coverage < 1 && stristr($layer["amount"], "few")) {
} elseif ($coverage < 2 && stristr($layer["amount"], "scattered")) {
} elseif ($coverage < 3 && (stristr($layer["amount"], "broken") || stristr($layer["amount"], "cumulus"))) {
} elseif ($coverage < 4 && stristr($layer["amount"], "overcast")) {
// Check if it is day or not. 0 is night, 2 is day, and 1 is unknown
// or twilight (~(+|-)1 hour of sunrise/sunset). Note that twilight isn't
// always accurate because of issues wrapping around the 24hr clock. Oh well...
if ($latitude < 90 && $latitude > -90 && $longitude < 180 && $longitude > -180 ) {
// Use provided time by report if available, otherwise use current GMT time
if ($reportTime <> "" && is_numeric($reportTime)) {
$timeOfDay = $reportTime;
// Calculate sunrise/sunset and current time in GMT
// Now that we have the sunrise/sunset times and the current time,
// we need to figure out if it is day, night, or twilight. Wrapping
// these times around the 24hr clock is a pain.
if ($sunrise < $sunset) {
if ($timeOfDay > ($sunrise + 3600 ) && $timeOfDay < ($sunset - 3600 )) {
} elseif ($timeOfDay > ($sunrise - 3600 ) && $timeOfDay < ($sunset + 3600 )) {
if ($timeOfDay < ($sunrise - 3600 ) && $timeOfDay > ($sunset + 3600 )) {
} elseif ($timeOfDay < ($sunrise + 3600 ) && $timeOfDay > ($sunset - 3600 )) {
// Default to twilight because it tends to have neutral icons.
return 37; // Lightning/Day
return 47; // Thunderstorm/Night
return 0; // Rain/Lightning
// Cloud conditions near the ground
return 26; // Mostly Cloudy
return 27; // Mostly Cloudy/Night
return 26; // Mostly Cloudy
return 28; // Mostly Cloudy/Day
return 29; // Partly Cloudy/Night
return 26; // Mostly Cloudy
return 30; // Partly Cloudy/Day
// Use night for twilight because the moon is generally
// out then, so it will match with most icon sets.
return 31; // Clear Night
Documentation generated on Mon, 11 Mar 2019 15:50:58 -0400 by phpDocumentor 1.4.4. PEAR Logo Copyright © PHP Group 2004.
|