The accurate prediction of solar position over time is not a trivial problem. There are literally hundreds of algorithms out there, all making slightly different assumptions in order to either simplify the maths in particular parts of the process or to derive coefficients for the many linear equations involved. This means that they all give slightly different answers, all of which vary to some degree from actual recorded solar positions in different parts of the world.

Obviously everyone wants to use the simplest and most accurate method, but it turns out in this case that these two criteria are pretty well mutually exclusive. Thus, the one you chose will depend on some combination of how accurate you really need to be, the resources available to do each of the calculations and how much time you want to spend implementing it. For a range of different algorithms and how relatively accurate they are, see the Calculating Solar Position article.

Why Are There Differences?

Obviously different methodologies will give slightly different answers due to the internal mathematics involved. However, even using exactly the same method, two different people will very likely still get two slightly different answers for the same situation.

The main reasons for this are variations or inconsistencies in input data. For example, one may use Google Earth to get the latitude/longitude for the exact centre of the site down to 12 decimal places. The other may use an online database such as infoplease or realestate3d and search just for the city or town, achieving an accuracy of only 2-3 decimal places.

Another problem is the day-of-year index that all algorithms use. Most likely this will be hidden behind an interface that lets you select a month and day, but the results of that selection will be converted to a single index for input. Unfortunately many algorithms are not explicit as to whether they require the day-of-year index in the range 0-364 or 1-365 and whether it should include an additional day in a leap year. Also, some interfaces may ask you for the actual year of calculation whilst others will just assume the current year or some other.

Thus, the underlying algorithm could be exactly the same, but different interfaces may feed it indexes that are one or two days out depending on which format they assume and whether they include the correct number of extra days in each leap year, etc.

Another potential problem when working with recorded data is determining the exact time each angle is calculated for. As an example, weather data intended for incident solar radiation calculations typically uses recordings averaged over each hour, implicitly assuming that a corresponding ‘average’ or representative solar position is taken.

This should be mid-way between the start and end of each averaging period. Thus, for each full hour of daylight, this means on the half-hour (9:30, 10:30, 11:30, etc). For the period just after sunrise, this means half-way between the actual sunrise time and the next integer hour. Similarly for the period just before sunset, the representative time is halfway between the last integer hour of daylight and the actual sunset time.

Figure 1 - The effective Sun position for average hourly solar radiation measurements.

Detailed information such as this is not always explicit for all recorded solar position datasets, so you often need to do some experiments to determine what you should use.

The positional differences resulting from all this are typically quite small and usually insignificant considering the applications to which they are put. However, the point being that it is actually very difficult to get two sets of solar position data to match anywhere near exactly.

Comparing Angles

Comparing the actual angles in each dataset sounds pretty trivial, but it isn’t. There are many instances in which two datasets that are so close as to be essentially the same will still throw up spuriously large differences in individual values. The reasons for these are pretty obvious once you think about them, but still need to be carefully considered and are deserving of some explanation.

Circular Wrapping

The Sun revolves around the Earth in very close to a circular motion so solar angles are periodic. Thus, the first issue to deal with is ensuring that the same wrapping range is used in each dataset. Some use -180 to +180 whilst others may use 0 to 360.

This is easily accommodated in the comparison itself using temporary variables and if/then tests, but you need to do this carefully or you will end up comparing -150° with +210° and getting some pretty large differences.

The next problem occurs around solar noon where the azimuth angle switches from -179.9 to +179.9 in the Northern hemisphere, or from 359.9 to 0.1 in the Southern hemisphere. Again, without some if/then tests, a direct comparison will show them as being 359.8° out instead of just 0.2°.

Angles Near the Zenith

The other source of potentially large differences is azimuth angle when the Sun is very near the zenith of the sky. As shown in Figure 2 below, as the Sun passes near the zenith, its azimuth angle changes quite significantly even in the space of just a few minutes. Thus, even the slightest variation in two solar position algorithms can show up in such circumstances as huge azimuth differences when, in context, the real variation is nothing.

Figure 2 - When the Sun is near the zenith, azimuth angles change significantly within only 5 minute steps.

As an additional illustration, Figure 3 shows two sun positions that are extremely close but on either side of the zenith, thus yielding azimuth angles nearly 180#deg; apart.

Figure 3 - When the Sun is near the zenith of the sky, a small positional difference can often result in a large azimuth angle difference.

Thus, to determine differences consistently, it is important to consider both the azimuth and altitude angles together when doing the comparison rather than comparing each separately.

For a consistent azimuth comparison across all altitudes, you can simply multiply the azimuth angle difference by the cosine of the average altitude angle. Thus, when both Sun positions are close to the zenith, the azimuth difference is multiplied by a number close to zero (cos(90°)=0) whereas near the horizon it is multiplied by a number close to one (cos(0°)=1).


  • Dif is the moderated azimuth difference.
  • Alt is the solar azimuth measured from the horizon,
  • Azi1 is the solar azimuth of dataset 1, and
  • Azi2 is the solar azimuth of dataset 2.


Angles at Sunrise/Sunset

Of course, multiplying by the cosine of altitude highlights any azimuth differences at the horizon. This is not really a problem for locations between the equator and mid-latitudes (up to about 50°). However, closer to the Poles where the Sun is very low in the sky throughout the day, a difference in sunrise/sunset times of only a couple of minutes or so can result in differences of 1-2° in azimuth angle. This is a trivial difference in context, but well above any standard test tolerance.

The options here are simply to ignore values below a certain altitude or try to correct for conditions of low altitude and high latitude. Unfortunately there is no obvious or ‘correct’ solution for the latter option. You could try some combination of weighted cosines of latitude and altitude, but then risk missing some important differences at mid-latitudes where the correction factors are actually masking significant variations. You could experiment with different weightings, but it all becomes a bit subjective and pretty arbitrary.

My approach was to use a stepped cut-off altitude angle based on latitude, but this is just as arbitrary and very specific to my particular application.


Directly comparing solar position data seems on the surface to be pretty simple, but turns out to be laden with context-specific quirks that you need to be aware of and able to deal with. This article has hopefully explained a little about what these quirks are and why they are there. Comments, suggestions and even anecdotes from your own experiences are more than welcome.

Click here to comment on this page.