Example #1
0
 /// <summary>
 /// Initializes a new instance of the <see cref="DaylightHours"/> class.
 /// </summary>
 /// <param name="location">
 /// The location.
 /// </param>
 /// <param name="day">
 /// The day.
 /// </param>
 /// <param name="sunrise">
 /// The sunrise time.
 /// </param>
 /// <param name="sunset">
 /// The sunset time.
 /// </param>
 private DaylightHours(GeographicLocation location, DateTimeOffset day, TimeSpan?sunrise, TimeSpan?sunset)
 {
     _day      = day;
     _location = location;
     _sunrise  = sunrise;
     _sunset   = sunset;
 }
Example #2
0
        private static DaylightHours CalculateCore(DateTimeOffset day, GeographicLocation location)
        {
            double jdate    = ToJulian(day);
            double n        = Math.Round((jdate - BaseJulianDays - 0.0009D) - (location.LongitudeWest / 360D));
            double jnoon    = BaseJulianDays + 0.0009D + (location.LongitudeWest / 360D) + n;
            double m        = (EarthDegreesPerYear + (EarthDegreesPerDay * (jnoon - BaseJulianDays))) % 360;
            double c        = (EarthEocCoeff1 * Sin(m)) + (EarthEocCoeff2 * Sin(2 * m)) + (EarthEocCoeff3 * Sin(3 * m));
            double sunLon   = (m + EarthPerihelion + c + 180D) % 360;
            double jtransit = jnoon + (EarthTransitJ1 * Sin(m)) + (EarthTransitJ2 * Sin(2 * sunLon));

            int    iteration = 0;
            double oldMean;

            do
            {
                oldMean = m;

                m        = (EarthDegreesPerYear + (EarthDegreesPerDay * (jtransit - BaseJulianDays))) % 360;
                c        = (EarthEocCoeff1 * Sin(m)) + (EarthEocCoeff2 * Sin(2 * m)) + (EarthEocCoeff3 * Sin(3 * m));
                sunLon   = (m + EarthPerihelion + c + 180D) % 360;
                jtransit = jnoon + (EarthTransitJ1 * Sin(m)) + (EarthTransitJ2 * Sin(2 * sunLon));
            }while (iteration++ < 100 && Math.Abs(m - oldMean) > Epsilon);

            double sunDec = Asin(Sin(sunLon) * Sin(EarthObliquity));
            double h      = Acos((Sin(EarthSolarDiskDiameter) - Sin(location.Latitude) * Sin(sunDec)) / (Cos(location.Latitude) * Cos(sunDec)));

            if (Math.Abs(h) < Epsilon || double.IsNaN(h) || double.IsInfinity(h))
            {
                return(new DaylightHours(location, day, null, null));
            }

            double jnoon2 = BaseJulianDays + 0.0009D + ((h + location.LongitudeWest) / 360D) + n;
            double jset   = jnoon2 + (EarthTransitJ1 * Sin(m)) + (EarthTransitJ2 * Sin(2 * sunLon));
            double jrise  = jtransit - (jset - jtransit);

            DateTimeOffset sunrise = FromJulian(jrise);

            Debug.Assert(sunrise.Date == day.Date, "Wrong sunrise", "Sunrise: Expected {0:D} but got {1:D} instead.", day, sunrise.Date);

            DateTimeOffset sunset = FromJulian(jset);

            Debug.Assert(sunset.Date == day.Date, "Wrong sunset", "Sunset: Expected {0:D} but got {1:D} instead.", day, sunset.Date);

            return(new DaylightHours(location, day, sunrise.TimeOfDay, sunset.TimeOfDay));
        }
Example #3
0
        /// <summary>
        /// Calculates the sunrise and sunset days for the specified date and location.
        /// </summary>
        /// <param name="year">
        /// The year for which the times are calculated.
        /// </param>
        /// <param name="month">
        /// The month for which the times are calculated.
        /// </param>
        /// <param name="day">
        /// The day for which the times are calculated.
        /// </param>
        /// <param name="location">
        /// The <see cref="GeographicLocation"/> for which the times are calculated.
        /// </param>
        /// <returns>
        /// A <see cref="DaylightHours"/> instance representing the calculated times.
        /// This value will never be <see langword="null"/>, although the sunrise/sunset times could be.
        /// </returns>
        /// <exception cref="ArgumentOutOfRangeException">
        /// <para><paramref name="year"/> is less than 1 or greater than 9999.</para>
        /// <para>-or-</para>
        /// <para><paramref name="month"/> is less than 1 or greater than 12.</para>
        /// <para>-or-</para>
        /// <para><paramref name="day"/> is less than 1 or greater than the number of days in the specified month.</para>
        /// <para>-or-</para>
        /// <para>The specified date is earlier than <see cref="DateTimeOffset.MinValue"/> or later than <see cref="DateTimeOffset.MaxValue"/>.</para>
        /// </exception>
        /// <exception cref="InvalidOperationException">
        /// There was an error with the calculation.
        /// </exception>
        public static DaylightHours Calculate(int year, int month, int day, GeographicLocation location)
        {
            var date = new DateTimeOffset(year, month, day, 0, 0, 0, TimeSpan.Zero);

            return(CalculateCore(date, location));
        }
Example #4
0
 /// <summary>
 /// Calculates the sunrise and sunset days for the specified date and location.
 /// </summary>
 /// <param name="day">
 /// The date for which the times are calculated.
 /// </param>
 /// <param name="location">
 /// The <see cref="GeographicLocation"/> for which the times are calculated.
 /// </param>
 /// <returns>
 /// A <see cref="DaylightHours"/> instance representing the calculated times.
 /// This value will never be <see langword="null"/>, although the sunrise/sunset times could be.
 /// </returns>
 /// <exception cref="InvalidOperationException">
 /// There was an error with the calculation.
 /// </exception>
 public static DaylightHours Calculate(DateTime day, GeographicLocation location)
 {
     return(CalculateCore(day.ToUniversalTime().Date, location));
 }
Example #5
0
 /// <summary>
 /// Calculates the sunrise and sunset days for the specified date and location.
 /// </summary>
 /// <param name="day">
 /// The date for which the times are calculated.
 /// </param>
 /// <param name="location">
 /// The <see cref="GeographicLocation"/> for which the times are calculated.
 /// </param>
 /// <returns>
 /// A <see cref="DaylightHours"/> instance representing the calculated times.
 /// This value will never be <see langword="null"/>, although the sunrise/sunset times could be.
 /// </returns>
 /// <exception cref="InvalidOperationException">
 /// There was an error with the calculation.
 /// </exception>
 public static DaylightHours Calculate(DateTimeOffset day, GeographicLocation location)
 {
     return(CalculateCore(day.UtcDateTime.Date, location));
 }