diff --git a/nighttime.php b/nighttime.php new file mode 100644 index 0000000..129d500 --- /dev/null +++ b/nighttime.php @@ -0,0 +1,307 @@ +setTimezone(new DateTimeZone("UTC")); //Now update the timezone to UTC + $utc_timestamp = $given->format('Ymd\THis\Z') . "\n"; //Output the UTC timestamp in ISO standard format + return $utc_timestamp; +} + +//Escape strings +function escape_string($string) { + return preg_replace('/([\,;])/','\\\$1', $string); +} + +$year = ( isset($_GET['year']) )? intval($_GET['year']) : date('Y'); +$lat = ( isset($_GET['lat']) )? floatval($_GET['lat']) : 43.0469; +$lng = ( isset($_GET['lng']) )? floatval($_GET['lng']) : -76.1444; + +$timezone = 'America/New_York'; //Default to American Eastern timezone +if ( isset($_GET['timezone']) ){ //If a timezone name is provided, use it + $timezone = $_GET['timezone']; +} elseif ( isset($_GET['gmt']) ){ //If a GMT offset is provided, try to find an equivalent timezone + $timezone_list = DateTimeZone::listIdentifiers(); //Get the list of all timezones + foreach ( $all_timezones as $timezone_to_check ){ //Loop through all of the timezones + $tz = new DateTimeZone($timezone_to_check); + $offset = $tz->getOffset(new DateTime()); //Get the offset in seconds from UTC for the timezone + $offset_hours = $offset/3600; //Convert the offset to hours + if ( $offset_hours == intval($_GET['gmt']) ){ //If the offset hours matches the GMT offset, use that timezone + $timezone = $timezone_to_check; + break; //Exit the loop + } + } +} + +date_default_timezone_set($timezone); //Now use the timezone that was determined above + +function is_syracuse($lat=false, $lng=false){ + if ( isset($_GET['syracuse']) ){ + return true; + } + + if ( $lat == 43.0469 && $lng == -76.1444 ){ //Could make this a little more flexible with >= <= + return true; + } + + return false; +} + +//Shortest Day Length +$shortest_date = $year . '-12-21'; +$shortest_sun_info = date_sun_info(strtotime($shortest_date), $lat, $lng); +$shortest_sunrise = $shortest_sun_info['sunrise']; +$shortest_sunset = $shortest_sun_info['sunset']; +$shortest_length = $shortest_sunset-$shortest_sunrise; + +//Longest Day Length +$longest_date = $year . '-06-21'; +$longest_sun_info = date_sun_info(strtotime($longest_date), $lat, $lng); +$longest_sunrise = $longest_sun_info['sunrise']; +$longest_sunset = $longest_sun_info['sunset']; +$longest_length = $longest_sunset-$longest_sunrise; + +//Current weather forecast +$weather_forecast = array(); +$weather_forecast_summary = ''; +if ( is_syracuse($lat, $lng) ){ + //Weather Forecast + $weather_json = file_get_contents('/home/gearside/public_html/weather.gearside.com/v2/data/weather-owm.json'); + if ( !empty($weather_json) ){ + $weather_forecast_data = json_decode($weather_json); + if ( is_string($weather_forecast_data) ){ + $weather_forecast_data = json_decode($weather_forecast_data); //Decode it again if it is not yet an array. Dunno why I need to do this but it is necessary. + } + + foreach ( $weather_forecast_data->daily as $forecast_day ){ + $weather_forecast['day' . date('Ymd', $forecast_day->dt)] = array( + 'date' => $forecast_day->dt, //UTC time + 'high' => round($forecast_day->temp->max) . '°F', + 'low' => round($forecast_day->temp->min) . '°F', + 'feels_like' => round($forecast_day->feels_like->day) . '°F', //Not using this because there is not a "max", and "day" is not equivalent to be accurate + 'humidity' => round($forecast_day->humidity) . '%', //Percent + 'wind' => ( $forecast_day->wind_speed > 18 )? round($forecast_day->wind_speed) . 'mph' : '', //Already in MPH from source. Only show if it is high + 'pop' => round(($forecast_day->pop)*100), //Percent + //'pop_type' => '', //This is not explicitly provided. Would need to do the math on ->rain vs. ->snow + 'snow_accumulation' => ( !empty($forecast_day->snow) && $forecast_day->snow*0.0393701 > 0.2 )? round($forecast_day->snow*0.0393701, 1) . '"' : '', //Convert millimeters to inches. Only show if more than 1/4" + 'forecast' => ucwords($forecast_day->weather[0]->main), + 'description' => ucwords($forecast_day->weather[0]->description), + 'icon' => get_weather_emoji($forecast_day->weather[0]->main, $forecast_day->weather[0]->description, $forecast_day->temp->max) //Combine the main, summary, and high temperature to figure out the icons + ); + } + } +} + +//Determine emoji icon based on forecast summary +//https://emojipedia.org/search/?q=weather +function get_weather_emoji($main='', $description='', $high=false){ + $forecast = strtolower($main) .' ' . strtolower($description); + + $emoji_icon = ''; + if ( strpos($forecast, 'mostly') !== false || strpos($forecast, 'partly') !== false ){ + $emoji_icon = '⛅'; + } elseif ( strpos($forecast, 'cloud') !== false || strpos($forecast, 'fog') !== false ){ + $emoji_icon = '☁️'; + } elseif ( strpos($forecast, 'sunny') !== false ){ + $emoji_icon = '☀️'; + } elseif ( strpos($forecast, 'snow') !== false ){ + $emoji_icon = '❄️'; + } elseif ( strpos($forecast, 'rain') !== false || strpos($forecast, 'shower') !== false ){ + $emoji_icon = '🌧️'; + } elseif ( strpos($forecast, 'storm') !== false ){ + $emoji_icon = '⛈️'; + } elseif ( strpos($forecast, 'wind') !== false ){ + $emoji_icon = '🌬️'; + } + + if ( !empty($high) ){ + if ( $high >= 90 ){ + $emoji_icon .= '🥵'; + } elseif ( $high >= 75 ){ + $emoji_icon .= '🔴'; + } elseif ( $high >= 60 ){ + $emoji_icon .= '🟠'; + } elseif ( $high >= 45 ){ + $emoji_icon .= '🟣'; + } elseif ( $high >= 32 ){ + $emoji_icon .= '🔵'; + } elseif ( $high < 32 ){ + $emoji_icon .= '🥶'; + } + } + + return $emoji_icon; +} + +?> +BEGIN:VCALENDAR +VERSION:2.0 +PRODID:-//hacksw/handcal//NONSGML v1.0//EN +CALSCALE:GREGORIAN +METHOD:PUBLISH +X-WR-CALNAME:Gearside - Nighttime + 0 ){ //Prevent division by 0 + $length_percentile = round((($length-$shortest_length)*100)/($longest_length-$shortest_length), 1); + } + + //Add the weather info to the summary if it matches the date correctly + $weather_forecast_summary = ''; //Empty this variable each time + $weather_icon = ''; //Default emoji icon. + if ( !empty($weather_forecast) ){ //If we have weather data + $this_weather_day = 'day' . date('Ymd', strtotime($date . '+1 year ')); + if ( !empty($weather_forecast[$this_weather_day]) ){ //If we have weather data for this specific day + $weather_icon = $weather_forecast[$this_weather_day]['icon']; + $weather_forecast_summary = ' ' . $weather_forecast[$this_weather_day]['forecast'] . ' (High: ' . $weather_forecast[$this_weather_day]['high'] . ', Low ' . $weather_forecast[$this_weather_day]['low'] . ').'; + + if ( !empty($weather_forecast[$this_weather_day]['pop']) && $weather_forecast[$this_weather_day]['pop'] != 0 ){ + $precip_icon = ( $weather_forecast[$this_weather_day]['pop'] >= 90 )? '💦' : ''; + $weather_forecast_summary .= ' ' . $precip_icon . ' ' . $weather_forecast[$this_weather_day]['pop'] . '% chance of precipitation.'; + } + + if ( !empty($weather_forecast[$this_weather_day]['wind']) ){ + $weather_forecast_summary .= ' ⚠️ Windy (' . $weather_forecast[$this_weather_day]['wind'] . ').'; + } + + if ( !empty($weather_forecast[$this_weather_day]['snow_accumulation']) ){ + $weather_forecast_summary .= ' ⚠️ ' . $weather_forecast[$this_weather_day]['snow_accumulation'] . ' Snow.'; + // Add extra warning for snow if accumulation is significant + } + } + } + + //Only show the solar noon time if weather is unavailable (to avoid clutter). + $solar_noon_summary = ''; + if ( empty($weather_forecast_summary) ){ + $solar_noon_summary = 'Solar noon: ' . date('g:ia', intval($solar_noon)) . '.'; + } + + if ( is_debug() ){ + echo "\r\n------------------\r\n"; + echo ( $date == date('Y-m-d', strtotime('Today -1 Year')) ) ? "(Today!) " : ""; + echo "Debug Info\r\n"; + echo "Last Modified: " . date('l, F j, Y', filemtime(__FILE__)) . "\r\n"; + echo "Date (-1 Year): " . $date . "\r\n"; + echo "Timezone Used: " . $timezone . "\r\n"; + echo "Sunrise: " . $sunrise . "\r\n"; + echo "Sunset: " . $sunset . "\r\n"; + echo "Nighttime: " . date('l, F j Y, g:ia', $sunrise) . ' to ' . date('l, F j Y, g:ia', $sunset) . "\r\n"; + echo "Length: " . $hours . "h " . $minutes . "m (" . round($percent, 1) . "%) of nighttime\r\n"; + echo "Solar Noon: " . date('g:ia', intval($solar_noon)) . "\r\n"; + if ( is_syracuse($lat, $lng) ) { + echo "Syracuse Detected! This request is eligible for a weather forecast!\r\n"; + } + echo "Civil: " . date('g:ia', $sunrise_civil) . ' to ' . date('g:ia', $sunset_civil) . " (There is enough natural sunlight that artificial light may not be required to carry out human activities.)\r\n"; + echo "Nautical: " . date('g:ia', $sunrise_nautical) . ' to ' . date('g:ia', $sunset_nautical) . " (The point at which the horizon stops being visible at sea)\r\n"; + echo "Astronomical: " . date('g:ia', $sunrise_astronomical) . ' to ' . date('g:ia', $sunset_astronomical) . " (The point when Sun stops being a source of any illumination)\r\n"; + echo "\r\nShortest day this year: " . $shortest_length . "\r\n"; + echo "Longest day this year: " . $longest_length . "\r\n"; + echo "This day length: " . $length . "\r\n"; + echo $length_percentile . " Percentile\r\n"; + echo ( !empty($weather_forecast_summary) )? $weather_forecast_summary : '(No forecast for this date)'; + + echo "\r\n"; + } +?> +BEGIN:VEVENT +CREATED: +DTSTART: +DTEND: +DTSTAMP: +LAST-MODIFIED: +UID: +DESCRIPTION: +URL;VALUE=URI: +SUMMARY: +RRULE:FREQ=YEARLY;COUNT=3 +END:VEVENT + +END:VCALENDAR + + +X-WR-CALDESC:Visualize nighttime