def toordinal(self):
     """Return the ordinal date of this Hindu lunar date."""
     approx = OldHindu.EPOCH + (self.SIDEREAL_YEAR *
                                (self.year + self.LUNAR_ERA +
                                 ((self.month - 1) / 12)))
     s = int(
         math.floor(approx -
                    ((1 / 360) * self.SIDEREAL_YEAR *
                     ((self.hindu_solar_longitude(approx) -
                       ((self.month - 1) * 30) + 180) % 360) - 180)))
     k = self.lunar_day_from_moment(s + Clock.days_from_hours(6))
     if (3 < k < 27):
         temp = k
     else:
         mid = self.lunar_fromordinal(s - 15)
         if ((mid.month != self.month)
                 or (mid.leap_month and not self.leap_month)):
             temp = ((k + 15) % 30) - 15
         else:
             temp = ((k - 15) % 30) + 15
     est = s + self.day - temp
     tau = est - (
         (self.lunar_day_from_moment(est + Clock.days_from_hours(6)) -
          self.day + 15) % 30) + 15
     date = next_int(
         tau - 1, lambda d: self.lunar_day_from_moment(self.sunrise(d)) in
         [self.day, amod(self.day + 1, 30)])
     return date + 1 if self.leap_day else date
 def toordinal(self):
     """Return the ordinal date corresponding to Hindu lunar date, l_date."""
     approx = (OldHindu.EPOCH + self.MEAN_SIDEREAL_YEAR *
               (self.year + self.LUNAR_ERA + ((self.month - 1) / 12)))
     s = int(
         math.floor(approx - 1 / 360 * self.MEAN_SIDEREAL_YEAR *
                    (((sidereal_solar_longitude(approx) -
                       (self.month - 1) * 30 + 180) % 360) - 180)))
     k = self.day_from_moment(s + Clock.days_from_hours(6))
     if (3 < k < 27):
         temp = k
     else:
         mid = self.fromordinal(s - 15)
         if ((mid.month != self.month)
                 or (mid.leap_month and not self.leap_month)):
             temp = ((k + 15) % 30) - 15
         else:
             temp = ((k - 15) % 30) + 15
     est = s + self.day - temp
     tau = est - ((self.day_from_moment(est + Clock.days_from_hours(6)) -
                   self.day + 15) % 30) + 15
     date = next_int(
         tau - 1, lambda d: (self.day_from_moment(self.alt_sunrise(d)) in
                             [self.day, amod(self.day + 1, 30)]))
     return (date + 1) if self.leap_day else date
 def approx_moment_of_depression(self, tee, alpha, early):
     """Return the moment in local time near tee when depression angle
     of sun is alpha (negative if above horizon) at location;
     early is true when MORNING event is sought and false for EVENING.
     Raise VlueError if depression angle is not reached."""
     ttry  = self.sine_offset(tee, alpha)
     date = Clock.ordinal_from_moment(tee)
 
     if alpha >= 0:
         if early:
             alt = date
         else:
             alt = date + 1
     else:
         alt = date + Clock.days_from_hours(12)
 
     if abs(ttry) > 1:
         value = self.sine_offset(alt, alpha)
     else:
         value = ttry
 
     if abs(value) <= 1:
         temp = -1 if early else 1
         temp *= mod(Clock.days_from_hours(12) + arcsin_degrees(value) / 360, 1) - Clock.days_from_hours(6)
         temp += date + Clock.days_from_hours(12)
         return self.local_from_apparent(temp)
     else:
         raise ValueError("Depression angle not reached")
Exemple #4
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))
 def testUniversalFromDynamical(self):
     date = GregorianDate(1977, MonthOfYear.FEBRUARY, 18)
     time = Clock(3, 37, 40).to_time()
     td = date.toordinal() + time
     utc = universal_from_dynamical(td)
     clk = Clock.from_moment(utc)
     self.assertEqual(clk.hour, 3)
     self.assertEqual(clk.minute, 36)
     self.assertEqual(int(round(clk.second)), 52)
Exemple #6
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
Exemple #7
0
def equation_of_time(tee):
    """Return the equation of time (as fraction of day) for moment, tee.
    Adapted from "Astronomical Algorithms" by Jean Meeus,
    Willmann_Bell, Inc., 1991."""
    c = julian_centuries(tee)
    lamb = poly(c, [mpf(280.46645), mpf(36000.76983), mpf(0.0003032)])
    anomaly = poly(
        c,
        [mpf(357.52910),
         mpf(35999.05030),
         mpf(-0.0001559),
         mpf(-0.00000048)])
    eccentricity = poly(
        c, [mpf(0.016708617),
            mpf(-0.000042037),
            mpf(-0.0000001236)])
    varepsilon = obliquity(tee)
    y = pow(tan_degrees(varepsilon / 2), 2)
    equation = (
        (1 / 2 / pi) *
        (y * sin_degrees(2 * lamb) + -2 * eccentricity * sin_degrees(anomaly) +
         (4 * eccentricity * y * sin_degrees(anomaly) * cos_degrees(2 * lamb))
         + -0.5 * y * y * sin_degrees(4 * lamb) +
         -1.25 * eccentricity * eccentricity * sin_degrees(2 * anomaly)))
    return signum(equation) * min(abs(equation), Clock.days_from_hours(
        mpf(12)))
Exemple #8
0
class BahaiDate(object):

    EPOCH = GregorianDate(1844, MonthOfYear.MARCH, 21).toordinal()
    HAIFA = Location(mpf(32.82), 35, 0, Clock.days_from_hours(2))
    AYYAM_I_HA = 0

    def __init__(self, major, cycle, year, month, day):
        self.major = major
        self.cycle = cycle
        self.year = year
        self.month = month
        self.day = day

    def to_tuple(self):
        return (self.major, self.cycle, self.year, self.month, self.day)

    def toordinal(self):
        raise NotImplementedError()

    @classmethod
    def fromordinal(cls, ordinal):
        raise NotImplementedError()

    @classmethod
    def new_year(cls, gregorian_year):
        """Return ordinal date of Bahai New Year in Gregorian year, 'gregorian_year'."""
        return GregorianDate(gregorian_year, MonthOfYear.MARCH, 21).toordinal()

    @classmethod
    def sunset_in_haifa(cls, ordinal):
        """Return universal time of sunset of evening
        before ordinal date in Haifa."""
        return cls.HAIFA.universal_from_standard(cls.HAIFA.sunset(ordinal))

    def __eq__(self, other):
        return isinstance(other, BahaiDate) 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, BahaiDate) 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, BahaiDate) 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, BahaiDate) 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, BahaiDate) 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)
class ObservationalIslamicDate(IslamicDate):

    # (Cairo, Egypt).
    LOCATION = Location(mpf(30.1), mpf(31.3), 200, Clock.days_from_hours(2))

    def __init__(self, year, month, day):
        IslamicDate.__init__(self, year, month, day)

    def toordinal(self):
        """Return ordinal date equivalent to Observational Islamic date, i_date."""
        midmonth = self.EPOCH + int(
            math.floor((((self.year - 1) * 12) + self.month - 0.5) *
                       MEAN_SYNODIC_MONTH))
        return (self.LOCATION.phasis_on_or_before(midmonth) + self.day - 1)

    @classmethod
    def fromordinal(cls, ordinal):
        """Return Observational Islamic date (year month day)
        corresponding to ordinal date, 'ordinal'."""
        crescent = cls.LOCATION.phasis_on_or_before(ordinal)
        elapsed_months = int(round(
            (crescent - cls.EPOCH) / MEAN_SYNODIC_MONTH))
        year = int(math.floor(elapsed_months / 12)) + 1
        month = (elapsed_months % 12) + 1
        day = (ordinal - crescent) + 1
        return ObservationalIslamicDate(year, month, day)
Exemple #10
0
 def molad(cls, month, year):
     """Return moment of mean conjunction of month in Hebrew year."""
     y = year + 1 if month < HebrewMonth.TISHRI else year
     months_elapsed = month - HebrewMonth.TISHRI + int(
         math.floor((235 * y - 234) / 19))
     return cls.EPOCH - Fraction(876, 25920) + months_elapsed * (
         29 + Clock.days_from_hours(12) + Fraction(793, 25920))
 def fromordinal(cls, ordinal):
     """Return Old Hindu solar date equivalent to ordinal date ordinal."""
     sun = cls.hindu_day_count(ordinal) + Clock.days_from_hours(6)
     year = int(math.floor(sun / cls.ARYA_SOLAR_YEAR))
     month = (int(math.floor(sun / cls.ARYA_SOLAR_MONTH)) % 12) + 1
     day = int(math.floor(sun % cls.ARYA_SOLAR_MONTH)) + 1
     return OldHinduSolarDate(year, month, day)
 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)))))
 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)))))
    def testDynamicalFromUniversal(self):
        date = GregorianDate(1977, MonthOfYear.FEBRUARY, 18)
        time = Clock(3, 36, 52).to_time()
        utc = date.toordinal() + time
        td = dynamical_from_universal(utc)
        clk = Clock.from_moment(td)
        self.assertEqual(clk.hour, 3)
        self.assertEqual(clk.minute, 37)
        self.assertEqual(int(round(clk.second)), 40)

        date = GregorianDate(333, MonthOfYear.FEBRUARY, 6)
        time = Clock(6, 0, 0).to_time()
        utc = date.toordinal() + time
        td = dynamical_from_universal(utc)
        clk = Clock.from_moment(td)
        self.assertEqual(clk.hour, 7)
        self.assertEqual(clk.minute, 57)
        self.assertAlmostEqual(clk.second, 54.66054, 4)
Exemple #15
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))
 def moment_of_depression(self, approx, alpha, early):
     """Return the moment in local time near approx when depression
     angle of sun is alpha (negative if above horizon) at location;
     early is true when MORNING event is sought, and false for EVENING."""
     tee = self.approx_moment_of_depression(approx, alpha, early)
     if abs(approx - tee) < Clock.days_from_seconds(30):
         return tee
     else:
         return self.moment_of_depression(tee, alpha, early)
 def sundial_time(cls, tee):
     """Return Hindu local time of temporal moment, tee."""
     date = Clock.ordinal_from_moment(tee)
     time = tee % 1
     q = int(math.floor(4 * time))
     if q == 0:
         a = cls.sunset(date - 1)
         b = cls.sunrise(date)
         t = Clock.days_from_hours(-6)
     elif q == 3:
         a = cls.sunset(date)
         b = cls.sunrise(date + 1)
         t = Clock.days_from_hours(18)
     else:
         a = cls.sunrise(date)
         b = cls.sunset(date)
         t = Clock.days_from_hours(6)
     return a + (2 * (b - a) * (time - t))
 def fromordinal(cls, ordinal):
     """Return Old Hindu lunar date equivalent to ordinal date 'ordinal'."""
     sun = cls.hindu_day_count(ordinal) + Clock.days_from_hours(6)
     new_moon = sun - (sun % cls.ARYA_LUNAR_MONTH)
     leap = cls.ARYA_SOLAR_MONTH - cls.ARYA_LUNAR_MONTH >= new_moon % cls.ARYA_SOLAR_MONTH and new_moon % cls.ARYA_SOLAR_MONTH > 0
     month = 1 + int(math.ceil(new_moon / cls.ARYA_SOLAR_MONTH) % 12)
     day = (int(math.floor(sun / cls.ARYA_LUNAR_DAY)) % 30) + 1
     year = int(
         math.ceil(
             (new_moon + cls.ARYA_SOLAR_MONTH) / cls.ARYA_SOLAR_YEAR)) - 1
     return OldHinduLunarDate(year, month, leap, day)
 def moonrise(self, date):
     """Return the standard time of moonrise on fixed, date,
     and location, location."""
     t = self.universal_from_standard(date)
     waning = (lunar_phase(t) > 180)
     alt = self.observed_lunar_altitude(t)
     offset = alt / 360
     if waning and (offset > 0):
         approx =  t + 1 - offset
     elif waning:
         approx = t - offset
     else:
         approx = t + (1 / 2) + offset
     rise = binary_search(approx - Clock.days_from_hours(3),
                          approx + Clock.days_from_hours(3),
                          lambda u, l: ((u - l) < Clock.days_from_hours(1/60)),
                          lambda x: self.observed_lunar_altitude(x) > 0)
     if rise < (t + 1):
         return self.standard_from_universal(rise)
     
     raise ValueError()
def hindu_tithi_occur(l_month, tithi, tee, l_year):
    """Return the ordinal date of occurrence of Hindu lunar tithi prior
    to sundial time, tee, in Hindu lunar month, l_month, and
    year, l_year."""
    approx = hindu_date_occur(l_month, int(math.floor(tithi)), l_year)
    lunar = HinduLunarDate.day_at_or_after(tithi, approx - 2)
    ttry = Clock.ordinal_from_moment(lunar)
    tee_h = HinduLunarDate.UJJAIN.standard_from_sundial(ttry + tee)
    if lunar <= tee_h or HinduLunarDate.lunar_phase(
            HinduLunarDate.UJJAIN.standard_from_sundial(ttry + 1 +
                                                        tee)) > 12 * tithi:
        return ttry
    else:
        return ttry + 1
Exemple #21
0
def ephemeris_correction(tee):
    """Return Dynamical Time minus Universal Time (in days) for
    moment, tee.  Adapted from "Astronomical Algorithms"
    by Jean Meeus, Willmann_Bell, Inc., 1991."""
    year = GregorianDate.to_year(int(math.floor(tee)))
    c = GregorianDate.date_difference(
        GregorianDate(1900, MonthOfYear.JANUARY, 1),
        GregorianDate(year, MonthOfYear.JULY, 1)) / mpf(36525)
    if 1988 <= year <= 2019:
        return 1 / 86400 * (year - 1933)
    elif 1900 <= year <= 1987:
        return poly(c, [
            mpf(-0.00002),
            mpf(0.000297),
            mpf(0.025184),
            mpf(-0.181133),
            mpf(0.553040),
            mpf(-0.861938),
            mpf(0.677066),
            mpf(-0.212591)
        ])
    elif 1800 <= year <= 1899:
        return poly(c, [
            mpf(-0.000009),
            mpf(0.003844),
            mpf(0.083563),
            mpf(0.865736),
            mpf(4.867575),
            mpf(15.845535),
            mpf(31.332267),
            mpf(38.291999),
            mpf(28.316289),
            mpf(11.636204),
            mpf(2.043794)
        ])
    elif 1700 <= year <= 1799:
        return 1 / 86400 * poly(
            year - 1700,
            [8.118780842, -0.005092142, 0.003336121, -0.0000266484])
    elif 1620 <= year <= 1699:
        return 1 / 86400 * poly(
            year - 1600,
            [mpf(196.58333), mpf(-4.0675),
             mpf(0.0219167)])
    else:
        x = Clock.days_from_hours(mpf(12)) + GregorianDate.date_difference(
            GregorianDate(1810, MonthOfYear.JANUARY, 1),
            GregorianDate(year, MonthOfYear.JANUARY, 1))
        return 1 / 86400 * (((x * x) / mpf(41048480)) - 15)
Exemple #22
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))
 def standard_from_sundial(self, tee):
     """Return standard time of temporal moment, tee, at location, location."""
     date = Clock.ordinal_from_moment(tee)
     hour = 24 * mod(tee, 1)
     if 6 <= hour <= 18:
         h = self.daytime_temporal_hour(date)
     elif (hour < 6):
         h = self.nighttime_temporal_hour(date - 1)
     else:
         h = self.nighttime_temporal_hour(date)
 
     # return
     if 6 <= hour <= 18:
         return self.sunrise(date) + ((hour - 6) * h)
     elif hour < 6:
         return self.sunset(date - 1) + ((hour + 6) * h)
     else:
         return self.sunset(date) + ((hour - 18) * h)
    def toordinal(self):
        """Return ordinal date corresponding to Old Hindu lunar date l_date."""
        mina = ((12 * self.year) - 1) * self.ARYA_SOLAR_MONTH
        lunar_new_year = self.ARYA_LUNAR_MONTH * (
            int(math.floor(mina / self.ARYA_LUNAR_MONTH)) + 1)

        if not self.leap and int(
                math.ceil((lunar_new_year - mina) /
                          (self.ARYA_SOLAR_MONTH -
                           self.ARYA_LUNAR_MONTH))) <= self.month:
            temp = self.month
        else:
            temp = self.month - 1

        temp = self.EPOCH + lunar_new_year + (self.ARYA_LUNAR_MONTH * temp) + (
            (self.day - 1) * self.ARYA_LUNAR_DAY) + Clock.days_from_hours(-6)

        return int(math.ceil(temp))
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))
 def midday(self, date):
     """Return standard time on fixed date, date, of midday
     at location, location."""
     return self.standard_from_local(self.local_from_apparent(date + Clock.days_from_hours(mpf(12))))
 def toordinal(self):
     """Return ordinal date corresponding to Old Hindu solar date s_date."""
     return int(
         math.ceil(self.EPOCH + self.year * self.ARYA_SOLAR_YEAR +
                   (self.month - 1) * self.ARYA_SOLAR_MONTH + self.day +
                   Clock.days_from_hours(-30)))
def shiva(gregorian_year):
    """Return the list of ordinal date(s) of Night of Shiva in Gregorian year, 'gregorian_year'."""
    return hindu_lunar_event(11, 29, Clock.days_from_hours(24), gregorian_year)
def rama(gregorian_year):
    """Return the list of ordinal date(s) of Rama's Birthday in Gregorian
    year, 'gregorian_year'."""
    return hindu_lunar_event(1, 9, Clock.days_from_hours(12), gregorian_year)
 def dusk(self, date, alpha):
     """Return standard time in evening on fixed date 'date' at
     location 'location' when depression angle of sun is alpha."""
     result = self.moment_of_depression(date + Clock.days_from_hours(18), alpha, self.EVENING)
     return self.standard_from_local(result)