/// <summary> /// A method that calculates UTC sunrise as well as any time based on an /// angle above or below sunrise. This abstract method is implemented by the /// classes that extend this class. /// </summary> /// <param name="dateWithLocation">Used to calculate day of year.</param> /// <param name="zenith">the azimuth below the vertical zenith of 90 degrees. for /// sunrise typically the <see cref="AstronomicalCalculator.AdjustZenith">zenith</see> used for /// the calculation uses geometric zenith of 90°; and /// <see cref="AstronomicalCalculator.AdjustZenith">adjusts</see> this slightly to account for /// solar refraction and the sun's radius. Another example would /// be <see cref="AstronomicalCalendar.GetBeginNauticalTwilight"/> /// that passes <see cref="AstronomicalCalendar.NAUTICAL_ZENITH"/> to /// this method.</param> /// <param name="adjustForElevation">if set to <c>true</c> [adjust for elevation].</param> /// <returns> /// The UTC time of sunrise in 24 hour format. 5:45:00 AM will return /// 5.75.0. If an error was encountered in the calculation (expected /// behavior for some locations such as near the poles, /// <see cref="Double.NaN"/> will be returned. /// </returns> /// <seealso cref="AstronomicalCalculator.GetUtcSunrise"/> public override double GetUtcSunrise(IDateWithLocation dateWithLocation, double zenith, bool adjustForElevation) { /*if (dateWithLocation.Date.Year <= 2000) * { * throw new Exception("NOAACalculator can not calculate times earlier than the year 2000. Please try a date with a different year."); * }*/ zenith = AdjustZenith(zenith, adjustForElevation ? dateWithLocation.Location.Elevation : 0); double sunrise = CalcSunriseUtc(CalcJulianDay(dateWithLocation), dateWithLocation.Location.Latitude, -dateWithLocation.Location.Longitude, zenith); sunrise = sunrise / 60; // ensure that the time is >= 0 and < 24 while (sunrise < 0.0) { sunrise += 24.0; } while (sunrise >= 24.0) { sunrise -= 24.0; } return(sunrise); }
///<summary> /// The date:date-time function returns the current date and time as a /// date/time string. The date/time string that's returned must be a string /// in the format defined as the lexical representation of xs:Date in /// <a href = "http://www.w3.org/TR/xmlschema11-2/#Date">[3.3.8 Date]</a> /// of <a href = "http://www.w3.org/TR/xmlschema11-2/">[XML Schema 1.1 Part 2: /// Datatypes]</a>. The date/time format is basically CCYY-MM-DDThh:mm:ss, /// although implementers should consult <a href = "http://www.w3.org/TR/xmlschema11-2/">[XML Schema 1.1 Part 2: /// Datatypes]</a> and <a href = "http://www.iso.ch/markete/8601.pdf">[ISO /// 8601]</a> for details. The date/time string format must include a time /// zone, either a Z to indicate Coordinated Universal Time or a + or - /// followed by the difference between the difference from UTC represented as /// hh:mm. ///</summary> public virtual string GetXSDate(DateTime date, IDateWithLocation cal) { string xsdDateFormat = "yyyy-MM-dd'T'HH:mm:ss"; // // * if (xmlDateFormat == null || xmlDateFormat.trim().equals("")) { // * xmlDateFormat = xsdDateFormat; } // //var dateFormat = new SimpleDateFormat(xsdDateFormat); var buff = new StringBuilder(date.ToString(xsdDateFormat)); // Must also include offset from UTF. // Get the offset (in milliseconds). int offset = cal.Location.TimeZone.UtcOffset(cal.Date); // If there is no offset, we have "Coordinated // Universal Time." if (offset == 0) { buff.Append("Z"); } else { // Convert milliseconds to hours and minutes int hrs = offset / (60 * 60 * 1000); // In a few cases, the time zone may be +/-hh:30. int min = offset % (60 * 60 * 1000); char posneg = hrs < 0 ? '-' : '+'; buff.Append(posneg + FormatDigits(hrs) + ':' + FormatDigits(min)); } return(buff.ToString()); }
/// <summary> /// A method that calculates UTC sunrise as well as any time based on an /// angle above or below sunrise. This abstract method is implemented by the /// classes that extend this class. /// </summary> /// <param name="dateWithLocation">Used to calculate day of year.</param> /// <param name="zenith">the azimuth below the vertical zenith of 90 degrees. for /// sunrise typically the <see cref="AstronomicalCalculator.AdjustZenith">zenith</see> used for /// the calculation uses geometric zenith of 90°; and /// <see cref="AstronomicalCalculator.AdjustZenith">adjusts</see> this slightly to account for /// solar refraction and the sun's radius. Another example would /// be <see cref="AstronomicalCalendar.GetBeginNauticalTwilight"/> /// that passes <see cref="AstronomicalCalendar.NAUTICAL_ZENITH"/> to /// this method.</param> /// <param name="adjustForElevation">if set to <c>true</c> [adjust for elevation].</param> /// <returns> /// The UTC time of sunrise in 24 hour format. 5:45:00 AM will return /// 5.75.0. If an error was encountered in the calculation (expected /// behavior for some locations such as near the poles, /// <see cref="Double.NaN"/> will be returned. /// </returns> /// <seealso cref="AstronomicalCalculator.GetUtcSunrise"/> public override double GetUtcSunrise(IDateWithLocation dateWithLocation, double zenith, bool adjustForElevation) { /*if (dateWithLocation.Date.Year <= 2000) { throw new Exception("NOAACalculator can not calculate times earlier than the year 2000. Please try a date with a different year."); }*/ zenith = AdjustZenith(zenith, adjustForElevation ? dateWithLocation.Location.Elevation : 0); double sunrise = CalcSunriseUtc(CalcJulianDay(dateWithLocation), dateWithLocation.Location.Latitude, -dateWithLocation.Location.Longitude, zenith); sunrise = sunrise / 60; // ensure that the time is >= 0 and < 24 while (sunrise < 0.0) { sunrise += 24.0; } while (sunrise >= 24.0) { sunrise -= 24.0; } return sunrise; }
/// <summary> /// A method that calculates UTC sunrise as well as any time based on an /// angle above or below sunrise. This abstract method is implemented by the /// classes that extend this class. /// </summary> /// <param name="dateWithLocation">Used to calculate day of year.</param> /// <param name="zenith">the azimuth below the vertical zenith of 90 degrees. for /// sunrise typically the <see cref="AstronomicalCalculator.AdjustZenith">zenith</see> used for /// the calculation uses geometric zenith of 90°; and /// <see cref="AstronomicalCalculator.AdjustZenith">adjusts</see> this slightly to account for /// solar refraction and the sun's radius. Another example would /// be <see cref="AstronomicalCalendar.GetBeginNauticalTwilight"/> /// that passes <see cref="AstronomicalCalendar.NAUTICAL_ZENITH"/> to /// this method.</param> /// <param name="adjustForElevation">if set to <c>true</c> [adjust for elevation].</param> /// <returns> /// The UTC time of sunrise in 24 hour format. 5:45:00 AM will return /// 5.75.0. If an error was encountered in the calculation (expected /// behavior for some locations such as near the poles, /// <see cref="Double.NaN"/> will be returned. /// </returns> /// <seealso cref="AstronomicalCalculator.GetUtcSunrise"/> public override double GetUtcSunrise(IDateWithLocation dateWithLocation, double zenith, bool adjustForElevation) { double elevation = adjustForElevation ? dateWithLocation.Location.Elevation : 0; return(GetTimeUtc( dateWithLocation.Date, dateWithLocation.Location, AdjustZenith(zenith, elevation), true)); }
///<summary> /// Formats a date using this classe's <see cref = "DateFormat">date format</see>. ///</summary> ///<param name = "date"> /// the date to format </param> ///<param name = "dateWithLocation"> /// the <see cref = "IDateWithLocation">TimeZone and DateTime</see> used to help format /// based on the Calendar's DST and other settings. </param> ///<returns> the formatted string </returns> public virtual string FormatDate(DateTime date, IDateWithLocation dateWithLocation) { if (DateFormat == "yyyy-MM-dd'T'HH:mm:ss") { return(GetXSDate(date, dateWithLocation)); } else { return(date.ToString(DateFormat)); } }
///<summary> /// Generate a Julian day from Java Calendar ///</summary> ///<param name = "date"> /// Java Calendar </param> ///<returns> the Julian day corresponding to the date Note: Number is returned /// for start of day. Fractional days should be added later. </returns> private static double CalcJd(IDateWithLocation date) { int year = date.Date.Year; int month = date.Date.Month + 1; int day = date.Date.Day; if (month <= 2) { year -= 1; month += 12; } double A = Math.Floor((double)(year / 100)); double B = 2 - A + Math.Floor(A / 4); return(Math.Floor(365.25 * (year + 4716)) + Math.Floor(30.6001 * (month + 1)) + day + B - 1524.5); }
private static double DateToJulian(IDateWithLocation date) { int year = date.Date.Year; int month = date.Date.Month; int day = date.Date.Day; int hour = date.Date.Hour; int minute = date.Date.Minute; int second = date.Date.Second; double extra = (100.0 * year) + month - 190002.5; double JD = (367.0 * year) - (Math.Floor(7.0 * (year + Math.Floor((month + 9.0) / 12.0)) / 4.0)) + Math.Floor((275.0 * month) / 9.0) + day + ((hour + ((minute + (second / 60.0)) / 60.0)) / 24.0) + 1721013.5 - ((0.5 * extra) / Math.Abs(extra)) + 0.5; return(JD); }
/// <summary> /// Return the <a href="http://en.wikipedia.org/wiki/Celestial_coordinate_system">Solar Elevation</a> for the /// horizontal coordinate system at the given location at the given time.Can be negative if the sun is below the /// horizon.Not corrected for altitude. /// /// <param name="dateWithLocation">the date with location</param> public static double GetSolarElevation(IDateWithLocation dateWithLocation) { double julianDay = GetJulianDay(dateWithLocation.Date); double julianCenturies = GetJulianCenturiesFromJulianDay(julianDay); double eot = GetEquationOfTime(julianCenturies); double longitude = (dateWithLocation.Date.Hour + 12.0) + (dateWithLocation.Date.Minute + eot + dateWithLocation.Date.Second / 60.0) / 60.0; longitude = -(longitude * 360.0 / 24.0) % 360.0; double hourAngle_rad = (dateWithLocation.Location.Longitude - longitude).ToRadians(); double declination = GetSunDeclination(julianCenturies); double dec_rad = declination.ToRadians(); double lat_rad = dateWithLocation.Location.Latitude.ToRadians(); return(Math.Asin((Math.Sin(lat_rad) * Math.Sin(dec_rad)) + (Math.Cos(lat_rad) * Math.Cos(dec_rad) * Math.Cos(hourAngle_rad))).ToDegree()); }
/// <summary> /// A method that calculates UTC sunrise as well as any time based on an /// angle above or below sunrise. This abstract method is implemented by the /// classes that extend this class. /// </summary> /// <param name="astronomicalCalendar">Used to calculate day of year.</param> /// <param name="zenith">the azimuth below the vertical zenith of 90 degrees. for /// sunrise typically the <see cref="AstronomicalCalculator.AdjustZenith">zenith</see> used for /// the calculation uses geometric zenith of 90°; and /// <see cref="AstronomicalCalculator.AdjustZenith">adjusts</see> this slightly to account for /// solar refraction and the sun's radius. Another example would /// be <see cref="AstronomicalCalendar.GetBeginNauticalTwilight"/> /// that passes <see cref="AstronomicalCalendar.NAUTICAL_ZENITH"/> to /// this method.</param> /// <param name="adjustForElevation">if set to <c>true</c> [adjust for elevation].</param> /// <returns> /// The UTC time of sunrise in 24 hour format. 5:45:00 AM will return /// 5.75.0. If an error was encountered in the calculation (expected /// behavior for some locations such as near the poles, /// <see cref="Double.NaN"/> will be returned. /// </returns> /// <seealso cref="AstronomicalCalculator.GetUtcSunrise"/> public override double GetUtcSunrise(IDateWithLocation dateWithLocation, double zenith, bool adjustForElevation) { double doubleTime = double.NaN; if (adjustForElevation) { zenith = AdjustZenith(zenith, dateWithLocation.Location.Elevation); } else { zenith = AdjustZenith(zenith, 0); } doubleTime = GetTimeUtc(dateWithLocation.Date.Year, dateWithLocation.Date.Month, dateWithLocation.Date.Day, dateWithLocation.Location.Longitude, dateWithLocation.Location.Latitude, zenith, TYPE_SUNRISE); return(doubleTime); }
/// <summary> /// A method that calculates UTC sunrise as well as any time based on an /// angle above or below sunrise. This abstract method is implemented by the /// classes that extend this class. /// </summary> /// <param name="dateWithLocation">Used to calculate day of year.</param> /// <param name="zenith">the azimuth below the vertical zenith of 90 degrees. for /// sunrise typically the <see cref="AstronomicalCalculator.AdjustZenith">zenith</see> used for /// the calculation uses geometric zenith of 90°; and /// <see cref="AstronomicalCalculator.AdjustZenith">adjusts</see> this slightly to account for /// solar refraction and the sun's radius. Another example would /// be <see cref="AstronomicalCalendar.GetBeginNauticalTwilight"/> /// that passes <see cref="AstronomicalCalendar.NAUTICAL_ZENITH"/> to /// this method.</param> /// <param name="adjustForElevation">if set to <c>true</c> [adjust for elevation].</param> /// <returns> /// The UTC time of sunrise in 24 hour format. 5:45:00 AM will return /// 5.75.0. If an error was encountered in the calculation (expected /// behavior for some locations such as near the poles, /// <see cref="Double.NaN"/> will be returned. /// </returns> /// <seealso cref="AstronomicalCalculator.GetUtcSunrise"/> public override double GetUtcSunrise(IDateWithLocation dateWithLocation, double zenith, bool adjustForElevation) { double adjustedZenith = AdjustZenith(zenith, adjustForElevation ? dateWithLocation.Location.Elevation : 0); double sunrise = GetSunriseUTC(GetJulianDay(dateWithLocation.Date), dateWithLocation.Location.Latitude, -dateWithLocation.Location.Longitude, adjustedZenith); sunrise = sunrise / 60; // ensure that the time is >= 0 and < 24 while (sunrise < 0.0) { sunrise += 24.0; } while (sunrise >= 24.0) { sunrise -= 24.0; } return(sunrise); }
/// <summary> /// A method that calculates UTC sunset as well as any time based on an angle /// above or below sunset. This abstract method is implemented by the classes /// that extend this class. /// </summary> /// <param name="astronomicalCalendar">Used to calculate day of year.</param> /// <param name="zenith">the azimuth below the vertical zenith of 90°;. For sunset /// typically the <see cref="AstronomicalCalculator.AdjustZenith">zenith</see> used for the /// calculation uses geometric zenith of 90°; and /// <see cref="AstronomicalCalculator.AdjustZenith">adjusts</see> this slightly to account for /// solar refraction and the sun's radius. Another example would /// be <see cref="AstronomicalCalendar.GetEndNauticalTwilight"/> that /// passes <see cref="AstronomicalCalendar.NAUTICAL_ZENITH"/> to this /// method.</param> /// <param name="adjustForElevation"></param> /// <returns> /// The UTC time of sunset in 24 hour format. 5:45:00 AM will return /// 5.75.0. If an error was encountered in the calculation (expected /// behavior for some locations such as near the poles, /// <seealso cref="Double.NaN"/> will be returned. /// </returns> /// <seealso cref="AstronomicalCalculator.GetUtcSunset"/> public override double GetUtcSunset(IDateWithLocation dateWithLocation, double zenith, bool adjustForElevation) { // if (astronomicalCalendar.getCalendar().get(Calendar.YEAR) <= 2000) { // throw new ZmanimException( // "NOAACalculator can not calculate times for the year 2000. Please try // a date with a different year."); // } if (adjustForElevation) { zenith = AdjustZenith(zenith, dateWithLocation.Location.Elevation); } else { zenith = AdjustZenith(zenith, 0); } double sunset = CalcSunsetUtc(CalcJulianDay(dateWithLocation), dateWithLocation.Location.Latitude, -dateWithLocation.Location.Longitude, zenith); sunset = sunset / 60; // ensure that the time is >= 0 and < 24 while (sunset < 0.0) { sunset += 24.0; } while (sunset >= 24.0) { sunset -= 24.0; } return(sunset); }
/// <summary> /// A method that calculates UTC sunset as well as any time based on an angle /// above or below sunset. This abstract method is implemented by the classes /// that extend this class. /// </summary> /// <param name="dateWithLocation">Used to calculate day of year.</param> /// <param name="zenith">the azimuth below the vertical zenith of 90°;. For sunset /// typically the <see cref="AstronomicalCalculator.AdjustZenith">zenith</see> used for the /// calculation uses geometric zenith of 90°; and /// <see cref="AstronomicalCalculator.AdjustZenith">adjusts</see> this slightly to account for /// solar refraction and the sun's radius. Another example would /// be <see cref="AstronomicalCalendar.GetEndNauticalTwilight"/> that /// passes <see cref="AstronomicalCalendar.NAUTICAL_ZENITH"/> to this /// method.</param> /// <param name="adjustForElevation"></param> /// <returns> /// The UTC time of sunset in 24 hour format. 5:45:00 AM will return /// 5.75.0. If an error was encountered in the calculation (expected /// behavior for some locations such as near the poles, /// <seealso cref="Double.NaN"/> will be returned. /// </returns> /// <seealso cref="AstronomicalCalculator.GetUtcSunset"/> public override double GetUtcSunset(IDateWithLocation dateWithLocation, double zenith, bool adjustForElevation) { double elevation = adjustForElevation ? dateWithLocation.Location.Elevation : 0; double sunset = GetSunsetUTC( GetJulianDay(dateWithLocation.Date), dateWithLocation.Location.Latitude, -dateWithLocation.Location.Longitude, AdjustZenith(zenith, elevation) ); sunset = sunset / 60; // ensure that the time is >= 0 and < 24 while (sunset < 0.0) { sunset += 24.0; } while (sunset >= 24.0) { sunset -= 24.0; } return(sunset); }
private static double DateToJulian(IDateWithLocation date) { int year = date.Date.Year; int month = date.Date.Month; int day = date.Date.Day; int hour = date.Date.Hour; int minute = date.Date.Minute; int second = date.Date.Second; double extra = (100.0*year) + month - 190002.5; double JD = (367.0*year) - (Math.Floor(7.0*(year + Math.Floor((month + 9.0)/12.0))/4.0)) + Math.Floor((275.0*month)/9.0) + day + ((hour + ((minute + (second/60.0))/60.0))/24.0) + 1721013.5 - ((0.5*extra)/Math.Abs(extra)) + 0.5; return JD; }
private double GetUtcSunriseSunset( IDateWithLocation dateWithLocation, double zenith, bool adjustForElevation, bool isSunrise) { double elevation = adjustForElevation ? dateWithLocation.Location.Elevation : 0; double adjustedZenith = AdjustZenith(zenith, elevation); // step 1: First calculate the day of the year int dayOfYear = dateWithLocation.Date.DayOfYear; // step 2: convert the longitude to hour value and calculate an // approximate time double lngHour = dateWithLocation.Location.Longitude / 15; double t = dayOfYear + (((isSunrise ? 6 : 18) - lngHour) / 24); // step 3: calculate the sun's mean anomaly double meanAnomaly = (0.9856 * t) - 3.289; // step 4: calculate the sun's true longitude double trueLongitude = meanAnomaly + (1.916 * Math.Sin(meanAnomaly.ToRadians())) + (0.020 * Math.Sin((2 * meanAnomaly).ToRadians())) + 282.634; while (trueLongitude < 0) { trueLongitude = trueLongitude + 360; } while (trueLongitude >= 360) { trueLongitude = trueLongitude - 360; } // step 5a: calculate the sun's right ascension double rAscension = Math.Atan(0.91764 * Math.Tan(trueLongitude.ToRadians())).ToDegree(); while (rAscension < 0) { rAscension = rAscension + 360; } while (rAscension >= 360) { rAscension = rAscension - 360; } // step 5b: right ascension value needs to be in the same quadrant as L double lQuadrant = Math.Floor(trueLongitude / 90) * 90; double rQuadrant = Math.Floor(rAscension / 90) * 90; rAscension = rAscension + (lQuadrant - rQuadrant); // step 5c: right ascension value needs to be converted into hours rAscension /= 15; // step 6: calculate the sun's declination double sinDec = 0.39782 * Math.Sin(trueLongitude.ToRadians()); double cosDec = Math.Cos(Math.Asin(sinDec)); var latitudeRadians = dateWithLocation.Location.Latitude.ToRadians(); // step 7a: calculate the sun's local hour angle double cosH = (Math.Cos(adjustedZenith.ToRadians()) - (sinDec * Math.Sin(latitudeRadians))) / (cosDec * Math.Cos(latitudeRadians)); // step 7b: finish calculating H and convert into hours double hours = Math.Acos(cosH).ToDegree(); if (isSunrise) { hours = 360 - hours; } hours = hours / 15; // step 8: calculate local mean time double localMeanTime = hours + rAscension - (0.06571 * t) - 6.622; // step 9: convert to UTC double utc = localMeanTime - lngHour; while (utc < 0) { utc = utc + 24; } while (utc >= 24) { utc = utc - 24; } return(utc); }
/// <summary> /// A method that calculates UTC sunrise as well as any time based on an /// angle above or below sunrise. This abstract method is implemented by the /// classes that extend this class. /// </summary> /// <param name="astronomicalCalendar">Used to calculate day of year.</param> /// <param name="zenith">the azimuth below the vertical zenith of 90 degrees. for /// sunrise typically the <see cref="AstronomicalCalculator.AdjustZenith">zenith</see> used for /// the calculation uses geometric zenith of 90°; and /// <see cref="AstronomicalCalculator.AdjustZenith">adjusts</see> this slightly to account for /// solar refraction and the sun's radius. Another example would /// be <see cref="AstronomicalCalendar.GetBeginNauticalTwilight"/> /// that passes <see cref="AstronomicalCalendar.NAUTICAL_ZENITH"/> to /// this method.</param> /// <param name="adjustForElevation"></param> /// <returns> /// The UTC time of sunrise in 24 hour format. 5:45:00 AM will return /// 5.75.0. If an error was encountered in the calculation (expected /// behavior for some locations such as near the poles, /// <see cref="Double.NaN"/> will be returned. /// </returns> public override double GetUtcSunrise(IDateWithLocation dateWithLocation, double zenith, bool adjustForElevation) { // zenith = adjustZenithForElevation(astronomicalCalendar, zenith, // geoLocation.getElevation()); // double elevationAdjustment = this.getElevationAdjustment(zenith, // geoLocation.getElevation()); // double refractionAdjustment = this.getRefraction(zenith); // zenith = zenith + elevationAdjustment + refractionAdjustment; if (adjustForElevation) zenith = AdjustZenith(zenith, dateWithLocation.Location.Elevation); else zenith = AdjustZenith(zenith, 0); // step 1: First calculate the day of the year // NOT NEEDED in this implementation // step 2: convert the longitude to hour value and calculate an // approximate time double lngHour = dateWithLocation.Location.Longitude / 15; double t = dateWithLocation.Date.DayOfYear + ((6 - lngHour) / 24); // use 18 for // sunset instead // of 6 // step 3: calculate the sun's mean anomaly double m = (0.9856*t) - 3.289; // step 4: calculate the sun's true longitude double l = m + (1.916*Math.Sin(MathExtensions.ToRadians(m))) + (0.020*Math.Sin(MathExtensions.ToRadians(2*m))) + 282.634; while (l < 0) { double Lx = l + 360; l = Lx; } while (l >= 360) { double Lx = l - 360; l = Lx; } // step 5a: calculate the sun's right ascension double RA = MathExtensions.ToDegree(Math.Atan(0.91764*Math.Tan(MathExtensions.ToRadians(l)))); while (RA < 0) { double RAx = RA + 360; RA = RAx; } while (RA >= 360) { double RAx = RA - 360; RA = RAx; } // step 5b: right ascension value needs to be in the same quadrant as L double lQuadrant = Math.Floor(l/90)*90; double raQuadrant = Math.Floor(RA/90)*90; RA = RA + (lQuadrant - raQuadrant); // step 5c: right ascension value needs to be converted into hours RA /= 15; // step 6: calculate the sun's declination double sinDec = 0.39782*Math.Sin(MathExtensions.ToRadians(l)); double cosDec = Math.Cos(Math.Asin(sinDec)); // step 7a: calculate the sun's local hour angle double cosH = (Math.Cos(MathExtensions.ToRadians(zenith)) - (sinDec * Math.Sin(MathExtensions.ToRadians(dateWithLocation.Location.Latitude)))) / (cosDec * Math.Cos(MathExtensions.ToRadians(dateWithLocation.Location.Latitude))); // the following line would throw an Exception if the sun never rose. // this is not needed since the calculation will return a Double.NaN // if (cosH > 1) throw new Exception("doesnthappen"); // FOR SUNSET use the following instead of the above if statement. // if (cosH < -1) // step 7b: finish calculating H and convert into hours double H = 360 - MathExtensions.ToDegree(Math.Acos(cosH)); // FOR SUNSET remove "360 - " from the above H = H/15; // step 8: calculate local mean time double T = H + RA - (0.06571*t) - 6.622; // step 9: convert to UTC double UT = T - lngHour; while (UT < 0) { double UTx = UT + 24; UT = UTx; } while (UT >= 24) { double UTx = UT - 24; UT = UTx; } return UT; }
/// <summary> /// A method that calculates UTC sunset as well as any time based on an angle /// above or below sunset. This abstract method is implemented by the classes /// that extend this class. /// </summary> /// <param name="astronomicalCalendar">Used to calculate day of year.</param> /// <param name="zenith">the azimuth below the vertical zenith of 90°;. For sunset /// typically the <see cref="AstronomicalCalculator.AdjustZenith">zenith</see> used for the /// calculation uses geometric zenith of 90°; and /// <see cref="AstronomicalCalculator.AdjustZenith">adjusts</see> this slightly to account for /// solar refraction and the sun's radius. Another example would /// be <see cref="AstronomicalCalendar.GetEndNauticalTwilight"/> that /// passes <see cref="AstronomicalCalendar.NAUTICAL_ZENITH"/> to this /// method.</param> /// <param name="adjustForElevation">if set to <c>true</c> [adjust for elevation].</param> /// <returns> /// The UTC time of sunset in 24 hour format. 5:45:00 AM will return /// 5.75.0. If an error was encountered in the calculation (expected /// behavior for some locations such as near the poles, /// <seealso cref="Double.NaN"/> will be returned. /// </returns> public abstract double GetUtcSunset(IDateWithLocation dateWithLocation, double zenith, bool adjustForElevation);
///<summary> /// Generate a Julian day from a .NET date ///</summary> ///<param name = "date"> /// Java Calendar </param> ///<returns> the Julian day corresponding to the date Note: Number is returned /// for start of day. Fractional days should be added later. </returns> private static double CalcJulianDay(IDateWithLocation dateWithLocation) { var date = dateWithLocation.Date; return new DateTime(date.Year, date.Month, date.Day).ToOADate() + 2415018.5; }
/// <summary> /// Initializes a new instance of the <see cref="AstronomicalCalendar"/> class. /// </summary> /// <param name="dateWithLocation">The date with location.</param> public AstronomicalCalendar(IDateWithLocation dateWithLocation) { DateWithLocation = dateWithLocation; AstronomicalCalculator = Calculator.AstronomicalCalculator.GetDefault(); }
///<summary> /// Formats a date using this classe's <see cref = "DateFormat">date format</see>. ///</summary> ///<param name = "date"> /// the date to format </param> ///<param name = "dateWithLocation"> /// the <see cref = "IDateWithLocation">TimeZone and DateTime</see> used to help format /// based on the Calendar's DST and other settings. </param> ///<returns> the formatted string </returns> public virtual string FormatDate(DateTime date, IDateWithLocation dateWithLocation) { if (DateFormat == "yyyy-MM-dd'T'HH:mm:ss") { return GetXSDate(date, dateWithLocation); } else { return date.ToString(DateFormat); } }
///<summary> /// Generate a Julian day from a .NET date ///</summary> ///<param name = "date"> /// Java Calendar </param> ///<returns> the Julian day corresponding to the date Note: Number is returned /// for start of day. Fractional days should be added later. </returns> private static double CalcJulianDay(IDateWithLocation dateWithLocation) { var date = dateWithLocation.Date; return(new DateTime(date.Year, date.Month, date.Day).ToOADate() + 2415018.5); }
/// <summary> /// A method that calculates UTC sunset as well as any time based on an angle /// above or below sunset. This abstract method is implemented by the classes /// that extend this class. /// </summary> /// <param name="astronomicalCalendar">Used to calculate day of year.</param> /// <param name="zenith">the azimuth below the vertical zenith of 90°;. For sunset /// typically the <see cref="AstronomicalCalculator.AdjustZenith">zenith</see> used for the /// calculation uses geometric zenith of 90°; and /// <see cref="AstronomicalCalculator.AdjustZenith">adjusts</see> this slightly to account for /// solar refraction and the sun's radius. Another example would /// be <see cref="AstronomicalCalendar.GetEndNauticalTwilight"/> that /// passes <see cref="AstronomicalCalendar.NAUTICAL_ZENITH"/> to this /// method.</param> /// <param name="adjustForElevation"></param> /// <returns> /// The UTC time of sunset in 24 hour format. 5:45:00 AM will return /// 5.75.0. If an error was encountered in the calculation (expected /// behavior for some locations such as near the poles, /// <seealso cref="Double.NaN"/> will be returned. /// </returns> /// <seealso cref="AstronomicalCalculator.GetUtcSunset"/> public override double GetUtcSunset(IDateWithLocation dateWithLocation, double zenith, bool adjustForElevation) { // if (astronomicalCalendar.getCalendar().get(Calendar.YEAR) <= 2000) { // throw new ZmanimException( // "NOAACalculator can not calculate times for the year 2000. Please try // a date with a different year."); // } if (adjustForElevation) { zenith = AdjustZenith(zenith, dateWithLocation.Location.Elevation); } else { zenith = AdjustZenith(zenith, 0); } double sunset = CalcSunsetUtc(CalcJulianDay(dateWithLocation), dateWithLocation.Location.Latitude, -dateWithLocation.Location.Longitude, zenith); sunset = sunset / 60; // ensure that the time is >= 0 and < 24 while (sunset < 0.0) { sunset += 24.0; } while (sunset >= 24.0) { sunset -= 24.0; } return sunset; }
/// <summary> /// A method that calculates UTC sunrise as well as any time based on an /// angle above or below sunrise. This abstract method is implemented by the /// classes that extend this class. /// </summary> /// <param name="astronomicalCalendar">Used to calculate day of year.</param> /// <param name="zenith">the azimuth below the vertical zenith of 90 degrees. for /// sunrise typically the <see cref="AstronomicalCalculator.AdjustZenith">zenith</see> used for /// the calculation uses geometric zenith of 90°; and /// <see cref="AstronomicalCalculator.AdjustZenith">adjusts</see> this slightly to account for /// solar refraction and the sun's radius. Another example would /// be <see cref="AstronomicalCalendar.GetBeginNauticalTwilight"/> /// that passes <see cref="AstronomicalCalendar.NAUTICAL_ZENITH"/> to /// this method.</param> /// <param name="adjustForElevation">if set to <c>true</c> [adjust for elevation].</param> /// <returns> /// The UTC time of sunrise in 24 hour format. 5:45:00 AM will return /// 5.75.0. If an error was encountered in the calculation (expected /// behavior for some locations such as near the poles, /// <see cref="Double.NaN"/> will be returned. /// </returns> /// <seealso cref="AstronomicalCalculator.GetUtcSunrise"/> public override double GetUtcSunrise(IDateWithLocation dateWithLocation, double zenith, bool adjustForElevation) { double doubleTime = double.NaN; if (adjustForElevation) { zenith = AdjustZenith(zenith, dateWithLocation.Location.Elevation); } else { zenith = AdjustZenith(zenith, 0); } doubleTime = GetTimeUtc(dateWithLocation.Date.Year, dateWithLocation.Date.Month, dateWithLocation.Date.Day, dateWithLocation.Location.Longitude, dateWithLocation.Location.Latitude, zenith, TYPE_SUNRISE); return doubleTime; }
///<summary> /// The date:date-time function returns the current date and time as a /// date/time string. The date/time string that's returned must be a string /// in the format defined as the lexical representation of xs:Date in /// <a href = "http://www.w3.org/TR/xmlschema11-2/#Date">[3.3.8 Date]</a> /// of <a href = "http://www.w3.org/TR/xmlschema11-2/">[XML Schema 1.1 Part 2: /// Datatypes]</a>. The date/time format is basically CCYY-MM-DDThh:mm:ss, /// although implementers should consult <a href = "http://www.w3.org/TR/xmlschema11-2/">[XML Schema 1.1 Part 2: /// Datatypes]</a> and <a href = "http://www.iso.ch/markete/8601.pdf">[ISO /// 8601]</a> for details. The date/time string format must include a time /// zone, either a Z to indicate Coordinated Universal Time or a + or - /// followed by the difference between the difference from UTC represented as /// hh:mm. ///</summary> public virtual string GetXSDate(DateTime date, IDateWithLocation cal) { string xsdDateFormat = "yyyy-MM-dd'T'HH:mm:ss"; // // * if (xmlDateFormat == null || xmlDateFormat.trim().equals("")) { // * xmlDateFormat = xsdDateFormat; } // //var dateFormat = new SimpleDateFormat(xsdDateFormat); var buff = new StringBuilder(date.ToString(xsdDateFormat)); // Must also include offset from UTF. // Get the offset (in milliseconds). int offset = cal.Location.TimeZone.UtcOffset(cal.Date); // If there is no offset, we have "Coordinated // Universal Time." if (offset == 0) buff.Append("Z"); else { // Convert milliseconds to hours and minutes int hrs = offset / (60 * 60 * 1000); // In a few cases, the time zone may be +/-hh:30. int min = offset % (60 * 60 * 1000); char posneg = hrs < 0 ? '-' : '+'; buff.Append(posneg + FormatDigits(hrs) + ':' + FormatDigits(min)); } return buff.ToString(); }
/// <summary> /// Initializes a new instance of the <see cref="ComplexZmanimCalendar"/> class. /// </summary> /// <param name="dateWithLocation">The date with location.</param> public ComplexZmanimCalendar(IDateWithLocation dateWithLocation) : base(dateWithLocation) { }
/// <summary> /// A method that calculates UTC sunset as well as any time based on an angle /// above or below sunset. This abstract method is implemented by the classes /// that extend this class. /// </summary> /// <param name="astronomicalCalendar">Used to calculate day of year.</param> /// <param name="zenith">the azimuth below the vertical zenith of 90°;. For sunset /// typically the <see cref="AstronomicalCalculator.AdjustZenith">zenith</see> used for the /// calculation uses geometric zenith of 90°; and /// <see cref="AstronomicalCalculator.AdjustZenith">adjusts</see> this slightly to account for /// solar refraction and the sun's radius. Another example would /// be <see cref="AstronomicalCalendar.GetEndNauticalTwilight"/> that /// passes <see cref="AstronomicalCalendar.NAUTICAL_ZENITH"/> to this /// method.</param> /// <param name="adjustForElevation"></param> /// <returns> /// The UTC time of sunset in 24 hour format. 5:45:00 AM will return /// 5.75.0. If an error was encountered in the calculation (expected /// behavior for some locations such as near the poles, /// <seealso cref="Double.NaN"/> will be returned. /// </returns> public override double GetUtcSunset(IDateWithLocation dateWithLocation, double zenith, bool adjustForElevation) { // zenith = adjustZenithForElevation(astronomicalCalendar, zenith, // geoLocation.getElevation()); // double elevationAdjustment = this.getElevationAdjustment(zenith, // geoLocation.getElevation()); // double refractionAdjustment = this.getRefraction(zenith); // zenith = zenith + elevationAdjustment + refractionAdjustment; if (adjustForElevation) { zenith = AdjustZenith(zenith, dateWithLocation.Location.Elevation); } else { zenith = AdjustZenith(zenith, 0); } // step 1: First calculate the day of the year // int calendarDayOfYear = calelendar.DAY_OF_YEAR; // int N=theday - date(1,1,theday.year()) + 1; int N = dateWithLocation.Date.DayOfYear; // step 2: convert the longitude to hour value and calculate an // approximate time double lngHour = dateWithLocation.Location.Longitude / 15; double t = N + ((18 - lngHour) / 24); // step 3: calculate the sun's mean anomaly double M = (0.9856 * t) - 3.289; // step 4: calculate the sun's true longitude double L = M + (1.916 * Math.Sin(MathExtensions.ToRadians(M))) + (0.020 * Math.Sin(MathExtensions.ToRadians(2 * M))) + 282.634; while (L < 0) { double Lx = L + 360; L = Lx; } while (L >= 360) { double Lx = L - 360; L = Lx; } // step 5a: calculate the sun's right ascension double RA = MathExtensions.ToDegree(Math.Atan(0.91764 * Math.Tan(MathExtensions.ToRadians(L)))); while (RA < 0) { double RAx = RA + 360; RA = RAx; } while (RA >= 360) { double RAx = RA - 360; RA = RAx; } // step 5b: right ascension value needs to be in the same quadrant as L double Lquadrant = Math.Floor(L / 90) * 90; double RAquadrant = Math.Floor(RA / 90) * 90; RA = RA + (Lquadrant - RAquadrant); // step 5c: right ascension value needs to be converted into hours RA /= 15; // step 6: calculate the sun's declination double sinDec = 0.39782 * Math.Sin(MathExtensions.ToRadians(L)); double cosDec = Math.Cos(Math.Asin(sinDec)); // step 7a: calculate the sun's local hour angle double cosH = (Math.Cos(MathExtensions.ToRadians(zenith)) - (sinDec * Math.Sin(MathExtensions.ToRadians(dateWithLocation.Location.Latitude)))) / (cosDec * Math.Cos(MathExtensions.ToRadians(dateWithLocation.Location.Latitude))); // the following line would throw an Exception if the sun never set. // this is not needed since the calculation will return a Double.NaN // if (cosH < -1) throw new ZmanimException("doesnthappen"); // step 7b: finish calculating H and convert into hours double H = MathExtensions.ToDegree(Math.Acos(cosH)); H = H / 15; // step 8: calculate local mean time double T = H + RA - (0.06571 * t) - 6.622; // step 9: convert to UTC double UT = T - lngHour; while (UT < 0) { double UTx = UT + 24; UT = UTx; } while (UT >= 24) { double UTx = UT - 24; UT = UTx; } return(UT); }
/// <summary> /// A method that calculates UTC sunrise as well as any time based on an /// angle above or below sunrise. This abstract method is implemented by the /// classes that extend this class. /// </summary> /// <param name="astronomicalCalendar">Used to calculate day of year.</param> /// <param name="zenith">the azimuth below the vertical zenith of 90 degrees. for /// sunrise typically the <see cref="AstronomicalCalculator.AdjustZenith">zenith</see> used for /// the calculation uses geometric zenith of 90°; and /// <see cref="AstronomicalCalculator.AdjustZenith">adjusts</see> this slightly to account for /// solar refraction and the sun's radius. Another example would /// be <see cref="AstronomicalCalendar.GetBeginNauticalTwilight"/> /// that passes <see cref="AstronomicalCalendar.NAUTICAL_ZENITH"/> to /// this method.</param> /// <param name="adjustForElevation"></param> /// <returns> /// The UTC time of sunrise in 24 hour format. 5:45:00 AM will return /// 5.75.0. If an error was encountered in the calculation (expected /// behavior for some locations such as near the poles, /// <see cref="Double.NaN"/> will be returned. /// </returns> public override double GetUtcSunrise(IDateWithLocation dateWithLocation, double zenith, bool adjustForElevation) { // zenith = adjustZenithForElevation(astronomicalCalendar, zenith, // geoLocation.getElevation()); // double elevationAdjustment = this.getElevationAdjustment(zenith, // geoLocation.getElevation()); // double refractionAdjustment = this.getRefraction(zenith); // zenith = zenith + elevationAdjustment + refractionAdjustment; if (adjustForElevation) { zenith = AdjustZenith(zenith, dateWithLocation.Location.Elevation); } else { zenith = AdjustZenith(zenith, 0); } // step 1: First calculate the day of the year // NOT NEEDED in this implementation // step 2: convert the longitude to hour value and calculate an // approximate time double lngHour = dateWithLocation.Location.Longitude / 15; double t = dateWithLocation.Date.DayOfYear + ((6 - lngHour) / 24); // use 18 for // sunset instead // of 6 // step 3: calculate the sun's mean anomaly double m = (0.9856 * t) - 3.289; // step 4: calculate the sun's true longitude double l = m + (1.916 * Math.Sin(MathExtensions.ToRadians(m))) + (0.020 * Math.Sin(MathExtensions.ToRadians(2 * m))) + 282.634; while (l < 0) { double Lx = l + 360; l = Lx; } while (l >= 360) { double Lx = l - 360; l = Lx; } // step 5a: calculate the sun's right ascension double RA = MathExtensions.ToDegree(Math.Atan(0.91764 * Math.Tan(MathExtensions.ToRadians(l)))); while (RA < 0) { double RAx = RA + 360; RA = RAx; } while (RA >= 360) { double RAx = RA - 360; RA = RAx; } // step 5b: right ascension value needs to be in the same quadrant as L double lQuadrant = Math.Floor(l / 90) * 90; double raQuadrant = Math.Floor(RA / 90) * 90; RA = RA + (lQuadrant - raQuadrant); // step 5c: right ascension value needs to be converted into hours RA /= 15; // step 6: calculate the sun's declination double sinDec = 0.39782 * Math.Sin(MathExtensions.ToRadians(l)); double cosDec = Math.Cos(Math.Asin(sinDec)); // step 7a: calculate the sun's local hour angle double cosH = (Math.Cos(MathExtensions.ToRadians(zenith)) - (sinDec * Math.Sin(MathExtensions.ToRadians(dateWithLocation.Location.Latitude)))) / (cosDec * Math.Cos(MathExtensions.ToRadians(dateWithLocation.Location.Latitude))); // the following line would throw an Exception if the sun never rose. // this is not needed since the calculation will return a Double.NaN // if (cosH > 1) throw new Exception("doesnthappen"); // FOR SUNSET use the following instead of the above if statement. // if (cosH < -1) // step 7b: finish calculating H and convert into hours double H = 360 - MathExtensions.ToDegree(Math.Acos(cosH)); // FOR SUNSET remove "360 - " from the above H = H / 15; // step 8: calculate local mean time double T = H + RA - (0.06571 * t) - 6.622; // step 9: convert to UTC double UT = T - lngHour; while (UT < 0) { double UTx = UT + 24; UT = UTx; } while (UT >= 24) { double UTx = UT - 24; UT = UTx; } return(UT); }
/// <summary> /// Initializes a new instance of the <see cref="ZmanimCalendar"/> class. /// </summary> /// <param name="dateWithLocation">The date with location.</param> public ZmanimCalendar(IDateWithLocation dateWithLocation) : base(dateWithLocation) { }
/// <summary> /// A method that calculates UTC sunset as well as any time based on an angle /// above or below sunset. This abstract method is implemented by the classes /// that extend this class. /// </summary> /// <param name="dateWithLocation">Used to calculate day of year.</param> /// <param name="zenith">the azimuth below the vertical zenith of 90°;. For sunset /// typically the <see cref="AstronomicalCalculator.AdjustZenith">zenith</see> used for the /// calculation uses geometric zenith of 90°; and /// <see cref="AstronomicalCalculator.AdjustZenith">adjusts</see> this slightly to account for /// solar refraction and the sun's radius. Another example would /// be <see cref="AstronomicalCalendar.GetEndNauticalTwilight"/> that /// passes <see cref="AstronomicalCalendar.NAUTICAL_ZENITH"/> to this /// method.</param> /// <param name="adjustForElevation"></param> /// <returns> /// The UTC time of sunset in 24 hour format. 5:45:00 AM will return /// 5.75.0. If an error was encountered in the calculation (expected /// behavior for some locations such as near the poles, /// <seealso cref="Double.NaN"/> will be returned. /// </returns> public override double GetUtcSunset( IDateWithLocation dateWithLocation, double zenith, bool adjustForElevation) { return(GetUtcSunriseSunset(dateWithLocation, zenith, adjustForElevation, false)); }
///<summary> /// Generate a Julian day from Java Calendar ///</summary> ///<param name = "date"> /// Java Calendar </param> ///<returns> the Julian day corresponding to the date Note: Number is returned /// for start of day. Fractional days should be added later. </returns> private static double CalcJd(IDateWithLocation date) { int year = date.Date.Year; int month = date.Date.Month + 1; int day = date.Date.Day; if (month <= 2) { year -= 1; month += 12; } double A = Math.Floor((double)(year / 100)); double B = 2 - A + Math.Floor(A / 4); return Math.Floor(365.25 * (year + 4716)) + Math.Floor(30.6001 * (month + 1)) + day + B - 1524.5; }
/// <summary> /// A method that calculates UTC sunset as well as any time based on an angle /// above or below sunset. This abstract method is implemented by the classes /// that extend this class. /// </summary> /// <param name="astronomicalCalendar">Used to calculate day of year.</param> /// <param name="zenith">the azimuth below the vertical zenith of 90°;. For sunset /// typically the <see cref="AstronomicalCalculator.AdjustZenith">zenith</see> used for the /// calculation uses geometric zenith of 90°; and /// <see cref="AstronomicalCalculator.AdjustZenith">adjusts</see> this slightly to account for /// solar refraction and the sun's radius. Another example would /// be <see cref="AstronomicalCalendar.GetEndNauticalTwilight"/> that /// passes <see cref="AstronomicalCalendar.NAUTICAL_ZENITH"/> to this /// method.</param> /// <param name="adjustForElevation"></param> /// <returns> /// The UTC time of sunset in 24 hour format. 5:45:00 AM will return /// 5.75.0. If an error was encountered in the calculation (expected /// behavior for some locations such as near the poles, /// <seealso cref="Double.NaN"/> will be returned. /// </returns> public override double GetUtcSunset(IDateWithLocation dateWithLocation, double zenith, bool adjustForElevation) { // zenith = adjustZenithForElevation(astronomicalCalendar, zenith, // geoLocation.getElevation()); // double elevationAdjustment = this.getElevationAdjustment(zenith, // geoLocation.getElevation()); // double refractionAdjustment = this.getRefraction(zenith); // zenith = zenith + elevationAdjustment + refractionAdjustment; if (adjustForElevation) { zenith = AdjustZenith(zenith, dateWithLocation.Location.Elevation); } else { zenith = AdjustZenith(zenith, 0); } // step 1: First calculate the day of the year // int calendarDayOfYear = calelendar.DAY_OF_YEAR; // int N=theday - date(1,1,theday.year()) + 1; int N = dateWithLocation.Date.DayOfYear; // step 2: convert the longitude to hour value and calculate an // approximate time double lngHour = dateWithLocation.Location.Longitude / 15; double t = N + ((18 - lngHour)/24); // step 3: calculate the sun's mean anomaly double M = (0.9856*t) - 3.289; // step 4: calculate the sun's true longitude double L = M + (1.916*Math.Sin(MathExtensions.ToRadians(M))) + (0.020*Math.Sin(MathExtensions.ToRadians(2*M))) + 282.634; while (L < 0) { double Lx = L + 360; L = Lx; } while (L >= 360) { double Lx = L - 360; L = Lx; } // step 5a: calculate the sun's right ascension double RA = MathExtensions.ToDegree(Math.Atan(0.91764*Math.Tan(MathExtensions.ToRadians(L)))); while (RA < 0) { double RAx = RA + 360; RA = RAx; } while (RA >= 360) { double RAx = RA - 360; RA = RAx; } // step 5b: right ascension value needs to be in the same quadrant as L double Lquadrant = Math.Floor(L/90)*90; double RAquadrant = Math.Floor(RA/90)*90; RA = RA + (Lquadrant - RAquadrant); // step 5c: right ascension value needs to be converted into hours RA /= 15; // step 6: calculate the sun's declination double sinDec = 0.39782*Math.Sin(MathExtensions.ToRadians(L)); double cosDec = Math.Cos(Math.Asin(sinDec)); // step 7a: calculate the sun's local hour angle double cosH = (Math.Cos(MathExtensions.ToRadians(zenith)) - (sinDec * Math.Sin(MathExtensions.ToRadians(dateWithLocation.Location.Latitude)))) / (cosDec * Math.Cos(MathExtensions.ToRadians(dateWithLocation.Location.Latitude))); // the following line would throw an Exception if the sun never set. // this is not needed since the calculation will return a Double.NaN // if (cosH < -1) throw new ZmanimException("doesnthappen"); // step 7b: finish calculating H and convert into hours double H = MathExtensions.ToDegree(Math.Acos(cosH)); H = H/15; // step 8: calculate local mean time double T = H + RA - (0.06571*t) - 6.622; // step 9: convert to UTC double UT = T - lngHour; while (UT < 0) { double UTx = UT + 24; UT = UTx; } while (UT >= 24) { double UTx = UT - 24; UT = UTx; } return UT; }