示例#1
0
def obliquity(tee):
    """Return (mean) obliquity of ecliptic at moment tee."""
    c = julian_centuries(tee)
    return (angle(23, 26, mpf(21.448)) + poly(c, [
        mpf(0),
        angle(0, 0, mpf(-46.8150)),
        angle(0, 0, mpf(-0.00059)),
        angle(0, 0, mpf(0.001813))
    ]))
示例#2
0
 def location(cls, tee):
     """Return location of Beijing; time zone varies with time, tee."""
     year = GregorianDate.to_year(int(math.floor(tee)))
     if (year < 1929):
         return Location(angle(39, 55, 0), angle(116, 25, 0), 43.5,
                         Clock.days_from_hours(1397 / 180))
     else:
         return Location(angle(39, 55, 0), angle(116, 25, 0), 43.5,
                         Clock.days_from_hours(8))
示例#3
0
def vietnamese_location(tee):
    """Return the location for Vietnamese calendar is Hanoi;
    varies with moment, tee. Time zone has changed over the years."""
    if (tee < GregorianDate.new_year(1968)):
        z = 8
    else:
        z = 7
    return Location(angle(21, 2, 0), angle(105, 51, 0), 12,
                    Clock.days_from_hours(z))
示例#4
0
def korean_location(tee):
    """Return the location for Korean calendar; varies with moment, tee."""
    # Seoul city hall at a varying time zone.
    if (tee < GregorianDate(1908, MonthOfYear.APRIL, 1).toordinal()):
        #local mean time for longitude 126 deg 58 min
        z = 3809 / 450
    elif (tee < GregorianDate(1912, MonthOfYear.JANUARY, 1).toordinal()):
        z = 8.5
    elif (tee < GregorianDate(1954, MonthOfYear.MARCH, 21).toordinal()):
        z = 9
    elif (tee < GregorianDate(1961, MonthOfYear.AUGUST, 10).toordinal()):
        z = 8.5
    else:
        z = 9
    return Location(angle(37, 34, 0), angle(126, 58, 0), 0,
                    Clock.days_from_hours(z))
示例#5
0
 def equation_of_time(cls, date):
     """Return the time from true to mean midnight of date, date."""
     offset = cls.sine(cls.mean_position(date, cls.ANOMALISTIC_YEAR))
     equation_sun = (offset * angle(57, 18, 0) * (14 / 360 -
                                                  (abs(offset) / 1080)))
     return ((cls.daily_motion(date) / 360) * (equation_sun / 360) *
             cls.SIDEREAL_YEAR)
示例#6
0
 def daily_motion(cls, date):
     """Return the sidereal daily motion of sun on date, date."""
     mean_motion = 360 / cls.SIDEREAL_YEAR
     anomaly = cls.mean_position(date, cls.ANOMALISTIC_YEAR)
     epicycle = 14 / 360 - abs(cls.sine(anomaly)) / 1080
     entry = int(math.floor(float(anomaly), angle(0, 225, 0)))
     sine_table_step = cls.sine_table(entry + 1) - cls.sine_table(entry)
     factor = -3438 / 225 * sine_table_step * epicycle
     return mean_motion * (factor + 1)
示例#7
0
 def arcsin(cls, amp):
     """Return the inverse of Hindu sine function of amp."""
     if (amp < 0):
         return -cls.arcsin(-amp)
     else:
         pos = next_int(0, lambda k: amp <= cls.sine_table(k))
         below = cls.sine_table(pos - 1)
         return (angle(0, 225, 0) * (pos - 1 +
                                     ((amp - below) /
                                      (cls.sine_table(pos) - below))))
示例#8
0
def japanese_location(tee):
    """Return the location for Japanese calendar; varies with moment, tee."""
    year = GregorianDate.to_year(int(math.floor(tee)))
    if (year < 1888):
        # Tokyo (139 deg 46 min east) local time
        loc = Location(mpf(35.7), angle(139, 46, 0), 24,
                       Clock.days_from_hours(9 + 143 / 450))
    else:
        # Longitude 135 time zone
        loc = Location(35, 135, 0, Clock.days_from_hours(9))
    return loc
示例#9
0
 def sine(cls, theta):
     """Return the linear interpolation for angle, theta, in Hindu table."""
     entry = theta / angle(0, 225, 0)
     fraction = entry % 1
     return ((fraction * cls.sine_table(int(math.ceil(entry)))) +
             ((1 - fraction) * cls.sine_table(int(math.floor(entry)))))
示例#10
0
 def sine_table(cls, entry):
     """Return the value for entry in the Hindu sine table.
     Entry, entry, is an angle given as a multiplier of 225'."""
     exact = 3438 * sin_degrees(entry * angle(0, 225, 0))
     error = 0.215 * signum(exact) * signum(abs(exact) - 1716)
     return int(round(exact + error)) / 3438
示例#11
0
class HinduDate(object):

    SIDEREAL_YEAR = 365 + 279457 / 1080000
    ANOMALISTIC_YEAR = 1577917828000 / (4320000000 - 387)
    CREATION = OldHindu.EPOCH - 1955880000 * SIDEREAL_YEAR
    UJJAIN = Location(angle(23, 9, 0), angle(75, 46, 6), 0,
                      Clock.days_from_hours(5 + 461 / 9000))
    LOCATION = UJJAIN

    def __init__(self, year, month, leap_month, day, leap_day):
        self.year = year
        self.month = month
        self.leap_month = leap_month
        self.day = day
        self.leap_day = leap_day

    def to_tuple(self):
        return (self.year, self.month, self.leap_month, self.day,
                self.leap_day)

    def __eq__(self, other):
        return isinstance(other, HinduDate) and all(
            map(lambda (x, y): x == y, zip(self.to_tuple(), other.to_tuple())))

    def __ne__(self, other):
        return not self.__eq__(other)

    def __lt__(self, other):
        return isinstance(other, HinduDate) and reduce_cond(
            lambda _, (x, y): x < y, lambda r, (x, y): not r and x == y,
            zip(self.to_tuple(), other.to_tuple()), False)

    def __le__(self, other):
        return isinstance(other, HinduDate) and reduce_cond(
            lambda _, (x, y): x <= y, lambda r, (x, y): not r and x == y,
            zip(self.to_tuple(), other.to_tuple()), False)

    def __gt__(self, other):
        return isinstance(other, HinduDate) and reduce_cond(
            lambda _, (x, y): x > y, lambda r, (x, y): not r and x == y,
            zip(self.to_tuple(), other.to_tuple()), False)

    def __ge__(self, other):
        return isinstance(other, HinduDate) and reduce_cond(
            lambda _, (x, y): x >= y, lambda r, (x, y): not r and x == y,
            zip(self.to_tuple(), other.to_tuple()), False)

    @classmethod
    def sine_table(cls, entry):
        """Return the value for entry in the Hindu sine table.
        Entry, entry, is an angle given as a multiplier of 225'."""
        exact = 3438 * sin_degrees(entry * angle(0, 225, 0))
        error = 0.215 * signum(exact) * signum(abs(exact) - 1716)
        return int(round(exact + error)) / 3438

    @classmethod
    def sine(cls, theta):
        """Return the linear interpolation for angle, theta, in Hindu table."""
        entry = theta / angle(0, 225, 0)
        fraction = entry % 1
        return ((fraction * cls.sine_table(int(math.ceil(entry)))) +
                ((1 - fraction) * cls.sine_table(int(math.floor(entry)))))

    @classmethod
    def arcsin(cls, amp):
        """Return the inverse of Hindu sine function of amp."""
        if (amp < 0):
            return -cls.arcsin(-amp)
        else:
            pos = next_int(0, lambda k: amp <= cls.sine_table(k))
            below = cls.sine_table(pos - 1)
            return (angle(0, 225, 0) * (pos - 1 +
                                        ((amp - below) /
                                         (cls.sine_table(pos) - below))))

    @classmethod
    def mean_position(cls, tee, period):
        """Return the position in degrees at moment, tee, in uniform circular
        orbit of period days."""
        return 360 * (((tee - cls.CREATION) / period) % 1)

    @classmethod
    def true_position(cls, tee, period, size, anomalistic, change):
        """Return the longitudinal position at moment, tee.
        period is the period of mean motion in days.
        size is ratio of radii of epicycle and deferent.
        anomalistic is the period of retrograde revolution about epicycle.
        change is maximum decrease in epicycle size."""
        lam = cls.mean_position(tee, period)
        offset = cls.sine(cls.mean_position(tee, anomalistic))
        contraction = abs(offset) * change * size
        equation = cls.arcsin(offset * (size - contraction))
        return (lam - equation) % 360

    @classmethod
    def solar_longitude(cls, tee):
        """Return the solar longitude at moment, tee."""
        return cls.true_position(tee, cls.SIDEREAL_YEAR, 14 / 360,
                                 cls.ANOMALISTIC_YEAR, 1 / 42)

    @classmethod
    def zodiac(cls, tee):
        """Return the zodiacal sign of the sun, as integer in range 1..12,
        at moment tee."""
        return int(math.floor(float(cls.solar_longitude(tee)), 30)) + 1

    @classmethod
    def equation_of_time(cls, date):
        """Return the time from true to mean midnight of date, date."""
        offset = cls.sine(cls.mean_position(date, cls.ANOMALISTIC_YEAR))
        equation_sun = (offset * angle(57, 18, 0) * (14 / 360 -
                                                     (abs(offset) / 1080)))
        return ((cls.daily_motion(date) / 360) * (equation_sun / 360) *
                cls.SIDEREAL_YEAR)

    @classmethod
    def ascensional_difference(cls, date, location):
        """Return the difference between right and oblique ascension
        of sun on date, date, at loacel, location."""
        sin_delta = (1397 / 3438) * cls.sine(cls.tropical_longitude(date))
        phi = location.latitude
        diurnal_radius = cls.sine(90 + cls.arcsin(sin_delta))
        tan_phi = cls.sine(phi) / cls.sine(90 + phi)
        earth_sine = sin_delta * tan_phi
        return cls.arcsin(-earth_sine / diurnal_radius)

    @classmethod
    def daily_motion(cls, date):
        """Return the sidereal daily motion of sun on date, date."""
        mean_motion = 360 / cls.SIDEREAL_YEAR
        anomaly = cls.mean_position(date, cls.ANOMALISTIC_YEAR)
        epicycle = 14 / 360 - abs(cls.sine(anomaly)) / 1080
        entry = int(math.floor(float(anomaly), angle(0, 225, 0)))
        sine_table_step = cls.sine_table(entry + 1) - cls.sine_table(entry)
        factor = -3438 / 225 * sine_table_step * epicycle
        return mean_motion * (factor + 1)

    @classmethod
    def solar_sidereal_difference(cls, date):
        """Return the difference between solar and sidereal day on date, date."""
        return cls.daily_motion(date) * cls.rising_sign(date)

    @classmethod
    def sunrise(cls, date):
        """Return the sunrise at hindu_location on date, date."""
        return (date + Clock.days_from_hours(6) +
                ((cls.UJJAIN.longitude - cls.LOCATION.longitude) / 360) -
                cls.equation_of_time(date) +
                ((1577917828 / 1582237828 / 360) *
                 (cls.ascensional_difference(date, cls.LOCATION) +
                  (1 / 4 * cls.solar_sidereal_difference(date)))))

    @classmethod
    def sunset(cls, date):
        """Return sunset at HINDU_LOCATION on date, date."""
        return (date + Clock.days_from_hours(18) +
                ((cls.UJJAIN.longitude - cls.LOCATION.longitude) / 360) -
                cls.equation_of_time(date) +
                (((1577917828 / 1582237828) / 360) *
                 (-cls.ascensional_difference(date, cls.LOCATION) +
                  (3 / 4 * cls.solar_sidereal_difference(date)))))

    @classmethod
    def alt_sunrise(cls, date):
        """Return the astronomical sunrise at Hindu location on date, date,
        per Lahiri, rounded to nearest minute, as a rational number."""
        rise = cls.UJJAIN.dawn(date, angle(0, 47, 0))
        return 1 / 24 * 1 / 60 * int(round(rise * 24 * 60))
示例#12
0
 def refraction(self, tee):
     """Return refraction angle at location 'location' and time 'tee'."""
     h     = max(0, self.elevation)
     cap_R = 6.372E6
     dip   = arccos_degrees(cap_R / (cap_R + h))
     return angle(0, 50, 0) + dip + secs(19) * math.sqrt(h)
示例#13
0
def hindu_lunar_station(date):
    """Return the Hindu lunar station (nakshatra) at sunrise on date, date."""
    critical = HinduDate.sunrise(date)
    return int(
        math.floor(HinduLunarDate.longitude(critical) / angle(0, 800, 0))) + 1
示例#14
0
def precise_obliquity(tee):
    """Return precise (mean) obliquity of ecliptic at moment tee."""
    u = julian_centuries(tee) / 100
    #assert(abs(u) < 1,
    #       'Error! This formula is valid for +/-10000 years around J2000.0')
    return (poly(u, [
        angle(23, 26, mpf(21.448)),
        angle(0, 0, mpf(-4680.93)),
        angle(0, 0, mpf(-1.55)),
        angle(0, 0, mpf(+1999.25)),
        angle(0, 0, mpf(-51.38)),
        angle(0, 0, mpf(-249.67)),
        angle(0, 0, mpf(-39.05)),
        angle(0, 0, mpf(+7.12)),
        angle(0, 0, mpf(+27.87)),
        angle(0, 0, mpf(+5.79)),
        angle(0, 0, mpf(+2.45))
    ]))
示例#15
0
class FrenchDate(YearMonthDay):

    #"""Date of start of the French Revolutionary calendar."""
    EPOCH = GregorianDate(1792, MonthOfYear.SEPTEMBER, 22).toordinal()
    PARIS = Location(angle(48, 50, 11), angle(2, 20, 15), 27, Clock.days_from_hours(1))
    
    def __init__(self, year, month, day):
        super().__init__(year, month, day)

    def toordinal(self):
        """Return ordinal date of French Revolutionary date, f_date"""
        new_year = self.new_year_on_or_before(ifloor(self.EPOCH + 180 + MEAN_TROPICAL_YEAR * (self.year - 1)))
        return new_year - 1 + 30 * (self.month - 1) + self.day

    @classmethod
    def fromordinal(cls, ordinal):
        """Return French Revolutionary date of ordinal date, 'ordinal'."""
        new_year = cls.new_year_on_or_before(ordinal)
        year  = iround((new_year - cls.EPOCH) / MEAN_TROPICAL_YEAR) + 1
        month = quotient(ordinal - new_year, 30) + 1
        day   = ((ordinal - new_year) % 30) + 1
        return FrenchDate(year, month, day)

    @classmethod        
    def midnight_in_paris(cls, ordinal):
        """Return Universal Time of true midnight at the end of
           ordinal date, ordinal."""
        # tricky bug: I was using midDAY!!! So French Revolutionary was failing...
        return cls.PARIS.universal_from_standard(cls.PARIS.midnight(ordinal + 1))

    @classmethod    
    def new_year_on_or_before(cls, ordinal):
        """Return ordinal date of French Revolutionary New Year on or
           before ordinal, ordinal."""
        approx = estimate_prior_solar_longitude(Season.AUTUMN, cls.midnight_in_paris(ordinal))
        return next_int(ifloor(approx) - 1, lambda day: Season.AUTUMN <= solar_longitude(cls.midnight_in_paris(day)))
    
    @classmethod
    def is_arithmetic_leap_year(cls, f_year):
        """Return True if year, f_year, is a leap year on the French
           Revolutionary calendar."""
        return f_year % 4 == 0 and f_year % 400 not in [100, 200, 300] and f_year % 4000 != 0
    
    def toordinal_arithmetic(self):
        """Return ordinal date of French Revolutionary date, f_date."""
        return (self.EPOCH - 1         +
                365 * (self.year - 1)         +
                quotient(self.year - 1, 4)    -
                quotient(self.year - 1, 100)  +
                quotient(self.year - 1, 400)  -
                quotient(self.year - 1, 4000) +
                30 * (self.month - 1)         +
                self.day)

    @classmethod    
    def fromordinal_arithmetic(cls, ordinal):
        """Return French Revolutionary date [year, month, day] of ordinal
           ordinal, ordinal."""
        approx = quotient(ordinal - cls.EPOCH + 2, 1460969/4000) + 1
        year   = ((approx - 1)
                  if (ordinal < FrenchDate(approx, 1, 1).toordinal_arithmetic())
                  else approx)
        month  = 1 + quotient(ordinal - FrenchDate(year, 1, 1).toordinal_arithmetic(), 30)
        day    = ordinal -  FrenchDate(year, month, 1).toordinal_arithmetic() + 1
        return FrenchDate(year, month, day)
def jewish_dusk(date, location):
    """Return standard time of Jewish dusk on fixed date, date,
    at location, location, (as per Vilna Gaon)."""
    return location.dusk(date, angle(4, 40, 0))
def jewish_sabbath_ends(date, location):
    """Return standard time of end of Jewish sabbath on fixed date, date,
    at location, location, (as per Berthold Cohn)."""
    return location.dusk(date, angle(7, 5, 0))
示例#18
0
 def alt_sunrise(cls, date):
     """Return the astronomical sunrise at Hindu location on date, date,
     per Lahiri, rounded to nearest minute, as a rational number."""
     rise = cls.UJJAIN.dawn(date, angle(0, 47, 0))
     return 1 / 24 * 1 / 60 * int(round(rise * 24 * 60))
示例#19
0
        at location, location, as a small positive/negative angle in degrees,
        ignoring parallax and refraction.  Adapted from 'Astronomical
        Algorithms' by Jean Meeus, Willmann_Bell, Inc., 1998."""
        lamb = lunar_longitude(tee)
        beta = lunar_latitude(tee)
        alpha =right_ascension(tee, beta, lamb)
        delta = declination(tee, beta, lamb)
        theta0 = sidereal_from_moment(tee)
        cap_H = mod(theta0 + self.longitude - alpha, 360)
        altitude = arcsin_degrees(
            (sin_degrees(self.latitude) * sin_degrees(delta)) +
            (cos_degrees(self.latitude) * cos_degrees(delta) * cos_degrees(cap_H)))
        return mod(altitude + 180, 360) - 180

    def visible_crescent(self, date):
        """Return S. K. Shaukat's criterion for likely
        visibility of crescent moon on eve of date 'date',
        at location 'location'."""
        tee = self.universal_from_standard(self.dusk(date - 1, mpf(4.5)))
        phase = lunar_phase(tee)
        altitude = self.lunar_altitude(tee)
        arc_of_light = arccos_degrees(cos_degrees(lunar_latitude(tee)) * cos_degrees(phase))
        return ((MoonPhase.NEW < phase < MoonPhase.FIRST_QUARTER) and
                (mpf(10.6) <= arc_of_light <= 90) and
                (altitude > mpf(4.1)))

MECCA = Location(angle(21, 25, 24), angle(39, 49, 24), 298, Clock.days_from_hours(3))
JERUSALEM = Location(31.8, 35.2, 800, Clock.days_from_hours(2))
BRUXELLES = Location(angle(4, 21, 17), angle(50, 50, 47), 800, Clock.days_from_hours(1))
URBANA = Location(40.1, -88.2, 225, Clock.days_from_hours(-6))
GREENWHICH = Location(51.4777815, 0, 46.9, Clock.days_from_hours(0))
示例#20
0
def yoga(date):
    """Return the Hindu yoga on date, date."""
    return int(
        math.floor(((
            (HinduSolarDate.longitude(date) + HinduLunarDate.longitude(date)) /
            angle(0, 800, 0)) % 27))) + 1
示例#21
0
        elif month == HebrewMonth.KISLEV and day < 30:
            extra = [DayOfWeek.MONDAY, DayOfWeek.WEDNESDAY, DayOfWeek.FRIDAY]
        elif month == HebrewMonth.KISLEV and day == 30:
            extra = [DayOfWeek.MONDAY]
        elif month in [HebrewMonth.TEVET, HebrewMonth.SHEVAT]:
            extra = [DayOfWeek.SUNDAY, DayOfWeek.MONDAY]
        elif month == HebrewMonth.ADAR and day < 30:
            extra = [DayOfWeek.SUNDAY, DayOfWeek.MONDAY]
        else:
            extra = [DayOfWeek.SUNDAY]

        basic.extend(extra)
        return map(lambda x: weekday_fromordinal(x + n), basic)


JAFFA = Location(angle(32, 1, 60), angle(34, 45, 0), 0,
                 Clock.days_from_hours(2))


class HebrewObservationalDate(YearMonthDay):
    def __init__(self, year, month, day):
        YearMonthDay.__init__(self, year, month, day)

    def toordinal(self):
        """Return ordinal date equivalent to Observational Hebrew date."""
        year1 = self.year - 1 if self.month >= HebrewMonth.TISHRI else self.year
        start = HebrewDate(year1, HebrewMonth.NISAN, 1).toordinal()
        g_year = GregorianDate.to_year(start + 60)
        new_year = self.new_year(g_year)
        midmonth = new_year + int(round(29.5 * (self.month - 1))) + 15
        return JAFFA.phasis_on_or_before(midmonth) + self.day - 1