Calculator

Sunrise & Sunset Calculator

Enter a date, a latitude and longitude, and (optionally) a UTC offset to get sunrise and sunset times for that exact location.

Fill in date, latitude, and longitude

Where to get latitude and longitude

Most map apps show coordinates when you long-press or right-click a location. West longitudes and southern latitudes are negative in this tool — for example, New York City is roughly 40.71 latitude, -74.01 longitude.

Why a UTC offset, not a timezone name

Sunrise and sunset are astronomical events tied to longitude, not to timezone boundaries or daylight saving rules — this calculator computes them in UTC first, since that's unambiguous, and then applies whatever offset you provide to show local clock time. If you skip the offset, you'll still get the correct UTC times; just add your zone's current offset (accounting for daylight saving if it applies) to convert.

This uses a standard solar-position approximation accurate to within about a minute for most dates and locations — for that last measure of precision, dedicated astronomical software or an official almanac is the reference to use.

Related

Related tools

function julianDate(y,m,d){ if(m <= 2){ y -= 1; m += 12; } const A = Math.floor(y/100); const B = 2 - A + Math.floor(A/4); return Math.floor(365.25*(y+4716)) + Math.floor(30.6001*(m+1)) + d + B - 1524.5; } function computeSunTimes(year, month, day, lat, lon){ const J_date = julianDate(year, month, day) + 0.5; // approx noon JD for the date const n = J_date - 2451545.0 + 0.0008; const Jstar = n - (lon/360); const Mdeg = (357.5291 + 0.98560028 * Jstar) % 360; const M = Mdeg * Math.PI/180; const C = 1.9148*Math.sin(M) + 0.0200*Math.sin(2*M) + 0.0003*Math.sin(3*M); let lambdaDeg = (Mdeg + C + 180 + 102.9372) % 360; const lambda = lambdaDeg * Math.PI/180; const Jtransit = 2451545.0 + Jstar + 0.0053*Math.sin(M) - 0.0069*Math.sin(2*lambda); const sinDelta = Math.sin(lambda) * Math.sin(23.4397*Math.PI/180); const delta = Math.asin(sinDelta); const latRad = lat * Math.PI/180; const cosOmega0 = (Math.sin(-0.83*Math.PI/180) - Math.sin(latRad)*Math.sin(delta)) / (Math.cos(latRad)*Math.cos(delta)); if(cosOmega0 > 1) return {polarNight:true}; if(cosOmega0 < -1) return {midnightSun:true}; const omega0 = Math.acos(cosOmega0) * 180/Math.PI; const Jrise = Jtransit - omega0/360; const Jset = Jtransit + omega0/360; function jdToDate(jd){ const unixMs = (jd - 2440587.5) * 86400000; return new Date(unixMs); } return { sunrise: jdToDate(Jrise), sunset: jdToDate(Jset), transit: jdToDate(Jtransit), daylightHours: (omega0/180)*24 }; } const ssDate = document.getElementById('ssDate'); const ssLat = document.getElementById('ssLat'); const ssLon = document.getElementById('ssLon'); const ssOffset = document.getElementById('ssOffset'); const ssResult = document.getElementById('ssResult'); function fmtUTC(d){ return d.toISOString().substr(11,5) + ' UTC'; } function fmtLocal(d, offsetHours){ const local = new Date(d.getTime() + offsetHours*3600000); const hh = String(local.getUTCHours()).padStart(2,'0'); const mm = String(local.getUTCMinutes()).padStart(2,'0'); return `${hh}:${mm} local`; } function render(){ if(!ssDate.value || ssLat.value === '' || ssLon.value === ''){ ssResult.innerHTML = 'Fill in date, latitude, and longitude'; return; } const [y,m,d] = ssDate.value.split('-').map(Number); const lat = parseFloat(ssLat.value), lon = parseFloat(ssLon.value); if(Math.abs(lat) > 90 || Math.abs(lon) > 180){ ssResult.innerHTML = 'Latitude must be -90 to 90, longitude -180 to 180'; return; } const r = computeSunTimes(y,m,d,lat,lon); if(r.polarNight){ ssResult.innerHTML = '
Sun does not rise on this date at this location (polar night).
'; return; } if(r.midnightSun){ ssResult.innerHTML = '
Sun does not set on this date at this location (midnight sun).
'; return; } const offset = ssOffset.value !== '' ? parseFloat(ssOffset.value) : null; let rows = `
Sunrise (UTC)${fmtUTC(r.sunrise)}
` + `
Sunset (UTC)${fmtUTC(r.sunset)}
`; if(offset !== null && !isNaN(offset)){ rows += `
Sunrise (local)${fmtLocal(r.sunrise, offset)}
` + `
Sunset (local)${fmtLocal(r.sunset, offset)}
`; } rows += `
Daylight${r.daylightHours.toFixed(2)} hours
`; ssResult.innerHTML = rows; } [ssDate, ssLat, ssLon, ssOffset].forEach(el => el.addEventListener('input', render));