/// <summary> /// Calculate 24 solar terms. /// </summary> /// <param name="year">Year.</param> /// <param name="term">Solar term.</param> /// <param name="localTimeZone">Local time zone.</param> /// <returns>The <see cref="DateTime"/> of solar term.</returns> /// <remarks> /// If you want to calculate the equinox and solstice, please use the method <see cref="GetEquinoxAndSolstice"/>. /// </remarks> public DateTime GetSolarTerms(int year, SolarTerm term, TimeZoneInfo localTimeZone) { // Estimate iteration start time interval EstimateSTtimeScope(year, term, out double lJD, out double rJD); double solarTermsJD = 0.0; double longitude = 0.0; DateTime solarTermsTime = new DateTime(); do { solarTermsJD = ((rJD - lJD) * 0.618) + lJD; solarTermsTime = Julian.ToCalendarDay(solarTermsJD); longitude = CoordinateSystem.Equator2Ecliptic(GetEquatorCoordinate(solarTermsTime, true), solarTermsTime, true).Longitude; // In the iterative approximation of 0 degree of ecliptic longitude, the estimated value of ecliptic longitude may be in the interval of (345,360] and [0,15) due to the 360 degree circularity of the angle. If the value falls into the previous interval, it needs to be corrected. longitude = ((term == 0) && (longitude > 345.0)) ? longitude - 360.0 : longitude; if (longitude > (int)term) { rJD = solarTermsJD; } else { lJD = solarTermsJD; } } while ((rJD - lJD) > 0.0001); // Min +2 correction return(TimeZoneInfo.ConvertTime(solarTermsTime.AddMinutes(2), TimeZoneInfo.Utc, localTimeZone)); }
internal void EstimateSTtimeScope(int year, SolarTerm term, out double lJD, out double rJD) { switch (term) { case SolarTerm.BeginningOfSpring: lJD = Julian.ToJulianDay(new DateTime(year, 2, 4)); rJD = Julian.ToJulianDay(new DateTime(year, 2, 9)); break; case SolarTerm.RainWater: lJD = Julian.ToJulianDay(new DateTime(year, 2, 16)); rJD = Julian.ToJulianDay(new DateTime(year, 2, 24)); break; case SolarTerm.WakingOfInsects: lJD = Julian.ToJulianDay(new DateTime(year, 3, 4)); rJD = Julian.ToJulianDay(new DateTime(year, 3, 9)); break; case SolarTerm.SpringEquinox: lJD = Julian.ToJulianDay(new DateTime(year, 3, 16)); rJD = Julian.ToJulianDay(new DateTime(year, 3, 24)); break; case SolarTerm.PureBrightness: lJD = Julian.ToJulianDay(new DateTime(year, 4, 4)); rJD = Julian.ToJulianDay(new DateTime(year, 4, 9)); break; case SolarTerm.GrainRain: lJD = Julian.ToJulianDay(new DateTime(year, 4, 16)); rJD = Julian.ToJulianDay(new DateTime(year, 4, 24)); break; case SolarTerm.BeginningOfSummer: lJD = Julian.ToJulianDay(new DateTime(year, 5, 4)); rJD = Julian.ToJulianDay(new DateTime(year, 5, 9)); break; case SolarTerm.LesserFullness: lJD = Julian.ToJulianDay(new DateTime(year, 5, 16)); rJD = Julian.ToJulianDay(new DateTime(year, 5, 24)); break; case SolarTerm.GrainInEar: lJD = Julian.ToJulianDay(new DateTime(year, 6, 4)); rJD = Julian.ToJulianDay(new DateTime(year, 6, 9)); break; case SolarTerm.SummerSolstice: lJD = Julian.ToJulianDay(new DateTime(year, 6, 16)); rJD = Julian.ToJulianDay(new DateTime(year, 6, 24)); break; case SolarTerm.LesserHeat: lJD = Julian.ToJulianDay(new DateTime(year, 7, 4)); rJD = Julian.ToJulianDay(new DateTime(year, 7, 9)); break; case SolarTerm.GreaterHeat: lJD = Julian.ToJulianDay(new DateTime(year, 7, 16)); rJD = Julian.ToJulianDay(new DateTime(year, 7, 24)); break; case SolarTerm.BeginningOfAutumn: lJD = Julian.ToJulianDay(new DateTime(year, 8, 4)); rJD = Julian.ToJulianDay(new DateTime(year, 8, 9)); break; case SolarTerm.EndOfHeat: lJD = Julian.ToJulianDay(new DateTime(year, 8, 16)); rJD = Julian.ToJulianDay(new DateTime(year, 8, 24)); break; case SolarTerm.WhiteDew: lJD = Julian.ToJulianDay(new DateTime(year, 9, 4)); rJD = Julian.ToJulianDay(new DateTime(year, 9, 9)); break; case SolarTerm.AutumnalEquinox: lJD = Julian.ToJulianDay(new DateTime(year, 9, 16)); rJD = Julian.ToJulianDay(new DateTime(year, 9, 24)); break; case SolarTerm.ColdDew: lJD = Julian.ToJulianDay(new DateTime(year, 10, 4)); rJD = Julian.ToJulianDay(new DateTime(year, 10, 9)); break; case SolarTerm.FirstFrost: lJD = Julian.ToJulianDay(new DateTime(year, 10, 16)); rJD = Julian.ToJulianDay(new DateTime(year, 10, 24)); break; case SolarTerm.BeginningOfWinter: lJD = Julian.ToJulianDay(new DateTime(year, 11, 4)); rJD = Julian.ToJulianDay(new DateTime(year, 11, 9)); break; case SolarTerm.LesserSnow: lJD = Julian.ToJulianDay(new DateTime(year, 11, 16)); rJD = Julian.ToJulianDay(new DateTime(year, 11, 24)); break; case SolarTerm.GreaterSnow: lJD = Julian.ToJulianDay(new DateTime(year, 12, 4)); rJD = Julian.ToJulianDay(new DateTime(year, 12, 9)); break; case SolarTerm.WinterSolstice: lJD = Julian.ToJulianDay(new DateTime(year, 12, 16)); rJD = Julian.ToJulianDay(new DateTime(year, 12, 24)); break; case SolarTerm.LesserCold: lJD = Julian.ToJulianDay(new DateTime(year, 1, 4)); rJD = Julian.ToJulianDay(new DateTime(year, 1, 9)); break; case SolarTerm.GreaterCold: lJD = Julian.ToJulianDay(new DateTime(year, 1, 16)); rJD = Julian.ToJulianDay(new DateTime(year, 1, 24)); break; default: lJD = 0; rJD = 0; break; } }
/// <summary> /// Elément de syntax pour définir une date solaire. /// </summary> /// <param name="value">Terme solaire.</param> /// <returns>L'élément de syntax <see cref="Composition.SolarDate"/> pour ajouter d'autres comportements.</returns> public SolarDate SolarDate(SolarTerm value) => new SolarDate(this, value);
/// <summary> /// Initialise une nouvelle instance de la classe <see cref="LunarDate"/>. /// </summary> /// <param name="parent">Elément de syntax parent.</param> /// <param name="value">Terme solaire.</param> public SolarDate(ExpressionElement parent, SolarTerm value) : base(parent) => Value = value;