def new_year(cls, gregorian_year): """Return fixed date of Observational (classical) Nisan 1 occurring in Gregorian year, 'gregorian_year'.""" jan1 = GregorianDate.new_year(gregorian_year) equinox = Solar.solar_longitude_after(Astro.SPRING, jan1) sset = JAFFA.universal_from_standard(JAFFA.sunset(ifloor(equinox))) return cls.phasis_on_or_after(ifloor(equinox) - (14 if (equinox < sset) else 13), JAFFA)
def minor_solar_term_on_or_after(cls, fixed_date): """Return moment (in Beijing) of the first Chinese minor solar term (jieqi) on or after fixed date, 'fixed_date'. The minor terms begin when the sun's longitude is an odd multiple of 15 degrees.""" s = Solar.solar_longitude(cls.midnight(fixed_date)) l = mod(30 * iceiling((s - 15) / 30) + 15, 360) return cls.solar_longitude_on_or_after(l, fixed_date)
def major_solar_term_on_or_after(cls, fixed_date): """Return moment (in Beijing) of the first Chinese major solar term (zhongqi) on or after fixed date, 'fixed_date'. The major terms begin when the sun's longitude is a multiple of 30 degrees.""" s = Solar.solar_longitude(cls.midnight(fixed_date)) l = mod(30 * iceiling(s / 30), 360) return cls.solar_longitude_on_or_after(l, fixed_date)
def lunar_latitude(cls, tee): """Return the latitude of moon (in degrees) at moment, tee. Adapted from "Astronomical Algorithms" by Jean Meeus, Willmann_Bell, Inc., 1998.""" c = cls.julian_centuries(tee) cap_L_prime = cls.mean_lunar_longitude(c) cap_D = cls.lunar_elongation(c) cap_M = Solar.solar_anomaly(c) cap_M_prime = cls.lunar_anomaly(c) cap_F = cls.moon_node(c) cap_E = poly(c, [1, mpf(-0.002516), mpf(-0.0000074)]) args_lunar_elongation = \ [0, 0, 0, 2, 2, 2, 2, 0, 2, 0, 2, 2, 2, 2, 2, 2, 2, 0, 4, 0, 0, 0, 1, 0, 0, 0, 1, 0, 4, 4, 0, 4, 2, 2, 2, 2, 0, 2, 2, 2, 2, 4, 2, 2, 0, 2, 1, 1, 0, 2, 1, 2, 0, 4, 4, 1, 4, 1, 4, 2] args_solar_anomaly = \ [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 1, -1, -1, -1, 1, 0, 1, 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 1, 1, 0, -1, -2, 0, 1, 1, 1, 1, 1, 0, -1, 1, 0, -1, 0, 0, 0, -1, -2] args_lunar_anomaly = \ [0, 1, 1, 0, -1, -1, 0, 2, 1, 2, 0, -2, 1, 0, -1, 0, -1, -1, -1, 0, 0, -1, 0, 1, 1, 0, 0, 3, 0, -1, 1, -2, 0, 2, 1, -2, 3, 2, -3, -1, 0, 0, 1, 0, 1, 1, 0, 0, -2, -1, 1, -2, 2, -2, -1, 1, 1, -2, 0, 0] args_moon_node = \ [1, 1, -1, -1, 1, -1, 1, 1, -1, -1, -1, -1, 1, -1, 1, 1, -1, -1, -1, 1, 3, 1, 1, 1, -1, -1, -1, 1, -1, 1, -3, 1, -3, -1, -1, 1, -1, 1, -1, 1, 1, 1, 1, -1, 3, -1, -1, 1, -1, -1, 1, -1, 1, -1, -1, -1, -1, -1, -1, 1] sine_coefficients = \ [5128122, 280602, 277693, 173237, 55413, 46271, 32573, 17198, 9266, 8822, 8216, 4324, 4200, -3359, 2463, 2211, 2065, -1870, 1828, -1794, -1749, -1565, -1491, -1475, -1410, -1344, -1335, 1107, 1021, 833, 777, 671, 607, 596, 491, -451, 439, 422, 421, -366, -351, 331, 315, 302, -283, -229, 223, 223, -220, -220, -185, 181, -177, 176, 166, -164, 132, -119, 115, 107] beta = ((1.0/1000000.0) * sigma([sine_coefficients, args_lunar_elongation, args_solar_anomaly, args_lunar_anomaly, args_moon_node], lambda v, w, x, y, z: (v * pow(cap_E, abs(x)) * sin_degrees((w * cap_D) + (x * cap_M) + (y * cap_M_prime) + (z * cap_F))))) venus = ((175/1000000) * (sin_degrees(mpf(119.75) + c * mpf(131.849) + cap_F) + sin_degrees(mpf(119.75) + c * mpf(131.849) - cap_F))) flat_earth = ((-2235/1000000) * sin_degrees(cap_L_prime) + (127/1000000) * sin_degrees(cap_L_prime - cap_M_prime) + (-115/1000000) * sin_degrees(cap_L_prime + cap_M_prime)) extra = ((382/1000000) * sin_degrees(mpf(313.45) + c * mpf(481266.484))) return beta + venus + flat_earth + extra
def lunar_longitude(cls, tee): """Return longitude of moon (in degrees) at moment tee. Adapted from "Astronomical Algorithms" by Jean Meeus, Willmann_Bell, Inc., 2nd ed., 1998.""" c = cls.julian_centuries(tee) cap_L_prime = cls.mean_lunar_longitude(c) cap_D = cls.lunar_elongation(c) cap_M = Solar.solar_anomaly(c) cap_M_prime = cls.lunar_anomaly(c) cap_F = cls.moon_node(c) # see eq. 47.6 in Meeus cap_E = poly(c, [1, mpf(-0.002516), mpf(-0.0000074)]) args_lunar_elongation = \ [0, 2, 2, 0, 0, 0, 2, 2, 2, 2, 0, 1, 0, 2, 0, 0, 4, 0, 4, 2, 2, 1, 1, 2, 2, 4, 2, 0, 2, 2, 1, 2, 0, 0, 2, 2, 2, 4, 0, 3, 2, 4, 0, 2, 2, 2, 4, 0, 4, 1, 2, 0, 1, 3, 4, 2, 0, 1, 2] args_solar_anomaly = \ [0, 0, 0, 0, 1, 0, 0, -1, 0, -1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 1, 1, 0, 1, -1, 0, 0, 0, 1, 0, -1, 0, -2, 1, 2, -2, 0, 0, -1, 0, 0, 1, -1, 2, 2, 1, -1, 0, 0, -1, 0, 1, 0, 1, 0, 0, -1, 2, 1, 0] args_lunar_anomaly = \ [1, -1, 0, 2, 0, 0, -2, -1, 1, 0, -1, 0, 1, 0, 1, 1, -1, 3, -2, -1, 0, -1, 0, 1, 2, 0, -3, -2, -1, -2, 1, 0, 2, 0, -1, 1, 0, -1, 2, -1, 1, -2, -1, -1, -2, 0, 1, 4, 0, -2, 0, 2, 1, -2, -3, 2, 1, -1, 3] args_moon_node = \ [0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, -2, 2, -2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, -2, 2, 0, 2, 0, 0, 0, 0, 0, 0, -2, 0, 0, 0, 0, -2, -2, 0, 0, 0, 0, 0, 0, 0] sine_coefficients = \ [6288774,1274027,658314,213618,-185116,-114332, 58793,57066,53322,45758,-40923,-34720,-30383, 15327,-12528,10980,10675,10034,8548,-7888, -6766,-5163,4987,4036,3994,3861,3665,-2689, -2602, 2390,-2348,2236,-2120,-2069,2048,-1773, -1595,1215,-1110,-892,-810,759,-713,-700,691, 596,549,537,520,-487,-399,-381,351,-340,330, 327,-323,299,294] correction = ((1.0/1000000.0) * sigma([sine_coefficients, args_lunar_elongation, args_solar_anomaly, args_lunar_anomaly, args_moon_node], lambda v, w, x, y, z: v * pow(cap_E, abs(x)) * sin_degrees((w * cap_D) + (x * cap_M) + (y * cap_M_prime) + (z * cap_F)))) A1 = mpf(119.75) + (c * mpf(131.849)) venus = ((3958/1000000) * sin_degrees(A1)) A2 = mpf(53.09) + c * mpf(479264.29) jupiter = ((318/1000000) * sin_degrees(A2)) flat_earth = ((1962/1000000) * sin_degrees(cap_L_prime - cap_F)) return mod(cap_L_prime + correction + venus + jupiter + flat_earth + cls.nutation(tee), 360)
def sine_offset(self, local_time, alpha): """Return sine of angle between position of sun at local time tee and when its depression is alpha at location, location. Out of range when it does not occur.""" phi = self.latitude tee_prime = self.universal_from_local(local_time) delta = Astro.declination(tee_prime, mpf(0), Solar.solar_longitude(tee_prime)) return ((tan_degrees(phi) * tan_degrees(delta)) + (sin_degrees(alpha) / (cos_degrees(delta) * cos_degrees(phi))))
def lunar_phase(cls, tee): """Return the lunar phase, as an angle in degrees, at moment tee. An angle of 0 means a new moon, 90 degrees means the first quarter, 180 means a full moon, and 270 degrees means the last quarter.""" phi = mod(cls.lunar_longitude(tee) - Solar.solar_longitude(tee), 360) t0 = cls.nth_new_moon(0) n = iround((tee - t0) / cls.MEAN_SYNODIC_MONTH) phi_prime = (360 * mod((tee - cls.nth_new_moon(n)) / cls.MEAN_SYNODIC_MONTH, 1)) if abs(phi - phi_prime) > 180: return phi_prime else: return phi
def new_year_on_or_before(cls, fixed_date): """Return fixed date of Future Bahai New Year on or before fixed date, 'fixed_date'.""" approx = Solar.estimate_prior_solar_longitude(Astro.SPRING, cls.sunset_in_haifa(fixed_date)) return next_int(ifloor(approx) - 1, lambda day: Solar.solar_longitude(cls.sunset_in_haifa(day)) <= Astro.SPRING + 2)
def sidereal_solar_longitude(tee): """Return sidereal solar longitude at moment, tee.""" return mod(Solar.solar_longitude(tee) - Astro.precession(tee) + SIDEREAL_START, 360)
def ayanamsha(tee): """Return the difference between tropical and sidereal solar longitude.""" return Solar.solar_longitude(tee) - sidereal_solar_longitude(tee)
def new_year_on_or_before(cls, date): """Return the fixed date of Astronomical Persian New Year on or before fixed date, date.""" approx = Solar.estimate_prior_solar_longitude(Astro.SPRING, cls.midday_in_tehran(date)) return next_int(ifloor(approx) - 1, lambda day: (Solar.solar_longitude(cls.midday_in_tehran(day)) <= (Astro.SPRING + 2)))
def current_minor_solar_term(cls, fixed_date): """Return last Chinese minor solar term (jieqi) before date, 'fixed_date'.""" s = Solar.solar_longitude(cls.location(fixed_date).universal_from_standard(fixed_date)) return amod(3 + quotient(s - 15, 30), 12)
def major_solar_term(cls, fixed_date): """Return last Chinese major solar term (zhongqi) before fixed date, 'fixed_date'.""" s = Solar.solar_longitude(cls.location(fixed_date).universal_from_standard(fixed_date)) return amod(2 + quotient(int(s), 30), 12)
def solar_longitude_on_or_after(cls, lam, fixed_date): """Return moment (Beijing time) of the first date on or after fixed date, 'fixed_date', (Beijing time) when the solar longitude will be 'lam' degrees.""" tee = Solar.solar_longitude_after(lam, cls.location(fixed_date).universal_from_standard(fixed_date)) return cls.location(tee).standard_from_universal(tee)
def winter_solstice_on_or_before(cls, fixed_date): """Return fixed date, in the Chinese zone, of winter solstice on or before fixed date, 'fixed_date'.""" approx = Solar.estimate_prior_solar_longitude(Astro.WINTER, cls.midnight(fixed_date + 1)) return next_int(ifloor(approx) - 1, lambda day: Astro.WINTER < Solar.solar_longitude(cls.midnight(1 + day)))
def new_year_on_or_before(cls, date): """Return fixed date of French Revolutionary New Year on or before fixed date, date.""" approx = Solar.estimate_prior_solar_longitude(Astro.AUTUMN, cls.midnight_in_paris(date)) return next_int(ifloor(approx) - 1, lambda day: Astro.AUTUMN <= Solar.solar_longitude(cls.midnight_in_paris(day)))