commons-suncalc offers six astronomical calculations:

Quick Start

All of the calculations mentioned above are invoked in the same way:

Date date = // date of calculation
double lat, lng = // geolocation
SunTimes times = SunTimes.compute()
            .on(date)       // set a date
            .at(lat, lng)   // set a location
            .execute();     // get the results
System.out.println("Sunrise: " + times.getRise());
System.out.println("Sunset: " + times.getSet());

You invoke compute(), set your parameters, invoke execute(), and then get the result of the calculation as an object.

All parameters are passed in by a fluent builder-style interface. After retrieving the builder from compute(), you can chain the parameter setters, and finally call execute() to perform the computation.

SunPosition pos = SunPosition.compute().today().at(12.3, 45.6).execute();

It is also possible to collect the parameters first, and execute the computation in a separate step:

SunPosition.Parameters param = SunPosition.compute();;, 45.6);

SunPosition pos = param.execute();

The instance that is returned by execute() is immutable and only holds the calculation result of the current set of parameters. You can modify the parameters without changing the first result, then call execute() again for a second result.

param.on(2016, 12, 24); // modify the param from above

SunPosition posAtChristmas = param.execute();
// pos from above is unchanged

Time-based Parameters

All calculations need a date and time parameter. Some examples:

// August 21st, 2017, local midnight
SunPosition.compute().on(2017, 8, 21);

// Current time, system time zone
Date now = new Date();

// Current time, UTC
Date now = new Date();

// Now (the default)

// Today (midnight), Berlin time zone

The available time-based parameters are:

  • on(int year, int month, int date): Midnight of the given date. Note that month is counted from 1 (1 = January, 2 = February, …).
  • on(int year, int month, int date, int hour, int minute, int second): Given date and time.
  • on(Calendar cal): Date, time and timezone as given in the Calendar. The Calender is copied and can safely be modified after that.
  • on(Date date): Date and time as given in the Date.
  • plusDays(int days): Adds the given number of days to the current date. days can also be negative, of course.
  • now(): The current system date and time. This is the default.
  • midnight(): Past midnight of the current date. It just truncates the time.
  • today(): Identical to .now().midnight().
  • tomorrow(): Identical to today().plusDays(1).
  • timezone(TimeZone tz): Use the given timezone.
  • timezone(String id): Same as above, but accepts a String for your convenience.
  • localTime(): The system's timezone. This is the default.
  • utc(): UTC timezone. Identical to timezone("UTC").
  • sameTimeAs(TimeParameter<?> t): Copies the current date, time, and timezone from any other parameter object. Note that subsequent changes to the other object are not adopted.

If no time-based parameter is given, the current date and time, and the system's time zone is used.


The accuracy of the results is decreasing for dates that are far in the future, or far in the past.

Location-based Parameters

Except of MoonPhase and MoonIllumination, all calculations require a geolocation as parameter. Some examples:

// At 20.5°N, 18.3°E
SunPosition.compute().at(20.5, 18.3);

// The same, but more verbose

// Use arrays for coordinate constants
final double[] COLOGNE = new double[] { 50.938056, 6.956944 };

The available location-based parameters are:

  • at(double lat, double lng): Latitude and longitude to be used for computation.
  • at(double[] coords): Accepts an array of 2 values (latitude, longitude) or 3 values (latitude, longitude, height).
  • latitude(double lat): Verbose way to set the latitude only.
  • longitude(double lng): Verbose way to set the longitude only.
  • latitude(int d, int m, double s): Set the latitude in degrees, minutes, seconds and fraction of seconds.
  • longitude(int d, int m, double s): Set the longitude in degrees, minutes, seconds and fraction of seconds.
  • height(double h): Height above sea level, in meters. Sea level is used by default.
  • sameLocationAs(LocationParameter<?> l): Copies the current location and height from any other parameter object. Note that subsequent changes to the other object are not adoped.


The location parameters are not mandatory. However, if they are not given, 0° is assumed as latitude and longitude, which is not very useful in most cases. Do not forget to set the parameters!


height cannot be negative. If you pass in a negative height, it is silently changed to the accepted minimum of 0 meters. For this reason, it is safe to pass coordinates from satellite-based navigation systems without range checking.

Time Range

By default, SunTimes and MoonTimes only consider the next 24 hours of the given start time. If the sun or moon does not rise or set within that time span, the appropriate getters return null. You can check if the sun or moon is always above or below the horizon, by checking isAlwaysUp() and isAlwaysDown().

If you need both the rise and set time, you can set the fullCycle() parameter. The calculation then runs until both times are found, even if several days in the future. However, depending on the date and geolocation, this calculation could take considerably more time and computing power.


fullCycle() only affects the result of getRise() and getSet(). The methods isAlwaysUp(), isAlwaysDown(), getNoon() and getNadir() will always only consider the next 24 hours.

Result Rounding

SunTimes, MoonTimes and MoonPhase return Date objects as result. By default, the result is rounded to the nearest full minute. This is so suncalc does not pretend a higher precision than it can actually deliver.

You can change rounding by adding a truncateTo() parameter. It accepts one of these constants:

Constant Description
SECONDS Include the calculated seconds. Note that due to the simplified formulas, suncalc is never accurate to the second.
MINUTES Round to the nearest full minute. This is the default.
HOURS Round to the nearest full hour.
DAYS Round down to the date. Basically it truncates the time component of the result.


Even though the method is called truncateTo(), the time component is rounded to the nearest full minute or hour. This gives more reasonable results.


Twilight Zones

By default, SunTimes calculates the time of the visual sunrise and sunset. This means that getRise() returns the instant when the sun just starts to rise above the horizon, and getSet() returns the instant when the sun just disappeared from the horizon. Atmospheric refraction is taken into account.

There are other interesting twilight angles available. You can set them via the twilight() parameter, by using one of the SunTimes.Twilight constants:

Constant Description Angle of the Sun Topocentric
VISUAL The moment when the visual upper edge of the sun crosses the horizon. This is the default. yes
VISUAL_LOWER The moment when the visual lower edge of the sun crosses the horizon. yes
ASTRONOMICAL Astronomical twilight -18° no
NAUTICAL Nautical twilight -12° no
CIVIL Civil twilight -6° no
HORIZON The moment when the center of the sun crosses the horizon. no
GOLDEN_HOUR Transition from daylight to Golden Hour no
BLUE_HOUR Transition from Golden Hour to Blue Hour -4° no
NIGHT_HOUR Transition from Blue Hour to night -8° no

The illustration shows the transitions of each twilight constant. If you want to get the duration of a twilight, you need to calculate the times of both transitions of the twilight. For example, to get the beginning and ending of the civil twilight, you need to calculate both the VISUAL and the CIVIL twilight transition times.

Alternatively you can also pass any other angle (in degrees) to twilight().


Only VISUAL and VISUAL_LOWER are topocentric. They refer to the visual edge of the sun, take account of the height parameter, and compensate atmospheric refraction.

All other twilights are geocentric and heliocentric. The height parameter is then ignored, and atmospheric refraction is not compensated.




By default, MoonPhase calculates the date of the next new moon. If you want to compute the date of another phase, you can set it via the phase() parameter, by using one of the MoonPhase.Phase constants:

Constant Description Angle
NEW_MOON Moon is not illuminated (new moon). This is the default.
WAXING_CRESCENT Waxing crescent moon. 45°
FIRST_QUARTER Half of the waxing moon is illuminated. 90°
WAXING_GIBBOUS Waxing gibbous moon. 135°
FULL_MOON Moon is fully illuminated. 180°
WANING_GIBBOUS Waning gibbous moon. 225°
LAST_QUARTER Half of the waning moon is illuminated. 270°
WANING_CRESCENT Waning crescent moon. 315°

Alternatively you can also pass any other angle (in degrees) to phase().