Skip to content

Instantly share code, notes, and snippets.

@yetimdasturchi
Created August 19, 2026 15:22
Show Gist options
  • Select an option

  • Save yetimdasturchi/8973a67dd7df53870b748b125e01932b to your computer and use it in GitHub Desktop.

Select an option

Save yetimdasturchi/8973a67dd7df53870b748b125e01932b to your computer and use it in GitHub Desktop.
Calculate sunrise and sunset times using geographic coordinates and date.
<?php
/**
* Check whether the given year is a leap year.
*/
function isLeapYear(int $year): bool
{
return $year % 400 === 0
|| ($year % 4 === 0 && $year % 100 !== 0);
}
/**
* Convert a date to the day number within the year.
*
* Examples:
* January 1 = 1
* January 31 = 31
* February 1 = 32
*/
function dayOfYear(int $year, int $month, int $day): int
{
$daysInMonths = [
31, 28, 31, 30, 31, 30,
31, 31, 30, 31, 30, 31,
];
if (isLeapYear($year)) {
$daysInMonths[1] = 29;
}
$result = $day;
for ($i = 0; $i < $month - 1; $i++) {
$result += $daysInMonths[$i];
}
return $result;
}
/**
* Convert decimal hours to HH:MM:SS.
*
* Example:
* 5.5 -> 05:30:00
*/
function hoursToTime(float $hours): string
{
$hours = fmod($hours, 24);
if ($hours < 0) {
$hours += 24;
}
$totalSeconds = (int) round($hours * 3600) % 86400;
$hour = intdiv($totalSeconds, 3600);
$minute = intdiv($totalSeconds % 3600, 60);
$second = $totalSeconds % 60;
return sprintf('%02d:%02d:%02d', $hour, $minute, $second);
}
/**
* Calculate sunrise and sunset times.
*/
function calculateSun(
int $year,
int $month,
int $day,
float $latitude,
float $longitude,
float $timezone,
): array {
// 1. Day of the year
$dayOfYear = dayOfYear($year, $month, $day);
// 2. Fractional year angle, in radians
$gamma = (2 * M_PI / 365) * ($dayOfYear - 1);
// 3. Difference between apparent solar time and clock time, in minutes
$equationOfTime = 229.18 * (
0.000075
+ 0.001868 * cos($gamma)
- 0.032077 * sin($gamma)
- 0.014615 * cos(2 * $gamma)
- 0.040849 * sin(2 * $gamma)
);
// 4. Solar declination, in radians
$declination =
0.006918
- 0.399912 * cos($gamma)
+ 0.070257 * sin($gamma)
- 0.006758 * cos(2 * $gamma)
+ 0.000907 * sin(2 * $gamma)
- 0.002697 * cos(3 * $gamma)
+ 0.001480 * sin(3 * $gamma);
// 5. Convert latitude to radians
$latitudeRad = deg2rad($latitude);
/**
* 6. Sunrise / sunset zenith
*
* 90° = geometric horizon
* 0.266° = apparent solar radius
* 0.567° = atmospheric refraction
*
* Total: 90.833°
*/
$zenith = deg2rad(90.833);
// 7. Calculate the hour angle at the horizon
$cosHourAngle =
cos($zenith) / (cos($latitudeRad) * cos($declination))
- tan($latitudeRad) * tan($declination);
// Polar night: the Sun does not rise
if ($cosHourAngle > 1) {
return [
'sunrise' => null,
'sunset' => null,
'status' => 'Sun does not rise',
];
}
// Midnight Sun: the Sun does not set
if ($cosHourAngle < -1) {
return [
'sunrise' => null,
'sunset' => null,
'status' => 'Sun does not set',
];
}
// 8. Convert hour angle from radians to degrees
$hourAngle = rad2deg(acos($cosHourAngle));
// 9. Solar peak time, in minutes from midnight
$solarPeakMinutes =
720
- 4 * $longitude
- $equationOfTime
+ $timezone * 60;
/**
* Earth rotates 360° in 24 hours:
*
* 360 / 24 = 15° per hour
* 1° = 4 minutes
*/
$offsetMinutes = $hourAngle * 4;
// 10. Sunrise and sunset times
$sunriseMinutes = $solarPeakMinutes - $offsetMinutes;
$sunsetMinutes = $solarPeakMinutes + $offsetMinutes;
return [
'sunrise' => hoursToTime($sunriseMinutes / 60),
'sunset' => hoursToTime($sunsetMinutes / 60),
// Debug values
'day_of_year' => $dayOfYear,
'equation_of_time' => $equationOfTime,
'declination_deg' => rad2deg($declination),
'solar_peak' => hoursToTime($solarPeakMinutes / 60),
'status' => 'OK',
];
}
// ------------------------------------------------------
// Example: Tashkent, August 19, 2026
// ------------------------------------------------------
$result = calculateSun(
year: 2026,
month: 8,
day: 19,
latitude: 41.2995,
longitude: 69.2401,
timezone: 5,
);
echo "Sunrise: {$result['sunrise']}" . PHP_EOL;
echo "Sunset: {$result['sunset']}" . PHP_EOL;
echo PHP_EOL;
echo "Solar peak: {$result['solar_peak']}" . PHP_EOL;
echo "Declination: {$result['declination_deg']}°" . PHP_EOL;
echo "Time difference: {$result['equation_of_time']} min" . PHP_EOL;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment