Class SolarTime

java.lang.Object
net.time4j.calendar.astro.SolarTime
All Implemented Interfaces:
Serializable, GeoLocation

public final class SolarTime extends Object implements GeoLocation, Serializable
Contains various routines to determine solar time.

Notice: Most chronological functions use the astronomical equation of time. Hence they are only applicable for years between -2000 and +3000 otherwise an IllegalArgumentException will be thrown.

Example for sunrise and sunset on the top of Africas highest mountain Kilimanjaro:

     PlainDate date = PlainDate.of(2017, 12, 22);
     TZID tzid = () -> "Africa/Dar_es_Salaam"; // Tanzania: UTC+03:00

     // high altitude implies earlier sunrise and later sunset
     SolarTime kibo5895 =
       SolarTime.ofLocation()
          .southernLatitude(3, 4, 0)
          .easternLongitude(37, 21, 33)
          .atAltitude(5895)
          .usingCalculator(StdSolarCalculator.TIME4J) // this calculator takes into account the altitude
          .build();

     assertThat(
       date.get(kibo5895.sunrise()).get().toZonalTimestamp(tzid).toTime(),
       is(PlainTime.of(6, 10, 35)));
     assertThat(
       date.get(kibo5895.sunset()).get().toZonalTimestamp(tzid).toTime(),
       is(PlainTime.of(18, 47, 47)));
 

About limitations of accuracy:

Time4J only models a spherical geometry but not local topology with mountains which can break the horizon line. Furthermore, special weather conditions which can have a bigger impact on atmospheric refraction are not calculatable. The concrete calculator in use is also a limiting factor for accuracy. Users should therefore not expect more than minute precision. This can be even worse for polar regions because the sun crosses then the horizon under a very shallow angle.

Interpretation of calendar dates:

This class interpretes every calendar date input as on LMT (Local Mean Time) unless the builder-method SolarTime.Builder.inTimezone(TZID) is called. Users only need to pay attention to this subtile difference if a few areas along the international date border like Kiribati or Samoa are involved. Following example demonstrates the difference:

LMT-date

     TZID tzid = Timezone.of("Pacific/Apia").getID();
     SolarTime apia = SolarTime.ofLocation().southernLatitude(13, 50, 0).westernLongitude(171, 45, 0).build();
     assertThat(
       PlainDate.of(2011, 12, 31).get(apia.sunrise()).get().toZonalTimestamp(tzid),
       is(PlainTimestamp.of(2012, 1, 1, 7, 2, 13))); // civil date is one day later than LMT-date
 

Zoned date

     TZID tzid = Timezone.of("Pacific/Apia").getID();
     SolarTime apia =
       SolarTime.ofLocation()
         .southernLatitude(13, 50, 0)
         .westernLongitude(171, 45, 0)
         .inTimezone(tzid)
         .build();
     assertThat(
       PlainDate.of(2012, 1, 1).get(apia.sunrise()).get().toZonalTimestamp(tzid),
       is(PlainTimestamp.of(2012, 1, 1, 7, 2, 13))); // civil date is same as input
 
Since:
3.33/4.28
Author:
Meno Hochschild
See Also:
Serialized Form
  • Method Details

    • ofLocation

      public static SolarTime.Builder ofLocation()

      Obtains a builder for creating a new instance of local solar time.

      This method is the recommended approach if any given geographical position is described in degrees including arc minutes and arc seconds in order to avoid manual conversions to decimal degrees.

      Returns:
      builder for creating a new instance of local solar time
      Since:
      3.35/4.30
    • ofLocation

      public static SolarTime ofLocation(double latitude, double longitude)

      Obtains the solar time for given geographical location at sea level.

      The default calculator is usually StdSolarCalculator.NOAA unless another calculator was set up via the service loader mechnism.

      This method handles the geographical location in decimal degrees only. If these data are given in degrees, arc minutes and arc seconds then users should apply the builder approach instead.

      Parameters:
      latitude - geographical latitude in decimal degrees (-90.0 <= x <= +90.0)
      longitude - geographical longitude in decimal degrees (-180.0 <= x < 180.0)
      Returns:
      instance of local solar time
      Throws:
      IllegalArgumentException - if the coordinates are out of range
      Since:
      3.34/4.29
      See Also:
      ofLocation(double, double, int, String)
    • ofLocation

      public static SolarTime ofLocation(double latitude, double longitude, int altitude, String calculator)

      Obtains the solar time for given geographical location.

      This method handles the geographical location in decimal degrees only. If these data are given in degrees, arc minutes and arc seconds then users should apply the builder approach instead.

      Parameters:
      latitude - geographical latitude in decimal degrees (-90.0 <= x <= +90.0)
      longitude - geographical longitude in decimal degrees (-180.0 <= x < 180.0)
      altitude - geographical altitude relative to sea level in meters (0 <= x < 11,0000)
      calculator - name of solar time calculator
      Returns:
      instance of local solar time
      Throws:
      IllegalArgumentException - if the coordinates are out of range or the calculator is unknown
      Since:
      3.34/4.29
      See Also:
      SolarTime.Calculator.name()
    • ofLocation

      public static SolarTime ofLocation(double latitude, double longitude, int altitude, SolarTime.Calculator calculator)

      Obtains the solar time for given geographical location.

      This method handles the geographical location in decimal degrees only. If these data are given in degrees, arc minutes and arc seconds then users should apply the builder approach instead.

      Parameters:
      latitude - geographical latitude in decimal degrees (-90.0 <= x <= +90.0)
      longitude - geographical longitude in decimal degrees (-180.0 <= x < 180.0)
      altitude - geographical altitude relative to sea level in meters (0 <= x < 11,0000)
      calculator - instance of solar time calculator
      Returns:
      instance of local solar time
      Throws:
      IllegalArgumentException - if the coordinates are out of range
      Since:
      3.36/4.31
    • ofJerusalem

      public static SolarTime ofJerusalem()

      Obtains an instance of solar time for the temple area in Jerusalem which has a prominent meaning in Hebrew calendar and time.

      Returns:
      SolarTime
      Since:
      3.37/4.32
    • ofMecca

      public static SolarTime ofMecca()

      Obtains an instance of solar time for the Kaaba in Mecca which has a prominent meaning in islamic calendar.

      The start of day in Mecca can be obtained by the expression StartOfDay.definedBy(SolarTime.ofMecca().sunset()).

      Returns:
      SolarTime
      Since:
      3.37/4.32
      See Also:
      StartOfDay.definedBy(ChronoFunction)
    • getLatitude

      public double getLatitude()
      Description copied from interface: GeoLocation

      Obtains the geographical latitude of this instance.

      Specified by:
      getLatitude in interface GeoLocation
      Returns:
      latitude in decimal degrees (-90.0 <= x <= +90.0)
    • getLongitude

      public double getLongitude()
      Description copied from interface: GeoLocation

      Obtains the geographical longitude of this instance.

      Specified by:
      getLongitude in interface GeoLocation
      Returns:
      longitude in decimal degrees (-180.0 <= x < 180.0)
    • getAltitude

      public int getAltitude()
      Description copied from interface: GeoLocation

      Obtains the geographical altitude of this instance relative to sea level.

      Specified by:
      getAltitude in interface GeoLocation
      Returns:
      altitude in meters (0 <= x < 11,0000)
    • getCalculator

      public SolarTime.Calculator getCalculator()

      Obtains the underlying calculator.

      Returns:
      String
      Since:
      3.34/4.29
    • getObserverZoneID

      public Optional<TZID> getObserverZoneID()

      Obtains the optional observer timezone which might be associated with any calendar date input.

      Usually, this setting is not relevant for most regions of Earth but can be specified via the builder approach to handle some special cases.

      Returns:
      optional zone identifier associated with this geographical position
      Since:
      5.6
      See Also:
      ofLocation(), SolarTime.Builder.inTimezone(TZID)
    • sunrise

      public ChronoFunction<CalendarDate,​Optional<Moment>> sunrise()

      Calculates the moment of sunrise at the location of this instance.

      Example:

           SolarTime hamburg = SolarTime.ofLocation(53.55, 10.0);
           Optional<Moment> result = PlainDate.nowInSystemTime().get(hamburg.sunrise());
           System.out.println(result.get().toZonalTimestamp(() -> "Europe/Berlin"));
       

      Note: The precision is generally constrained to minutes.

      The result might be undefined (indicated by Optional.empty()) if the sun does not rise on given day (midnight sun or polar night).

      Returns:
      sunrise function applicable on any calendar date
      Since:
      3.34/4.29
    • sunrise

      public ChronoFunction<CalendarDate,​Optional<Moment>> sunrise(Twilight twilight)

      Calculates the time of given twilight at sunrise and the location of this instance.

      Note: The precision is generally constrained to minutes. And the atmospheric refraction is here not taken into account.

      The result might be undefined (indicated by Optional.empty()) if the twilight event does not happen on given day.

      Parameters:
      twilight - relevant definition of twilight
      Returns:
      twilight function at sunrise applicable on any calendar date
      Since:
      3.34/4.29
    • sunset

      Calculates the moment of sunset at the location of this instance.

      Example:

           SolarTime hamburg = SolarTime.ofLocation(53.55, 10.0);
           Optional<Moment> result = PlainDate.nowInSystemTime().get(hamburg.sunset());
           System.out.println(result.get().toZonalTimestamp(() -> "Europe/Berlin"));
       

      Note: The precision is generally constrained to minutes.

      The result might be undefined (indicated by Optional.empty()) if the sun does not set on given day (midnight sun or polar night).

      Returns:
      sunset function applicable on any calendar date
      Since:
      3.34/4.29
    • sunset

      public ChronoFunction<CalendarDate,​Optional<Moment>> sunset(Twilight twilight)

      Calculates the time of given twilight at sunset and the location of this instance.

      Note: The precision is generally constrained to minutes. And the atmospheric refraction is here not taken into account.

      The result might be undefined (indicated by Optional.empty()) if the twilight event does not happen on given day.

      Parameters:
      twilight - relevant definition of twilight
      Returns:
      twilight function at sunset applicable on any calendar date
      Since:
      3.34/4.29
    • sunshine

      public ChronoFunction<CalendarDate,​SolarTime.Sunshine> sunshine(TZID tzid)

      Queries a given calendar date for its associated sunshine data.

      The timezone parameter enables users to query for solar time data described in terms of a potentially quite different zone of the earth. However, the parameter does not interprete the input calendar date.

      The calculation is only possible if the underlying calculator supports the feature of solar declination. Otherwise an UnsupportedOperationException will be thrown.

      Parameters:
      tzid - the identifier of the timezone any local times of the result refer to
      Returns:
      function for obtaining sunshine data
      Since:
      3.34/4.29
    • polarNight

      public ChronoCondition<CalendarDate> polarNight()

      Determines if the sun is invisible all day on a given calendar date.

      The calculation is only possible if the underlying calculator supports the feature of solar declination. Otherwise an UnsupportedOperationException will be thrown.

      Returns:
      ChronoCondition
      Since:
      3.34/4.29
    • midnightSun

      public ChronoCondition<CalendarDate> midnightSun()

      Determines if the sun is visible all day on a given calendar date.

      The calculation is only possible if the underlying calculator supports the feature of solar declination. Otherwise an UnsupportedOperationException will be thrown.

      Returns:
      ChronoCondition
      Since:
      3.34/4.29
    • transitAtNoon

      public ChronoFunction<CalendarDate,​Moment> transitAtNoon()

      Calculates the moment of noon at the location of this instance (solar transit).

      Note 1: The transit time does not tell if the sun is above or below the horizon.

      Note 2: Here, the term noon is not related to civil timekeeping but the sundial time.

      Returns:
      noon function applicable on any calendar date
      Since:
      3.34/4.29
    • transitAtMidnight

      public ChronoFunction<CalendarDate,​Moment> transitAtMidnight()

      Calculates the moment of midnight at the location of this instance (lowest position of sun).

      Note 1: The transit time does not tell if the sun is above or below the horizon.

      Note 2: Here, the term midnight is not related to civil timekeeping but the sundial time.

      Returns:
      midnight function applicable on any calendar date
      Since:
      3.34/4.29
    • timeOfShadowBeforeNoon

      public ChronoFunction<CalendarDate,​Optional<Moment>> timeOfShadowBeforeNoon(double objectHeight, double shadowLength)

      Calculates the moment before noon when the given shadow occurs on given date at the location of this instance.

      The function is not supported in polar regions (+/- 66°) because the angle of sun is often changing too slowly to guarantee reliable results. Furthermore, the function might obtain an empty result if the given shadow is too short for the date in question.

      Parameters:
      objectHeight - the height of object in meters, must be positive
      shadowLength - the length of shadow thrown by the object in meters, must not be negative
      Returns:
      function for calculating the time of shadow applicable on any calendar date in minute precision
      Throws:
      IllegalArgumentException - if one or both parameters are not finite or out of range
      UnsupportedOperationException - if this instance is within the arctic or antarctic circle
      Since:
      5.7
      See Also:
      SunPosition.getShadowLength(double), timeOfShadowAfterNoon(double, double)
    • timeOfShadowAfterNoon

      public ChronoFunction<CalendarDate,​Optional<Moment>> timeOfShadowAfterNoon(double objectHeight, double shadowLength)

      Calculates the moment after noon when the given shadow occurs on given date at the location of this instance.

      The function is not supported in polar regions (+/- 66°) because the angle of sun is often changing too slowly to guarantee reliable results. Furthermore, the function might obtain an empty result if the given shadow is too short for the date in question.

      Parameters:
      objectHeight - the height of object in meters, must be positive
      shadowLength - the length of shadow thrown by the object in meters, must not be negative
      Returns:
      function for calculating the time of shadow applicable on any calendar date in minute precision
      Throws:
      IllegalArgumentException - if one or both parameters are not finite or out of range
      UnsupportedOperationException - if this instance is within the arctic or antarctic circle
      Since:
      5.7
      See Also:
      SunPosition.getShadowLength(double), timeOfShadowBeforeNoon(double, double)
    • equals

      public boolean equals(Object obj)
      Overrides:
      equals in class Object
    • hashCode

      public int hashCode()
      Overrides:
      hashCode in class Object
    • toString

      public String toString()
      Overrides:
      toString in class Object
    • apparentAt

      public static ChronoFunction<Moment,​PlainTimestamp> apparentAt(ZonalOffset offset)

      Determines the apparent solar time of any moment at given local time zone offset.

      Based on the astronomical equation of time. The default calculator is usually StdSolarCalculator.NOAA unless another calculator was set up via the service loader mechnism.

      Parameters:
      offset - the time zone offset which might depend on the geographical longitude
      Returns:
      function for getting the apparent solar time
      See Also:
      ZonalOffset.atLongitude(OffsetSign, int, int, double), equationOfTime(Moment)
    • apparentAt

      public static ChronoFunction<Moment,​PlainTimestamp> apparentAt(ZonalOffset offset, String calculator)

      Determines the apparent solar time of any moment at given local time zone offset.

      Based on the astronomical equation of time.

      Parameters:
      offset - the time zone offset which might depend on the geographical longitude
      calculator - name of solar time calculator
      Returns:
      function for getting the apparent solar time
      Since:
      3.34/4.29
      See Also:
      ZonalOffset.atLongitude(OffsetSign, int, int, double), equationOfTime(Moment, String)
    • onAverage

      public static ChronoFunction<Moment,​PlainTimestamp> onAverage(ZonalOffset offset)

      Determines the mean solar time of any moment at given local time zone offset.

      Parameters:
      offset - the time zone offset which might depend on the geographical longitude
      Returns:
      function for getting the mean solar time
      See Also:
      ZonalOffset.atLongitude(OffsetSign, int, int, double)
    • equationOfTime

      public static double equationOfTime(Moment moment)

      Determines the difference between apparent and mean solar time at given moment.

      See also Wikipedia. Relation: mean-solar-time + equation-of-time = apparent-solar-time

      The default calculator is usually StdSolarCalculator.NOAA unless another calculator was set up via the service loader mechnism.

      Parameters:
      moment - the moment when to determine the equation of time
      Returns:
      difference between apparent solar time and mean solar time in seconds
      Throws:
      IllegalArgumentException - if the moment is out of year range -2000/+3000
    • equationOfTime

      public static double equationOfTime(Moment moment, String calculator)

      Determines the difference between apparent and mean solar time at given moment.

      See also Wikipedia.

      Relation: mean-solar-time + equation-of-time = apparent-solar-time

      Parameters:
      moment - the moment when to determine the equation of time
      calculator - name of solar time calculator
      Returns:
      difference between apparent solar time and mean solar time in seconds
      Throws:
      IllegalArgumentException - if the moment is out of year range -2000/+3000 or if the calculator is unknown
      Since:
      3.34/4.29