Пример #1
2
def get_sunrise_and_sunset(date, observer):
    day = datetime_to_julian(date.replace(hour=12))

    sunrise = revjul_to_datetime(
        swisseph.revjul(
            swisseph.rise_trans(
                day - 1, swisseph.SUN, observer.lng, observer.lat, alt=observer.elevation, rsmi=swisseph.CALC_RISE
            )[1][0]
        )
    )

    sunset = revjul_to_datetime(
        swisseph.revjul(
            swisseph.rise_trans(
                day, swisseph.SUN, observer.lng, observer.lat, observer.elevation, rsmi=swisseph.CALC_SET
            )[1][0]
        )
    )

    next_sunrise = revjul_to_datetime(
        swisseph.revjul(
            swisseph.rise_trans(
                day, swisseph.SUN, observer.lng, observer.lat, observer.elevation, rsmi=swisseph.CALC_RISE
            )[1][0]
        )
    )
    swisseph.close()
    return sunrise, sunset, next_sunrise
Пример #2
0
def get_sunrise_and_sunset(date, observer):
	day = datetime_to_julian(date.replace(hour=12))

	sunrise = revjul_to_datetime(swisseph.revjul(swisseph.rise_trans(day-1, swisseph.SUN, 
	                                                                 observer.lng, 
	                                                                 observer.lat, 
	                                                                 alt=observer.elevation, 
	                                                                 rsmi=swisseph.CALC_RISE)[1][0]
	                                            )
	                            )

	sunset = revjul_to_datetime(swisseph.revjul(swisseph.rise_trans(day, swisseph.SUN, 
	                                                                observer.lng, observer.lat, 
	                                                                observer.elevation, 
	                                                                rsmi=swisseph.CALC_SET)[1][0]
	                                           )
	                           )

	next_sunrise = revjul_to_datetime(swisseph.revjul(swisseph.rise_trans(day, swisseph.SUN, 
	                                                                      observer.lng, observer.lat, 
	                                                                      observer.elevation, 
	                                                                      rsmi=swisseph.CALC_RISE)[1][0]
	                                                 )
	                                 )
	swisseph.close()
	return sunrise, sunset, next_sunrise
Пример #3
0
def get_transit(planet, observer, date):
	day = datetime_to_julian(date)
	if observer.lat < 0:
		transit=revjul_to_datetime(swisseph.revjul(swisseph.rise_trans(day-1, \
				planet, observer.lng, observer.lat, alt=observer.elevation, \
				rsmi=swisseph.CALC_MTRANSIT)[1][0]))
	else:
		transit=revjul_to_datetime(swisseph.revjul(swisseph.rise_trans(day-1, \
				planet, observer.lng, observer.lat, alt=observer.elevation, \
				rsmi=swisseph.CALC_ITRANSIT)[1][0]))
	swisseph.close()
	return transit
Пример #4
0
def get_last_dhanur_transit (jd_start,latitude,longitude):
  swisseph.set_sid_mode(swisseph.SIDM_LAHIRI) #Force Lahiri Ayanamsha
  for d in range(-25,0):
    jd = jd_start + d
    [y,m,d,t] = swisseph.revjul(jd)
  
    jd_sunrise=swisseph.rise_trans(jd_start=jd,body=swisseph.SUN,lon=longitude,
      lat=latitude,rsmi=swisseph.CALC_RISE|swisseph.BIT_DISC_CENTER)[1][0]
    jd_sunrise_tmrw=swisseph.rise_trans(jd_start=jd+1,body=swisseph.SUN,
      lon=longitude,lat=latitude,rsmi=swisseph.CALC_RISE|swisseph.BIT_DISC_CENTER)[1][0]
    jd_sunset =swisseph.rise_trans(jd_start=jd,body=swisseph.SUN,lon=longitude,
      lat=latitude,rsmi=swisseph.CALC_SET|swisseph.BIT_DISC_CENTER)[1][0]
  
    longitude_sun=swisseph.calc_ut(jd_sunrise,swisseph.SUN)[0]-swisseph.get_ayanamsa(jd_sunrise)
    longitude_sun_set=swisseph.calc_ut(jd_sunset,swisseph.SUN)[0]-swisseph.get_ayanamsa(jd_sunset)
    sun_month_rise = int(1+math.floor(((longitude_sun)%360)/30.0))
    sun_month = int(1+math.floor(((longitude_sun_set)%360)/30.0))
    longitude_sun_tmrw=swisseph.calc_ut(jd_sunrise+1,swisseph.SUN)[0]-swisseph.get_ayanamsa(jd_sunrise+1)
    sun_month_tmrw = int(1+math.floor(((longitude_sun_tmrw)%360)/30.0))

    if sun_month_rise!=sun_month_tmrw:
      if sun_month!=sun_month_tmrw:
        return jd+1
      else:
        return jd
Пример #5
0
def lunar_return(date, month, year, data, refinements=2): #data contains the angle, date is for a reasonable baseline
	day = datetime_to_julian(date)
	progress, cycles = math.modf((day/LUNAR_MONTH_DAYS))

	cycles = cycles+(year-date.year)*LMONTH_IN_SYEAR
	cycles = cycles+(month-date.month)*LMONTH_TO_MONTH

	day = (cycles)*LUNAR_MONTH_DAYS

	for i in range(refinements):
		angle = swisseph.calc_ut(day, swisseph.MOON)[0]
		day = day+(data-angle)/360*LUNAR_MONTH_DAYS

	for i in range(refinements):
		angle = swisseph.calc_ut(day, swisseph.MOON)[0]
		sec = ((data-angle)/LUNAR_DEGREE_SECOND)/SECS_TO_DAYS
		day = day+sec

	for i in range(refinements):
		angle = swisseph.calc_ut(day, swisseph.MOON)[0]
		msec = ((data-angle)/LUNAR_DEGREE_MS)/(SECS_TO_DAYS*1000)
		day = day+msec

	for i in range(refinements):
		angle = swisseph.calc_ut(day, swisseph.MOON)[0]
		nsec = ((data-angle)/LUNAR_DEGREE_NS)/(SECS_TO_DAYS*1000000)
		day = day+nsec

	return revjul_to_datetime(swisseph.revjul(day))
Пример #6
0
def previous_new_moon(date, refinements=2):
	days_since_nm = datetime_to_julian(date)-LAST_NM
	cycles = int(days_since_nm/LUNAR_MONTH_DAYS) #get a baseline
	day = cycles*LUNAR_MONTH_DAYS+LAST_NM

	for i in range(refinements):
		angle = get_moon_sun_diff(day)
		day = day+angle/360*LUNAR_MONTH_DAYS

	for i in range(refinements):
		angle = get_moon_sun_diff(day)
		sec = (angle/LUNAR_DEGREE_SECOND)/SECS_TO_DAYS
		day = day+sec

	for i in range(refinements):
		angle = get_moon_sun_diff(day)
		msec = (angle/LUNAR_DEGREE_MS)/(SECS_TO_DAYS*1000)
		day = day+msec

	for i in range(refinements):
		angle = get_moon_sun_diff(day)
		nsec = (angle/LUNAR_DEGREE_NS)/(SECS_TO_DAYS*1000000)
		day = day+nsec

	return revjul_to_datetime(swisseph.revjul(day))
Пример #7
0
def next_full_moon(date):
	days_since_nm = datetime_to_julian(date)-LAST_NM
	cycles = int(days_since_nm/LUNAR_MONTH_DAYS)+0.5 #get a baseline
	day = cycles*LUNAR_MONTH_DAYS+LAST_NM

	for i in range(refinements):
		angle = get_moon_sun_diff(day)
		day = day+(angle-180.0)/360*LUNAR_MONTH_DAYS

	for i in range(refinements):
		angle = get_moon_sun_diff(day)
		sec = ((angle-180)/LUNAR_DEGREE_SECOND)/SECS_TO_DAYS
		day = day+sec

	for i in range(refinements):
		angle = get_moon_sun_diff(day)
		msec = ((angle-180.0)/LUNAR_DEGREE_MS)/(SECS_TO_DAYS*1000)
		day = day+msec

	for i in range(refinements):
		angle = get_moon_sun_diff(day)
		nsec = ((angle-180.0)/LUNAR_DEGREE_NS)/(SECS_TO_DAYS*1000000)
		day = day+nsec
	## sun
	##/-----moon
	##sun-moon+ indicates that this is before
	##sun-moon- indicates that this is after
	return revjul_to_datetime(swisseph.revjul(day))
Пример #8
0
def next_full_moon(date):
    days_since_nm = datetime_to_julian(date) - LAST_NM
    cycles = int(days_since_nm / LUNAR_MONTH_DAYS) + 0.5  # get a baseline
    day = cycles * LUNAR_MONTH_DAYS + LAST_NM

    for i in range(refinements):
        angle = get_moon_sun_diff(day)
        day = day + (angle - 180.0) / 360 * LUNAR_MONTH_DAYS

    for i in range(refinements):
        angle = get_moon_sun_diff(day)
        sec = ((angle - 180) / LUNAR_DEGREE_SECOND) / SECS_TO_DAYS
        day = day + sec

    for i in range(refinements):
        angle = get_moon_sun_diff(day)
        msec = ((angle - 180.0) / LUNAR_DEGREE_MS) / (SECS_TO_DAYS * 1000)
        day = day + msec

    for i in range(refinements):
        angle = get_moon_sun_diff(day)
        nsec = ((angle - 180.0) / LUNAR_DEGREE_NS) / (SECS_TO_DAYS * 1000000)
        day = day + nsec
        ## sun
        ##/-----moon
        ##sun-moon+ indicates that this is before
        ##sun-moon- indicates that this is after
    return revjul_to_datetime(swisseph.revjul(day))
Пример #9
0
def previous_new_moon(date, refinements=2):
    days_since_nm = datetime_to_julian(date) - LAST_NM
    cycles = int(days_since_nm / LUNAR_MONTH_DAYS)  # get a baseline
    day = cycles * LUNAR_MONTH_DAYS + LAST_NM

    for i in range(refinements):
        angle = get_moon_sun_diff(day)
        day = day + angle / 360 * LUNAR_MONTH_DAYS

    for i in range(refinements):
        angle = get_moon_sun_diff(day)
        sec = (angle / LUNAR_DEGREE_SECOND) / SECS_TO_DAYS
        day = day + sec

    for i in range(refinements):
        angle = get_moon_sun_diff(day)
        msec = (angle / LUNAR_DEGREE_MS) / (SECS_TO_DAYS * 1000)
        day = day + msec

    for i in range(refinements):
        angle = get_moon_sun_diff(day)
        nsec = (angle / LUNAR_DEGREE_NS) / (SECS_TO_DAYS * 1000000)
        day = day + nsec

    return revjul_to_datetime(swisseph.revjul(day))
Пример #10
0
def lunar_return(date, month, year, data, refinements=2):  # data contains the angle, date is for a reasonable baseline
    day = datetime_to_julian(date)
    progress, cycles = math.modf((day / LUNAR_MONTH_DAYS))

    cycles = cycles + (year - date.year) * LMONTH_IN_SYEAR
    cycles = cycles + (month - date.month) * LMONTH_TO_MONTH

    day = (cycles) * LUNAR_MONTH_DAYS

    for i in range(refinements):
        angle = swisseph.calc_ut(day, swisseph.MOON)[0]
        day = day + (data - angle) / 360 * LUNAR_MONTH_DAYS

    for i in range(refinements):
        angle = swisseph.calc_ut(day, swisseph.MOON)[0]
        sec = ((data - angle) / LUNAR_DEGREE_SECOND) / SECS_TO_DAYS
        day = day + sec

    for i in range(refinements):
        angle = swisseph.calc_ut(day, swisseph.MOON)[0]
        msec = ((data - angle) / LUNAR_DEGREE_MS) / (SECS_TO_DAYS * 1000)
        day = day + msec

    for i in range(refinements):
        angle = swisseph.calc_ut(day, swisseph.MOON)[0]
        nsec = ((data - angle) / LUNAR_DEGREE_NS) / (SECS_TO_DAYS * 1000000)
        day = day + nsec

    return revjul_to_datetime(swisseph.revjul(day))
Пример #11
0
  def get_timezone_offset_hours_from_jd(self, julian_day):
    """Get timezone offset in hours east of UTC (negative west of UTC)

    Timezone offset is dependent both on place and time - due to Daylight savings time.
    compute offset from UTC in hours
    """
    [y, m, dt, t] = swe.revjul(julian_day)
    return self.get_timezone_offset_hours_from_date(year=y, month=m, day=dt)
Пример #12
0
def date_convert(jul_number):
    temp = swe.revjul(jul_number)
    year = temp[0]
    month = temp[1]
    day = temp[2]
    min_temp, hour = math.modf(temp[3])
    sec_temp, min = math.modf(min_temp * 60)
    sub_sec, sec = math.modf(sec_temp * 60)
    return datetime.datetime(year, month, day, int(hour), int(min), int(sec))
Пример #13
0
def date_convert(jul_number):
    temp = swe.revjul(jul_number)
    year = temp[0]
    month = temp[1]
    day = temp[2]
    min_temp, hour = math.modf(temp[3])
    sec_temp, min = math.modf(min_temp * 60)
    sub_sec, sec = math.modf(sec_temp * 60)
    return datetime.datetime(year, month, day, int(hour), int(min), int(sec))
Пример #14
0
def revjul(jd, formatstr='%4d-%02d-%02d %02d:%02d:%02d', tz_off=0):
    """Returns a more human readable revjul compared to swe

    Converts a given jd (float) to a tuple [y,m,d,h,mm,ss]

    Args:
      A float corresponding to a Julian day

    Returns:
      A tuple detailing the year, month, day, hour, minute and second

    Examples:
      >>> revjul(2444961.7125, None)
      (1981, 12, 23, 5, 6, 0)
      >>> revjul(2444961.7125)
      '1981-12-23 05:06:00'
    """

    if jd is None:
        return None

    year, month, day, h_float = swe.revjul(jd + tz_off / 24.0)

    hour = floor(h_float)
    h_float = (h_float - hour) * 60

    minute = floor(h_float)
    h_float = (h_float - minute) * 60

    second = int(round(h_float))

    if second == 60:
        minute += 1
        second = 0
        if minute == 60:
            hour += 1
            minute = 0
            if hour == 24:
                year, month, day, _h = swe.revjul(jd + (tz_off + 1) / 24.0)

    if formatstr is None:
        return (year, month, day, hour, minute, second)
    else:
        return (formatstr % (year, month, day, hour, minute, second))
Пример #15
0
def get_transit(planet, observer, date):
	day = datetime_to_julian(date)
	if observer.lat < 0:
		transit = revjul_to_datetime(swisseph.revjul(swisseph.rise_trans(day-1, planet,
		                                                               observer.lng, 
		                                                               observer.lat, 
		                                                               alt=observer.elevation, 
		                                                               rsmi=swisseph.CALC_MTRANSIT)[1][0]
		                                          )
		                          )
	else:
		transit = revjul_to_datetime(swisseph.revjul(swisseph.rise_trans(day-1, planet, 
		                                                               observer.lng, 
		                                                               observer.lat, 
		                                                               alt=observer.elevation, 
		                                                               rsmi=swisseph.CALC_ITRANSIT)[1][0]
		                                          )
		                          )
	swisseph.close()
	return transit
Пример #16
0
def solar_return(date, year, data, refinements=2):  # data contains the angule, date is for a reasonable baseline
    day = datetime_to_julian(date) + (SOLAR_YEAR_DAYS * (year - date.year))

    for i in range(refinements):
        angle = swisseph.calc_ut(day, swisseph.SUN)[0]
        sec = ((data - angle) / SOLAR_DEGREE_SECOND) / SECS_TO_DAYS
        day = day + sec
    for i in range(refinements):
        angle = swisseph.calc_ut(day, swisseph.SUN)[0]
        msec = ((data - angle) / SOLAR_DEGREE_MS) / (SECS_TO_DAYS * 1000)

    return revjul_to_datetime(swisseph.revjul(day + msec))
Пример #17
0
def solar_return(date, year, data, refinements=2): #data contains the angule, date is for a reasonable baseline
	day = datetime_to_julian(date)+(SOLAR_YEAR_DAYS*(year-date.year))

	for i in range(refinements):
		angle = swisseph.calc_ut(day, swisseph.SUN)[0]
		sec = ((data-angle)/SOLAR_DEGREE_SECOND)/SECS_TO_DAYS
		day = day+sec
	for i in range(refinements):
		angle = swisseph.calc_ut(day, swisseph.SUN)[0]
		msec = ((data-angle)/SOLAR_DEGREE_MS)/(SECS_TO_DAYS*1000)

	return revjul_to_datetime(swisseph.revjul(day+msec))
Пример #18
0
 def julian_day_to_local_time(self, julian_day, round_seconds=False):
     [y, m, dt, time_in_hours] = swe.revjul(julian_day)
     (hours, minutes,
      seconds) = decypher_fractional_hours(time_in_hours=time_in_hours)
     local_time = swe.utc_time_zone(
         y, m, dt, hours, minutes,
         seconds, -self.get_timezone_offset_hours_from_date(
             y, m, dt, hours, minutes, seconds))
     if round_seconds:
         (y, m, dt, hours, minutes, seconds) = local_time
         local_time = (y, m, dt, hours, minutes, int(round(seconds)))
         local_time = temporal.sanitize_time(*local_time)
     return local_time
Пример #19
0
  def get_timezone_offset_hours(self, julian_day):
    """Get timezone offset in hours east of UTC (negative west of UTC)

    Timezone offset is dependent both on place and time - due to Daylight savings time.
    compute offset from UTC in hours
    """
    [y, m, dt, t] = swe.revjul(julian_day)

    import pytz
    # checking @ 6am local - can we do any better?
    local_time = pytz.timezone(self.timezone).localize(datetime(y, m, dt, 6, 0, 0))

    return datetime.utcoffset(local_time).seconds / 3600.0
Пример #20
0
 def day_buckets(self, dates):
     zero_date = swe.julday(1900, 1, 1)
     buckets = collections.defaultdict(list)
     if self.args.match_by_days == 1:
         # Recover the calendar day for extra accuracy
         for date in dates:
             _, m, d, _ = swe.revjul(date)
             bucket = (m, d)
             buckets[bucket].append(date)
     else:
         for date in dates:
             year_fraction = (date - zero_date) / DAYS_IN_YEAR + 1000
             year_fraction -= int(year_fraction)
             bucket = int(year_fraction * DAYS_IN_YEAR /
                          self.args.match_by_days)
             buckets[bucket].append(date)
     return buckets
Пример #21
0
def get_last_dhanur_transit(jd_start, latitude, longitude):
    swisseph.set_sid_mode(swisseph.SIDM_LAHIRI)  #Force Lahiri Ayanamsha
    for d in range(-25, 0):
        jd = jd_start + d
        [y, m, d, t] = swisseph.revjul(jd)

        jd_rise = swisseph.rise_trans(jd_start=jd,
                                      body=swisseph.SUN,
                                      lon=longitude,
                                      lat=latitude,
                                      rsmi=swisseph.CALC_RISE
                                      | swisseph.BIT_DISC_CENTER)[1][0]
        jd_rise_tmrw = swisseph.rise_trans(jd_start=jd + 1,
                                           body=swisseph.SUN,
                                           lon=longitude,
                                           lat=latitude,
                                           rsmi=swisseph.CALC_RISE
                                           | swisseph.BIT_DISC_CENTER)[1][0]
        jd_set = swisseph.rise_trans(jd_start=jd,
                                     body=swisseph.SUN,
                                     lon=longitude,
                                     lat=latitude,
                                     rsmi=swisseph.CALC_SET
                                     | swisseph.BIT_DISC_CENTER)[1][0]

        longitude_sun = swisseph.calc_ut(
            jd_rise, swisseph.SUN)[0] - swisseph.get_ayanamsa(jd_rise)
        longitude_sun_set = swisseph.calc_ut(
            jd_set, swisseph.SUN)[0] - swisseph.get_ayanamsa(jd_set)
        sun_month_rise = masa_names[int(1 + math.floor((
            (longitude_sun) % 360) / 30.0))]
        sun_month = masa_names[int(1 + math.floor((
            (longitude_sun_set) % 360) / 30.0))]
        longitude_sun_tmrw = swisseph.calc_ut(
            jd_rise + 1, swisseph.SUN)[0] - swisseph.get_ayanamsa(jd_rise + 1)
        sun_month_tmrw = masa_names[int(1 + math.floor((
            (longitude_sun_tmrw) % 360) / 30.0))]

        #print '%f:%d-%d-%d: rise=%s, set=%s, tmrw=%s' %(jd,y,m,d,sun_month_rise,sun_month,sun_month_tmrw)

        if sun_month_rise != sun_month_tmrw:
            if sun_month != sun_month_tmrw:
                return jd + 1
            else:
                return jd
Пример #22
0
def main():
    city_name = sys.argv[1]
    latitude = sexastr2deci(sys.argv[2])
    longitude = sexastr2deci(sys.argv[3])
    tz = sys.argv[4]

    start_year = int(sys.argv[5])
    year = start_year
    jd = swisseph.julday(year, 1, 1, 0)
    jd_start = jd
    start_date = datetime(year=year,
                          month=1,
                          day=1,
                          hour=0,
                          minute=0,
                          second=0)

    day_of_year = 0

    swisseph.set_sid_mode(swisseph.SIDM_LAHIRI)  #Force Lahiri Ayanamsha

    sun_month_day = jd - get_last_dhanur_transit(jd, latitude, longitude)
    #this has to be done in a generic fashion, by scanning for the transit into dhanur of the last year!

    month_start_after_set = 0

    template_file = open('cal_template.tex')
    template_lines = template_file.readlines()
    for i in range(0, len(template_lines) - 3):
        print template_lines[i][:-1]

    samvatsara_id = (year - 1568) % 60 + 1
    #distance from prabhava
    samvatsara_names = '%s–%s' % (year_names[samvatsara_id],
                                  year_names[(samvatsara_id % 60) + 1])

    print '\\mbox{}'
    print '{\\font\\x="Warnock Pro" at 60 pt\\x %d\\\\[0.3cm]}' % year
    print '\\mbox{\\font\\x="Sanskrit 2003:script=deva" at 48 pt\\x %s}\\\\[0.5cm]' % samvatsara_names
    print '{\\font\\x="Warnock Pro" at 48 pt\\x \\uppercase{%s}\\\\[0.3cm]}' % city_name
    print '\hrule'

    while year <= start_year:

        day_of_year = day_of_year + 1

        [y, m, d, t] = swisseph.revjul(jd)
        weekday = (swisseph.day_of_week(jd) +
                   1) % 7  #swisseph has Mon = 0, non-intuitively!

        local_time = pytz.timezone(tz).localize(datetime(
            y, m, d, 6, 0, 0))  #checking @ 6am local - can we do any better?
        tz_off = datetime.utcoffset(
            local_time).seconds / 3600.0  #compute offset from UTC

        jd_rise = swisseph.rise_trans(jd_start=jd,
                                      body=swisseph.SUN,
                                      lon=longitude,
                                      lat=latitude,
                                      rsmi=swisseph.CALC_RISE
                                      | swisseph.BIT_DISC_CENTER)[1][0]
        jd_rise_tmrw = swisseph.rise_trans(jd_start=jd + 1,
                                           body=swisseph.SUN,
                                           lon=longitude,
                                           lat=latitude,
                                           rsmi=swisseph.CALC_RISE
                                           | swisseph.BIT_DISC_CENTER)[1][0]
        jd_set = swisseph.rise_trans(jd_start=jd,
                                     body=swisseph.SUN,
                                     lon=longitude,
                                     lat=latitude,
                                     rsmi=swisseph.CALC_SET
                                     | swisseph.BIT_DISC_CENTER)[1][0]

        [_y, _m, _d, t_rise] = swisseph.revjul(jd_rise + tz_off / 24.0)
        [_y, _m, _d, t_set] = swisseph.revjul(jd_set + tz_off / 24.0)

        longitude_moon = swisseph.calc_ut(
            jd_rise, swisseph.MOON)[0] - swisseph.get_ayanamsa(jd_rise)
        longitude_moon_tmrw = swisseph.calc_ut(
            jd_rise + 1, swisseph.MOON)[0] - swisseph.get_ayanamsa(jd_rise + 1)

        longitude_sun = swisseph.calc_ut(
            jd_rise, swisseph.SUN)[0] - swisseph.get_ayanamsa(jd_rise)
        longitude_sun_set = swisseph.calc_ut(
            jd_set, swisseph.SUN)[0] - swisseph.get_ayanamsa(jd_set)
        sun_month_rise = masa_names[int(1 + math.floor((
            (longitude_sun) % 360) / 30.0))]
        sun_month = masa_names[int(1 + math.floor((
            (longitude_sun_set) % 360) / 30.0))]
        longitude_sun_tmrw = swisseph.calc_ut(
            jd_rise + 1, swisseph.SUN)[0] - swisseph.get_ayanamsa(jd_rise + 1)
        sun_month_tmrw = masa_names[int(1 + math.floor((
            (longitude_sun_tmrw) % 360) / 30.0))]

        daily_motion_moon = (longitude_moon_tmrw - longitude_moon) % 360
        daily_motion_sun = (longitude_sun_tmrw - longitude_sun) % 360

        #Solar month calculations
        if month_start_after_set == 1:
            sun_month_day = 0
            month_start_after_set = 0

        if sun_month_rise != sun_month_tmrw:
            if sun_month != sun_month_tmrw:
                month_start_after_set = 1
                sun_month_day = sun_month_day + 1
            #mAsa pirappu!
            #sun_month = sun_month_tmrw #sun moves into next rAsi before sunset -- check rules!
            else:
                sun_month_day = 1
            month_remaining = 30 - (longitude_sun % 30.0)
            month_end = month_remaining / daily_motion_sun * 24.0
            me = deci2sexa(t_rise + month_end)
            if me[0] >= 24:
                suff = '(+1)'
                me[0] = me[0] - 24
            else:
                suff = '\\hspace{2ex}'
            sun_month_end_time = '{\\textsf{%s} {\\tiny \\RIGHTarrow} %02d:%02d%s}' % (
                last_sun_month, me[0], me[1], suff)
        else:
            sun_month_day = sun_month_day + 1
            sun_month_end_time = ''

        month_data = '\\sunmonth{%s}{%d}{%s}' % (sun_month, sun_month_day,
                                                 sun_month_end_time)
        #print '%%@%f:%d-%d-%d: rise=%s, set=%s, tmrw=%s' %(jd,y,m,d,sun_month_rise,sun_month,sun_month_tmrw)

        #Compute tithi details
        tithi = int(1 +
                    math.floor((longitude_moon - longitude_sun) % 360 / 12.0))
        tithi_tmrw = int(1 + math.floor(
            (longitude_moon_tmrw - longitude_sun_tmrw) % 360 / 12.0))

        if (tithi_tmrw - tithi) % 30 > 1:
            #double change
            tithi_2 = (tithi % 30) + 1
            if tithi_2 % 15 != 0:
                paksha = ('shukla' if tithi_2 < 15 else 'krishna')
            else:
                if tithi_2 == 15:
                    paksha = 'fullmoon'
                elif tithi_2 == 30:
                    paksha = 'newmoon'

            if tithi_2 % 15 == 0:
                tithi_str_2 = paksha + tithi_names[tithi_2]
            else:
                tithi_str_2 = paksha + tithi_names[tithi_2 % 15]

            tithi_remaining_2 = 12 + 12 - ((
                (longitude_moon - longitude_sun) % 360) % 12)
            tithi_end_2 = tithi_remaining_2 / (daily_motion_moon -
                                               daily_motion_sun) * 24.0
            tithi_end_str_2 = print_end_time(tithi_end_2,
                                             jd_rise_tmrw - jd_rise, t_rise)
            if tithi_end_str_2 == '\\textsf{अहोरात्रम्}':
                #needs correction, owing to the fact that we compute longitude every 24h, rather than at next sunrise
                #the second tithi cannot be 'all day'! It's ending will reflect in tomorrow's calendar
                tithi_str_2 = ''
                tithi_end_str_2 = ''
        else:
            tithi_str_2 = ''
            tithi_end_str_2 = ''

        if tithi % 15 != 0:
            paksha = ('shukla' if tithi < 15 else 'krishna')
        else:
            if tithi == 15:
                paksha = 'fullmoon'
            elif tithi == 30:
                paksha = 'newmoon'

        if tithi % 15 == 0:
            tithi_str = paksha + tithi_names[tithi]
        else:
            tithi_str = paksha + tithi_names[tithi % 15]

        tithi_remaining = 12 - (((longitude_moon - longitude_sun) % 360) % 12)
        tithi_end = tithi_remaining / (daily_motion_moon -
                                       daily_motion_sun) * 24.0
        tithi_end_str = print_end_time(tithi_end, jd_rise_tmrw - jd_rise,
                                       t_rise)

        #Compute nakshatram details
        n_id = int(1 + math.floor((longitude_moon % 360) / (360.0 / 27)))
        n_id_tmrw = int(1 + math.floor((longitude_moon_tmrw % 360) /
                                       (360.0 / 27)))
        if (n_id_tmrw - n_id) % 27 > 1:
            #there is a double change
            nakshatram_str_2 = nakshatra_names[n_id % 27 + 1]
            nakshatram_remaining_2 = (360.0 / 27) + (360.0 / 27) - (
                (longitude_moon % 360) % (360.0 / 27))
            nakshatram_end_2 = nakshatram_remaining_2 / daily_motion_moon * 24
            nakshatram_end_str_2 = print_end_time(nakshatram_end_2,
                                                  jd_rise_tmrw - jd_rise,
                                                  t_rise)
            if nakshatram_end_str_2 == '\\textsf{अहोरात्रम्}':
                #needs correction, owing to the fact that we compute longitude every 24h, rather than at next sunrise
                #the second nakshatram cannot be 'all day'! It's ending will reflect in tomorrow's calendar
                nakshatram_str_2 = ''
                nakshatram_end_str_2 = ''
        else:
            nakshatram_str_2 = ''
            nakshatram_end_str_2 = ''

        nakshatram_str = nakshatra_names[n_id]
        nakshatram_remaining = (360.0 / 27) - ((longitude_moon % 360) %
                                               (360.0 / 27))
        nakshatram_end = nakshatram_remaining / daily_motion_moon * 24
        nakshatram_end_str = print_end_time(nakshatram_end,
                                            jd_rise_tmrw - jd_rise, t_rise)

        #Sunrise/sunset and related stuff (like rahu, yama)
        [rh, rm, rs] = deci2sexa(t_rise)  #rise_t hour, rise minute
        [sh, sm, ss] = deci2sexa(t_set)  #set_t hour, set minute

        present_day = start_date + timedelta(days=day_of_year)
        rise_t = present_day + timedelta(hours=rh, minutes=rm)
        set_t = present_day + timedelta(hours=sh, minutes=sm)

        length_of_day = set_t - rise_t
        yamakandam_start = rise_t + timedelta(
            seconds=(1 / 8.0) *
            (yamakandam_octets[weekday] - 1) * length_of_day.seconds)
        yamakandam_end = yamakandam_start + timedelta(seconds=(1 / 8.0) *
                                                      length_of_day.seconds)
        rahukalam_start = rise_t + timedelta(seconds=(1 / 8.0) *
                                             (rahukalam_octets[weekday] - 1) *
                                             length_of_day.seconds)
        rahukalam_end = rahukalam_start + timedelta(seconds=(1 / 8.0) *
                                                    length_of_day.seconds)
        madhyahnikam_start = rise_t + timedelta(seconds=(1 / 5.0) *
                                                length_of_day.seconds)

        rise = '%02d:%02d' % (rh, rm)
        set = '%02d:%02d' % (sh, sm)
        madhya = print_time(madhyahnikam_start)
        rahu = '%s--%s' % (print_time(rahukalam_start),
                           print_time(rahukalam_end))
        yama = '%s--%s' % (print_time(yamakandam_start),
                           print_time(yamakandam_end))

        #Layout calendar in LATeX format
        if d == 1:
            if m > 1:
                if weekday != 0:  #Space till Sunday
                    for i in range(weekday, 6):
                        print "{}  &"
                    print "\\\\ \hline"
                print '\end{tabular}'
                print '\n\n'

            #Begin tabular
            print '\\begin{tabular}{|c|c|c|c|c|c|c|}'
            print '\multicolumn{7}{c}{\Large \\bfseries %s %s}\\\\[3mm]' % (
                month[m], y)
            print '\hline'
            print '\\textbf{SUN} & \\textbf{MON} & \\textbf{TUE} & \\textbf{WED} & \\textbf{THU} & \\textbf{FRI} & \\textbf{SAT} \\\\ \hline'
            #print '\\textbf{भानु} & \\textbf{इन्दु} & \\textbf{भौम} & \\textbf{बुध} & \\textbf{गुरु} & \\textbf{भृगु} & \\textbf{स्थिर} \\\\ \hline'

            #Blanks for previous weekdays
            for i in range(0, weekday):
                print "{}  &"

        #Create nakshatram data string
        nEmpty = 0

        if nakshatram_end_str_2 != '':
            nakshatram_data_string = '{\\textsf{%s} {\\tiny \\RIGHTarrow} %s}{\\textsf{%s} {\\tiny \\RIGHTarrow} %s}' % (
                nakshatram_str, nakshatram_end_str, nakshatram_str_2,
                nakshatram_end_str_2)
        else:
            nakshatram_data_string = '{\\textsf{%s} {\\tiny \\RIGHTarrow} %s}' % (
                nakshatram_str, nakshatram_end_str)
            nEmpty = nEmpty + 1

        if tithi_end_str_2 != '':
            tithi_data_string = '{\\textsf{\\%s} {\\tiny \\RIGHTarrow} %s}{\\textsf{\\%s} {\\tiny \\RIGHTarrow} %s}' % (
                tithi_str, tithi_end_str, tithi_str_2, tithi_end_str_2)
        else:
            tithi_data_string = '{\\textsf{\\%s} {\\tiny \\RIGHTarrow} %s}' % (
                tithi_str, tithi_end_str)
            nEmpty = nEmpty + 1

        empty_str = ''
        for i in range(0, nEmpty):
            empty_str = empty_str + '{}'

        print '\caldata{\\textcolor{%s}{%s}}{%s}{\\sundata{%s}{%s}{%s}}%s%s%s{\\textsf{राहु}~%s~~\\textsf{यम}~%s} ' % (
            daycol[weekday], d, month_data, rise, set, madhya,
            tithi_data_string, nakshatram_data_string, empty_str, rahu, yama)

        if weekday == 6:
            print "\\\\ \hline"
        else:
            print "&"

        jd = jd + 1

        last_sun_month = sun_month

        if m == 12 and d == 31:
            year = year + 1

        # For debugging specific dates
        #if m==4 and d==10:
        #  break

    for i in range(weekday + 1, 6):
        print "{}  &"
    if weekday != 6:
        print "\\\\ \hline"
    print '\end{tabular}'
    print '\n\n'

    #print '\\input{%d-%s.tex}' % (year,city_name)
    print template_lines[-2][:-1]
    print template_lines[-1][:-1]
    assert (adhipati(citta) == swe.MARS)
    assert (mahadasa[adhipati(citta)] == 7)
    assert (adhipati(aslesha) == swe.MERCURY)
    assert (mahadasa[adhipati(aslesha)] == 17)


if __name__ == "__main__":
    adhipati_tests()
    # YYYY-MM-DD 09:40 IST = 04:10 UTC
    jdut1 = swe.utc_to_jd(1985, 6, 9, 4, 10, 0, flag=swe.GREG_CAL)[1]
    tz = 5.5
    print("jdut1", jdut1)
    dashas = vimsottari_mahadasa(jdut1)
    for i in dashas:
        print(' ---------- ' + get_planet_name(i) + ' Dasa ---------- ')
        bhuktis = vimsottari_bhukti(i, dashas[i])
        for j in bhuktis:
            jd = bhuktis[j]
            y, m, d, h = swe.revjul(round(jd + tz))
            print('%8s: %04d-%02d-%02d\t%.6lf' %
                  (get_planet_name(j), y, m, d, jd))

    jd = 2456950  # Some random date, ex: current date
    i, j, antara = compute_antara_from(jd, dashas)
    print("---- JD %d falls in %s dasa/%s bhukti -----" %
          (jd, get_planet_name(i), get_planet_name(j)))
    for k in antara:
        jd = antara[k]
        y, m, d, h = swe.revjul(round(jd + tz))
        print('%8s: %04d-%02d-%02d\t%.6lf' % (get_planet_name(k), y, m, d, jd))
Пример #24
0
Файл: sb.py Проект: musalisa/se
import swisseph as swe
#swe.set_ephe_path('/usr/share/ephe') # set path to ephemeris files
now = swe.julday(2007,3,3) # get Julian day number
res = swe.lun_eclipse_when(now) # find next lunar eclipse (from now on)
ecltime = swe.revjul(res[1][0]) # get date UTC
print (ecltime)
Пример #25
0
def lunar(time_zone, year, month, day, location_latitude, location_longitude):
    # ###lunar eclipses
    lunar_eclipse = {}
    now = swe.julday(year, month, day)
    res = swe.lun_eclipse_when(now)
    res_how = swe.lun_eclipse_how(res[1][0], 139.7, 35.68)
    #print res
    #print res_how
    eclip_time = swe.revjul(res[1][0])  # utc
    # print len(res[1]),res[0],res[1],eclip_time,bin(res[0][0])
    ecl_central_or_not = ''
    duration_penumbral = ''
    ecl_central = int('00000001', 2)
    central = res[0][0] & ecl_central
    if central == 1:
        ecl_central_or_not = 'Eclipse Central'
    ecl_noncentral = int('00000010', 2)
    central = res[0][0] & ecl_noncentral
    if central == 2:
        ecl_central_or_not = 'Eclipse Non Central'
    eclipse_total = int('00000100', 2)
    central = res[0][0] & eclipse_total
    if central == 4:
        Type = 'Eclipse Total'
        start = (date_convert(res[1][6]) + datetime.timedelta(hours=time_zone))
        #print 'Start partial', date_convert(res[1][2]) + datetime.timedelta(hours=time_zone)
        #print 'Start Total  ', date_convert(res[1][4]) + datetime.timedelta(hours=time_zone)
        maxi = (date_convert(res[1][0]) + datetime.timedelta(hours=time_zone))
        #print 'End Total    ', date_convert(res[1][5]) + datetime.timedelta(hours=time_zone)
        #print 'End partial  ', date_convert(res[1][3]) + datetime.timedelta(hours=time_zone)
        end = (date_convert(res[1][7]) + datetime.timedelta(hours=time_zone))
        duration_penumbral = (date_convert(res[1][7]) - date_convert(res[1][6]))
        duration_umbral = (date_convert(res[1][3]) - date_convert(res[1][2]))
        #print 'Total             ', date_convert(res[1][5]) - date_convert(res[1][4])

    eclipse_annualar = int('00001000', 2)
    central = res[0][0] & eclipse_annualar
    if central == 8:
        Type = 'Eclipse Annular'
    eclipse_partial = int('0010000', 2)
    central = res[0][0] & eclipse_partial
    if central == 16:
        Type = 'Eclipse Partial'
        start = (date_convert(res[1][6]) + datetime.timedelta(hours=time_zone))
        #print 'Start partial', date_convert(res[1][2]) + datetime.timedelta(hours=time_zone)
        maxi = (date_convert(res[1][0]) + datetime.timedelta(hours=time_zone))
        #print 'End partial  ', date_convert(res[1][3]) + datetime.timedelta(hours=time_zone)
        end = (date_convert(res[1][7]) + datetime.timedelta(hours=time_zone))
        duration_penumbral = (date_convert(res[1][7]) - date_convert(res[1][6]))
        duration_umbral = (date_convert(res[1][3]) - date_convert(res[1][2]))
    eclipse_ann_total = int('0100000', 2)
    central = res[0][0] & eclipse_ann_total
    if central == 32:
        Type  = 'Eclipse Penumbral'
    eclipse_ann_total = int('1000000', 2)
    central = res[0][0] & eclipse_ann_total
    if central == 64:
        Type = 'Eclipse Penumbral'
        start = (date_convert(res[1][6]) + datetime.timedelta(hours=time_zone))
        maxi = (date_convert(res[1][0]) + datetime.timedelta(hours=time_zone))
        end = (date_convert(res[1][7]) + datetime.timedelta(hours=time_zone))
        duration_umbral = (date_convert(res[1][7]) - date_convert(res[1][6]))
    soros_cycle = int(res_how[1][9])
    soros_number = int(res_how[1][10])
    magnitude_umbral = res_how[1][0]
    magnitude_penumbral = res_how[1][1]

    pos_p = swe.calc_ut(res[1][0], 0)
    signs = birthchart.natal_planet_signs(pos_p)
    sun_pos = pos_p[0]
    sun_zodiac = constants.SIGN_ZODIAC[signs[0]]
    pos_p = swe.calc_ut(res[1][0], 1)
    signs = birthchart.natal_planet_signs(pos_p)
    moon_pos = pos_p[0]
    moon_zodiac = constants.SIGN_ZODIAC[signs[0]]

    lunar_eclipse = {'ecl_central_or_not' : ecl_central_or_not, 'soros_cycle' : soros_cycle,
                            'sun_pos' : sun_pos, 'sun_zodiac' : sun_zodiac, 'moon_pos' : moon_pos, 'moon_zodiac' : moon_zodiac,
                            'start' : str(start), 'max' : str(maxi), 'soros_number' : soros_number, 'magnitude_umbral' : magnitude_umbral,
                            'end' : str(end), 'Type' : Type, 'magnitude_penumbral' : magnitude_penumbral, 'duration_umbral' : str(duration_umbral),
                            'duration_penumbral' : str(duration_penumbral)}
    return lunar_eclipse
Пример #26
0
samvatsara_names = '%s–%s' % (
    NAMES['SAMVATSARA_NAMES'][panchangam.script][samvatsara_id],
    NAMES['SAMVATSARA_NAMES'][panchangam.script][(samvatsara_id % 60) + 1])

output_collector = {}

# year data that is not specified for each day
samvatsara_id = (panchangam.year - 1568) % 60 + 1  # distance from prabhava
samvatsara_names = (
    NAMES['SAMVATSARA_NAMES'][panchangam.script][samvatsara_id],
    NAMES['SAMVATSARA_NAMES'][panchangam.script][(samvatsara_id % 60) + 1])
yname = samvatsara_names[0]  # Assign year name until Mesha Sankranti

for d in range(1, temporal.MAX_SZ - 1):
    try:
        [y, m, dt, t] = swe.revjul(panchangam.jd_start_utc + d - 1)
        local_time = tz(panchangam.city.timezone).localize(
            datetime(y, m, dt, 6, 0, 0))
        tz_off = (datetime.utcoffset(local_time).days * 86400 +
                  datetime.utcoffset(local_time).seconds) / 3600.0
        jd = panchangam.jd_start_utc - tz_off / 24.0 + d - 1

        sunrise = get_time_string(panchangam.jd_sunrise[d], jd)
        sunset = get_time_string(panchangam.jd_sunset[d], jd)
        moonrise = get_time_string(panchangam.jd_moonrise[d], jd)
        moonset = get_time_string(panchangam.jd_moonset[d], jd)

        rahu_start = get_time_string(panchangam.kaalas[d]['rahu'][0], jd)
        rahu_end = get_time_string(panchangam.kaalas[d]['rahu'][1], jd)
        yama_start = get_time_string(panchangam.kaalas[d]['yama'][0], jd)
        yama_end = get_time_string(panchangam.kaalas[d]['yama'][1], jd)
Пример #27
0
def main():
  city_name = sys.argv[1]
  latitude = sexastr2deci(sys.argv[2])
  longitude = sexastr2deci(sys.argv[3])
  tz = sys.argv[4]
  
  start_year = int(sys.argv[5])
  year = start_year
  jd=swisseph.julday(year,1,1,0)
  jd_start=jd

  if len(sys.argv)==7:
    script = sys.argv[6]
  else:
    script = 'deva' #Default script is devanagari
  
  swisseph.set_sid_mode(swisseph.SIDM_LAHIRI) #Force Lahiri Ayanamsha
  
  sun_month_day = jd-get_last_dhanur_transit(jd,latitude,longitude)
  
  month_start_after_set = 0
  
  template_file=open('cal_template_compre.tex')
  template_lines=template_file.readlines()
  for i in range(0,len(template_lines)-3):
    print template_lines[i][:-1]
  
  samvatsara_id = (year - 1568)%60 + 1; #distance from prabhava
  samvatsara_names = '%s–%s' % (year_names[script][samvatsara_id], 
    year_names[script][(samvatsara_id%60)+1])
  new_yr=mesha_sankranti[script]+'~('+year_names[script][(samvatsara_id%60)+1]+'-'+samvatsara[script]+')'
  
  print '\\mbox{}'
  print '{\\font\\x="Candara" at 60 pt\\x %d\\\\[0.5cm]}' % year
  print '\\mbox{\\font\\x="Sanskrit 2003:script=deva" at 48 pt\\x %s}\\\\[0.5cm]' % samvatsara_names
  print '{\\font\\x="Candara" at 48 pt\\x \\uppercase{%s}\\\\[0.5cm]}' % city_name
  print '\hrule'


  #INITIALISE VARIABLES
  jd_sunrise=[None]*368
  jd_sunset=[None]*368
  jd_moonrise=[None]*368
  longitude_moon=[None]*368
  longitude_sun=[None]*368
  longitude_sun_set=[None]*368
  sun_month_id=[None]*368
  sun_month=[None]*368
  sun_month_rise=[None]*368
  moon_month=[None]*368
  month_data=[None]*368
  tithi_data_string=[None]*368
  tithi_sunrise=[None]*368
  nakshatram_data_string=[None]*368
  nakshatram_sunrise=[None]*368
  karanam_data_string=[None]*368
  karanam_sunrise=[None]*368
  yogam_data_string=[None]*368
  yogam_sunrise=[None]*368
  weekday=[None]*368
  sunrise=[None]*368
  sunset=[None]*368
  madhya=[None]*368
  rahu=[None]*368
  yama=[None]*368
  festival_day_list={}
  festivals=['']*368
  
  weekday_start=swisseph.day_of_week(jd)+1
  #swisseph has Mon = 0, non-intuitively!

  ##################################################
  #Compute all parameters -- latitude/longitude etc#
  ##################################################

  for d in range(-1,367):
    jd = jd_start-1+d
    [y,m,dt,t] = swisseph.revjul(jd)
    weekday = (weekday_start -1 + d)%7 
  
    local_time = pytz.timezone(tz).localize(datetime(y, m, dt, 6, 0, 0))
    #checking @ 6am local - can we do any better?
    tz_off=datetime.utcoffset(local_time).seconds/3600.0 
    #compute offset from UTC

    jd_sunrise[d+1]=swisseph.rise_trans(jd_start=jd+1,body=swisseph.SUN,
      lon=longitude,lat=latitude,rsmi=swisseph.CALC_RISE|swisseph.BIT_DISC_CENTER)[1][0]
    jd_sunset[d+1]=swisseph.rise_trans(jd_start=jd+1,body=swisseph.SUN,
      lon=longitude,lat=latitude,rsmi=swisseph.CALC_SET|swisseph.BIT_DISC_CENTER)[1][0]
    jd_moonrise[d+1]=swisseph.rise_trans(jd_start=jd+1,body=swisseph.MOON,
      lon=longitude,lat=latitude,rsmi=swisseph.CALC_RISE|swisseph.BIT_DISC_CENTER)[1][0]
  
    longitude_sun[d+1]=swisseph.calc_ut(jd_sunrise[d+1],swisseph.SUN)[0]-swisseph.get_ayanamsa(jd_sunrise[d+1])
    longitude_moon[d+1]=swisseph.calc_ut(jd_sunrise[d+1],swisseph.MOON)[0]-swisseph.get_ayanamsa(jd_sunrise[d+1])
    longitude_sun_set[d+1]=swisseph.calc_ut(jd_sunset[d+1],swisseph.SUN)[0]-swisseph.get_ayanamsa(jd_sunset[d+1])
    
    sun_month_id[d+1] = int(1+math.floor(((longitude_sun_set[d+1])%360)/30.0))
    sun_month[d+1] = int(1+math.floor(((longitude_sun_set[d+1])%360)/30.0))

    sun_month_rise[d+1] = int(1+math.floor(((longitude_sun[d+1])%360)/30.0))

    if(d<=0):
      continue

    t_sunrise=(jd_sunrise[d]-jd)*24.0+tz_off
    t_sunset=(jd_sunset[d]-jd)*24.0+tz_off

  
    #Solar month calculations
    if month_start_after_set==1:
      sun_month_day = 0
      month_start_after_set = 0
  
    if sun_month[d]!=sun_month[d+1]:
      sun_month_day = sun_month_day + 1

      if sun_month[d]!=sun_month_rise[d+1]:
        month_start_after_set=1
        [_m,sun_month_end_time] = get_angam_data_string(masa_names[script], 30, jd_sunrise[d],
          jd_sunrise[d+1], t_sunrise, longitude_moon[d], longitude_sun[d], longitude_moon[d+1],
          longitude_sun[d+1], [0,1], script)
 
    elif sun_month_rise[d]!=sun_month[d]:
      #mAsa pirappu!
      #sun moves into next rAsi before sunset -- check rules!
      sun_month_day = 1

      [_m,sun_month_end_time] = get_angam_data_string(masa_names[script], 30, jd_sunrise[d],
      jd_sunrise[d+1], t_sunrise, longitude_moon[d], longitude_sun[d], longitude_moon[d+1],
      longitude_sun[d+1], [0,1], script)
    
    else:
      sun_month_day = sun_month_day + 1
      sun_month_end_time = ''
    
    month_data[d] = '\\sunmonth{%s}{%d}{%s}' % (masa_names[script][sun_month[d]],sun_month_day,sun_month_end_time)

    #KARADAYAN NOMBU -- easy to check here
    if sun_month_end_time !='': #month ends today
      if (sun_month[d]==12 and sun_month_day==1) or (sun_month[d]==11 and sun_month_day!=1):
        festival_day_list[karadayan_nombu[script]] = [d]
    #KOODARA VALLI -- easy to check here
    if sun_month[d]==9 and sun_month_day==27:
      festival_day_list[koodaravalli[script]]= [d]

  
    #Sunrise/sunset and related stuff (like rahu, yama)
    [rhs, rms, rss] = deci2sexa(t_sunrise)  #rise hour sun, rise minute sun, rise sec sun
    [shs, sms, sss] = deci2sexa(t_sunset)   
  
    length_of_day = t_sunset-t_sunrise
    yamagandam_start = t_sunrise + (1/8.0)*(yamagandam_octets[weekday]-1)*length_of_day
    yamagandam_end = yamagandam_start + (1/8.0)*length_of_day
    rahukalam_start = t_sunrise + (1/8.0)*(rahukalam_octets[weekday]-1)*length_of_day
    rahukalam_end = rahukalam_start + (1/8.0)*length_of_day
    madhyahnikam_start = t_sunrise + (1/5.0)*length_of_day
  
    sunrise[d]  = '%02d:%02d' % (rhs,rms)
    sunset[d]   = '%02d:%02d' % (shs,sms)
    madhya[d] = print_time(madhyahnikam_start)
    rahu[d] = '%s--%s' % (print_time(rahukalam_start), print_time(rahukalam_end))
    yama[d] = '%s--%s' % (print_time(yamagandam_start),print_time(yamagandam_end))
    
    [tithi_sunrise[d],tithi_data_string[d]]=get_angam_data_string(tithi_names[script], 12, jd_sunrise[d],
      jd_sunrise[d+1], t_sunrise, longitude_moon[d], longitude_sun[d], longitude_moon[d+1],
      longitude_sun[d+1], [1,-1], script)
    [nakshatram_sunrise[d], nakshatram_data_string[d]]=get_angam_data_string(nakshatra_names[script], (360.0/27.0),
      jd_sunrise[d], jd_sunrise[d+1], t_sunrise, longitude_moon[d], longitude_sun[d], 
      longitude_moon[d+1], longitude_sun[d+1], [1,0], script)
    [karanam_sunrise[d],karanam_data_string[d]]=get_angam_data_string(karanam_names[script], 6, jd_sunrise[d],
      jd_sunrise[d+1], t_sunrise, longitude_moon[d], longitude_sun[d], longitude_moon[d+1],
      longitude_sun[d+1], [1,-1], script)
    [yogam_sunrise[d],yogam_data_string[d]]=get_angam_data_string(yogam_names[script], (360.0/27.0), jd_sunrise[d],
      jd_sunrise[d+1], t_sunrise, longitude_moon[d], longitude_sun[d], longitude_moon[d+1],
      longitude_sun[d+1], [1,1], script)

  #ASSIGN MOON MONTHS
  last_month_change = 1
  last_moon_month = None
  for d in range(1,367):
    #Assign moon_month for each day
    if(tithi_sunrise[d]==1):
      for i in range(last_month_change,d):
        #print '%%#Setting moon_month to sun_month_id, for i=%d:%d to %d' %(last_month_change,d-1,sun_month_id[d])
        if (sun_month_id[d]==last_moon_month):
          moon_month[i] = sun_month_id[d]%12 + 0.5
        else:
          moon_month[i] = sun_month_id[d]
      last_month_change = d 
      last_moon_month = sun_month_id[d]
    elif(tithi_sunrise[d]==2 and tithi_sunrise[d-1]==30):
      #prathama tithi was never seen @ sunrise
      for i in range(last_month_change,d):
        #print '%%@Setting moon_month to sun_month_id, for i=%d:%d to %d (last month = %d)' %(last_month_change,d-1,sun_month_id[d],last_moon_month)
        if (sun_month_id[d-1]==last_moon_month):
          moon_month[i] = sun_month_id[d-1]%12 + 0.5
        else:
          moon_month[i] = sun_month_id[d-1]
      last_month_change = d 
      last_moon_month = sun_month_id[d-1]

  for i in range(last_month_change,367):
    moon_month[i]=sun_month_id[last_month_change-1]+1
    
  #for d in range(1,367):
    #jd = jd_start-1+d
    #[y,m,dt,t] = swisseph.revjul(jd)
    #print '%%#%02d-%02d-%4d: %3d:%s (sunrise tithi=%d) {%s}' % (dt,m,y,d,moon_month[d],tithi_sunrise[d],tithi_data_string[d])

  log_file=open('cal_log_%4d.txt' % year,'w')
  for d in range(1,367):
    jd = jd_start-1+d
    [y,m,dt,t] = swisseph.revjul(jd)
    log_data = '%02d-%02d-%4d\t[%3d]\tsun_rashi=%8.3f\ttithi=%8.3f\tsun_month=%2d\tmoon_month=%4.1f\n' % (dt,m,y,d,(longitude_sun_set[d]%360)/30.0,get_angam_float(jd_sunrise[d],12.0,[1,-1]),sun_month[d],moon_month[d])
    log_file.write(log_data)


  #PRINT CALENDAR

  for d in range(1,367):
    jd = jd_start-1+d
    [y,m,dt,t] = swisseph.revjul(jd)
    weekday = (weekday_start -1 + d)%7 

    ##################
    #Festival details#
    ##################

    ###--- MONTHLY VRATAMS ---###

    #EKADASHI Vratam
    if tithi_sunrise[d]==11 or tithi_sunrise[d]==12: #One of two consecutive tithis must appear @ sunrise!
      #check for shukla ekadashi
      if (tithi_sunrise[d]==11 and tithi_sunrise[d+1]==11): 
        festivals[d+1]=sarva[script]+'~'+get_ekadashi_name(paksha='shukla',month=moon_month[d],script=script)#moon_month[d] or [d+1]?
        if moon_month[d+1]==4:
          festivals[d+1]+='\\\\'+chaturmasya_start[script]
        if moon_month[d+1]==8:
          festivals[d+1]+='\\\\'+chaturmasya_end[script]
      elif (tithi_sunrise[d]==11 and tithi_sunrise[d+1]!=11): 
        #Check dashami end time to decide for whether this is sarva/smartha
        tithi_arunodayam = get_tithi(jd_sunrise[d]-(1/15.0)*(jd_sunrise[d]-jd_sunrise[d-1])) #Two muhurtams is 1/15 of day-length
        if tithi_arunodayam==10:
          festivals[d]=smartha[script]+'~'+get_ekadashi_name(paksha='shukla',month=moon_month[d],script=script)
          festivals[d+1]=vaishnava[script]+'~'+get_ekadashi_name(paksha='shukla',month=moon_month[d],script=script)
          if moon_month[d]==4:
            festivals[d]+='\\\\'+chaturmasya_start[script]
          if moon_month[d]==8:
            festivals[d]+='\\\\'+chaturmasya_end[script]
        else:
          festivals[d]=sarva[script]+'~'+get_ekadashi_name(paksha='shukla',month=moon_month[d],script=script)
          if moon_month[d]==4:
            festivals[d]+='\\\\'+chaturmasya_start[script]
          if moon_month[d]==8:
            festivals[d]+='\\\\'+chaturmasya_end[script]
      elif (tithi_sunrise[d-1]!=11 and tithi_sunrise[d]==12):
        festivals[d]=sarva[script]+'~'+get_ekadashi_name(paksha='shukla',month=moon_month[d],script=script)
        if moon_month[d]==4:
          festivals[d]+='\\\\'+chaturmasya_start[script]
        if moon_month[d]==8:
          festivals[d]+='\\\\'+chaturmasya_end[script]
 
    if tithi_sunrise[d]==26 or tithi_sunrise[d]==27: #One of two consecutive tithis must appear @ sunrise!
      #check for krishna ekadashi
      if (tithi_sunrise[d]==26 and tithi_sunrise[d+1]==26): 
        festivals[d+1]=sarva[script]+'~'+get_ekadashi_name(paksha='krishna',month=moon_month[d],script=script)#moon_month[d] or [d+1]?
      elif (tithi_sunrise[d]==26 and tithi_sunrise[d+1]!=26): 
        #Check dashami end time to decide for whether this is sarva/smartha
        tithi_arunodayam = get_tithi(jd_sunrise[d]-(1/15.0)*(jd_sunrise[d]-jd_sunrise[d-1])) #Two muhurtams is 1/15 of day-length
        if tithi_arunodayam==25:
          festivals[d]=smartha[script]+'~'+get_ekadashi_name(paksha='krishna',month=moon_month[d],script=script)
          festivals[d+1]=vaishnava[script]+'~'+get_ekadashi_name(paksha='krishna',month=moon_month[d],script=script)
        else:
          festivals[d]=sarva[script]+'~'+get_ekadashi_name(paksha='krishna',month=moon_month[d],script=script)
      elif (tithi_sunrise[d-1]!=26 and tithi_sunrise[d]==27):
        festivals[d]=sarva[script]+'~'+get_ekadashi_name(paksha='krishna',month=moon_month[d],script=script)

    #PRADOSHA Vratam
    if tithi_sunrise[d]==12 or tithi_sunrise[d]==13:
      ldiff_set=(swisseph.calc_ut(jd_sunset[d],swisseph.MOON)[0]-swisseph.calc_ut(jd_sunset[d],swisseph.SUN)[0])%360
      ldiff_set_tmrw=(swisseph.calc_ut(jd_sunset[d+1],swisseph.MOON)[0]-swisseph.calc_ut(jd_sunset[d+1],swisseph.SUN)[0])%360
      tithi_sunset = int(1+math.floor(ldiff_set/12.0))
      tithi_sunset_tmrw = int(1+math.floor(ldiff_set_tmrw/12.0))
      if tithi_sunset<=13 and tithi_sunset_tmrw!=13:
        festivals[d]=pradosham[script]
      elif tithi_sunset_tmrw==13:
        festivals[d+1]=pradosham[script]

    if tithi_sunrise[d]==27 or tithi_sunrise[d]==28:
      ldiff_set=(swisseph.calc_ut(jd_sunset[d],swisseph.MOON)[0]-swisseph.calc_ut(jd_sunset[d],swisseph.SUN)[0])%360
      ldiff_set_tmrw=(swisseph.calc_ut(jd_sunset[d+1],swisseph.MOON)[0]-swisseph.calc_ut(jd_sunset[d+1],swisseph.SUN)[0])%360
      tithi_sunset = int(1+math.floor(ldiff_set/12.0))
      tithi_sunset_tmrw = int(1+math.floor(ldiff_set_tmrw/12.0))
      if tithi_sunset<=28 and tithi_sunset_tmrw!=28:
        festivals[d]=pradosham[script]
      elif tithi_sunset_tmrw==28:
        festivals[d+1]=pradosham[script]

    #SANKATAHARA chaturthi
    if tithi_sunrise[d]==18 or tithi_sunrise[d]==19:
      ldiff_moonrise_yest=(swisseph.calc_ut(jd_moonrise[d-1],swisseph.MOON)[0]-swisseph.calc_ut(jd_moonrise[d-1],swisseph.SUN)[0])%360
      ldiff_moonrise=(swisseph.calc_ut(jd_moonrise[d],swisseph.MOON)[0]-swisseph.calc_ut(jd_moonrise[d],swisseph.SUN)[0])%360
      ldiff_moonrise_tmrw=(swisseph.calc_ut(jd_moonrise[d+1],swisseph.MOON)[0]-swisseph.calc_ut(jd_moonrise[d+1],swisseph.SUN)[0])%360
      tithi_moonrise_yest = int(1+math.floor(ldiff_moonrise_yest/12.0))
      tithi_moonrise = int(1+math.floor(ldiff_moonrise/12.0))
      tithi_moonrise_tmrw = int(1+math.floor(ldiff_moonrise_tmrw/12.0))

      if tithi_moonrise==19:
        if tithi_moonrise_yest!=19:#otherwise yesterday would have already been assigned
          festivals[d]=chaturthi[script] 
          if moon_month[d]==5:#shravana krishna chaturthi
            festivals[d]=maha[script]+festivals[d]
      elif tithi_moonrise_tmrw==19:
          festivals[d+1]=chaturthi[script] 
          if moon_month[d]==5: #moon_month[d] and[d+1] are same, so checking [d] is enough
            festivals[d+1]=maha[script]+festivals[d+1]

    #SHASHTHI Vratam
    if tithi_sunrise[d]==5 or tithi_sunrise[d]==6:
      if tithi_sunrise[d]==6 or (tithi_sunrise[d]==5 and tithi_sunrise[d+1]==7):
        if tithi_sunrise[d-1]!=6:#otherwise yesterday would have already been assigned
          festivals[d]=shashthi[script] 
          if moon_month[d]==8:#kArtika krishna shashthi
            festivals[d]=skanda[script]+festivals[d]
      elif tithi_sunrise[d+1]==6:
          festivals[d+1]=shashthi[script] 
          if moon_month[d]==8: #moon_month[d] and[d+1] are same, so checking [d] is enough
            festivals[d+1]=skanda[script]+festivals[d+1]

    ###--- OTHER (MAJOR) FESTIVALS ---###
    #type of month | month number | type of angam (tithi|nakshatram) | angam number | min_t cut off for considering prev day (without sunrise_angam) as festival date
    purvaviddha_rules={akshaya_tritiya[script]:['moon_month',2,'tithi',3,0],
    chitra_purnima[script]:['sun_month',1,'tithi',15,0],
    durgashtami[script]:['moon_month',7,'tithi',8,0],
    mahanavami[script]:['moon_month',7,'tithi',9,0],
    vijayadashami[script]:['moon_month',7,'tithi',10,0],
    dipavali[script]:['moon_month',7,'tithi',29,0],
    shankara_jayanti[script]:['moon_month',2,'tithi',5,0],
    yajur_upakarma[script]:['moon_month',5,'tithi',15,0],
    rg_upakarma[script]:['moon_month',5,'nakshatram',22,0],
    sama_upakarma[script]:['sun_month',5,'nakshatram',13,0],
    rishi_panchami[script]:['moon_month',6,'tithi',5,0],
    ananta_chaturdashi[script]:['moon_month',6,'tithi',14,0],
    mahalaya_paksham[script]:['moon_month',6,'tithi',16,0],
    hanumat_jayanti[script]:['sun_month',9,'tithi',30,0],
    ardra_darshanam[script]:['sun_month',9,'nakshatram',6,0],
    ratha_saptami[script]:['sun_month',10,'tithi',7,0],
    goda_jayanti[script]:['sun_month',4,'nakshatram',11,0],
    adi_krittika[script]:['sun_month',4,'nakshatram',3,0],
    phalguni_uttaram[script]:['sun_month',12,'nakshatram',12,4],
    mahalaya_amavasya[script]:['moon_month',6,'tithi',30,0],
    uma_maheshvara_vratam[script]:['moon_month',6,'tithi',15,0]}

    for x in iter(purvaviddha_rules.keys()):
      rule=purvaviddha_rules[x]
      if rule[0]=='moon_month':
        if moon_month[d]==rule[1]:
          if rule[2]=='tithi':
            fday = get_festival_day_purvaviddha(rule[3],tithi_sunrise,d,jd_sunrise[d],jd_sunrise[d+1],get_tithi,rule[4])
          elif rule[2]=='nakshatram':
            fday = get_festival_day_purvaviddha(rule[3],nakshatram_sunrise,d,jd_sunrise[d],jd_sunrise[d+1],get_nakshatram,rule[4])
          if fday is not None:
            if festival_day_list.has_key(x):
              if festival_day_list[x][0]!=fday:
                #Second occurrence of a festival within a Gregorian calendar year
                festival_day_list[x]=[festival_day_list[x][0],fday]
            else:
              festival_day_list[x]=[fday]
      elif rule[0]=='sun_month':
        if sun_month[d]==rule[1]:
          if rule[2]=='tithi':
            fday = get_festival_day_purvaviddha(rule[3],tithi_sunrise,d,jd_sunrise[d],jd_sunrise[d+1],get_tithi,rule[4])
          elif rule[2]=='nakshatram':
            fday = get_festival_day_purvaviddha(rule[3],nakshatram_sunrise,d,jd_sunrise[d],jd_sunrise[d+1],get_nakshatram,rule[4])
          if fday is not None:
            if festival_day_list.has_key(x):
              if festival_day_list[x][0]!=fday:
                #Second occurrence of a festival within a Gregorian calendar year
                festival_day_list[x]=[festival_day_list[x][0],fday]
            else:
              festival_day_list[x]=[fday]
      else:
        print 'Error; unknown string in rule: %s' % (rule[0])    
        return

    #NAVARATRI START
    if moon_month[d]==7 and moon_month[d-1]==6:
      festival_day_list[navaratri_start[script]]=[d]

    #PONGAL/AYANAM
    if sun_month[d]==10 and sun_month[d-1]==9:
      festival_day_list[uttarayanam[script]]=[d]

    if sun_month[d]==4 and sun_month[d-1]==3:
      festival_day_list[dakshinayanam[script]]=[d]

    if sun_month[d]==1 and sun_month[d-1]==12:
      festival_day_list[new_yr]=[d]

    if moon_month[d]==1 and moon_month[d-1]!=1:
      festival_day_list[yugadi[script]]=[d]

    #SHRIRAMANAVAMI
    if moon_month[d]==1:
      if tithi_sunrise[d]==8 or tithi_sunrise[d]==9:
        t_11 = get_tithi(jd_sunrise[d]+(jd_sunset[d]-jd_sunrise[d])*(2.0/5.0))#madhyahna1 start
        t_12 = get_tithi(jd_sunrise[d]+(jd_sunset[d]-jd_sunrise[d])*(3.0/5.0))#madhyahna1 end 
        t_21 = get_tithi(jd_sunrise[d+1]+(jd_sunset[d+1]-jd_sunrise[d+1])*(2.0/5.0))#madhyahna2 start
        t_22 = get_tithi(jd_sunrise[d+1]+(jd_sunset[d+1]-jd_sunrise[d+1])*(3.0/5.0))#madhyahna2 end
        if t_11==9 or t_12==9:
          if t_21==9 or t_22==9:
            festival_day_list[ramanavami[script]]=[d+1]
          else:
            festival_day_list[ramanavami[script]]=[d]
 
    #JANMASHTAMI
    if moon_month[d]==5:
      if tithi_sunrise[d]==22 or tithi_sunrise[d]==23:
        t_11 = get_tithi(jd_sunset[d]+(jd_sunrise[d+1]-jd_sunset[d])*(7.0/15.0))#nishita1 start
        t_12 = get_tithi(jd_sunset[d]+(jd_sunrise[d+1]-jd_sunset[d])*(8.0/15.0))#nishita1 end
        #t_11 = get_tithi(jd_sunset[d]+(jd_sunrise[d+1]-jd_sunset[d])*(2.0/5.0))#madhyaratri1 start
        #t_12 = get_tithi(jd_sunset[d]+(jd_sunrise[d+1]-jd_sunset[d])*(3.0/5.0))#madhyaratri1 end
        t_21 = get_tithi(jd_sunset[d+1]+(jd_sunrise[d+2]-jd_sunset[d+1])*(7.0/15.0))#nishita2 start
        t_22 = get_tithi(jd_sunset[d+1]+(jd_sunrise[d+2]-jd_sunset[d+1])*(8.0/15.0))#nishita2 end
        #t_21 = get_tithi(jd_sunset[d+1]+(jd_sunrise[d+2]-jd_sunset[d+1])*(2.0/5.0))#madhyaratri2 start
        #t_22 = get_tithi(jd_sunset[d+1]+(jd_sunrise[d+2]-jd_sunset[d+1])*(3.0/5.0))#madhyaratri2 end
        if t_11==23 or t_12==23:
          if t_21==23 or t_22==23:
            festival_day_list[janmashtami[script]]=[d+1]
          else:
            festival_day_list[janmashtami[script]]=[d]

    #SHIVARATRI
    if moon_month[d]==11:
      if tithi_sunrise[d]==28 or tithi_sunrise[d]==29:
        t_11 = get_tithi(jd_sunset[d]+(jd_sunrise[d+1]-jd_sunset[d])*(7.0/15.0))#nishita1 start
        t_12 = get_tithi(jd_sunset[d]+(jd_sunrise[d+1]-jd_sunset[d])*(8.0/15.0))#nishita1 end
        t_21 = get_tithi(jd_sunset[d+1]+(jd_sunrise[d+2]-jd_sunset[d+1])*(7.0/15.0))#nishita2 start
        t_22 = get_tithi(jd_sunset[d+1]+(jd_sunrise[d+2]-jd_sunset[d+1])*(8.0/15.0))#nishita2 end
        if t_11==29 or t_12==29:
          if t_21==29 or t_22==29:
            festival_day_list[shivaratri[script]]=[d+1]
          else:
            festival_day_list[shivaratri[script]]=[d]

    #VINAYAKA CHATURTHI
    if moon_month[d]==6:
      if tithi_sunrise[d]==3 or tithi_sunrise[d]==4:
        t_11 = get_tithi(jd_sunrise[d]+(jd_sunset[d]-jd_sunrise[d])*(2.0/5.0))#madhyahna1 start
        t_12 = get_tithi(jd_sunrise[d]+(jd_sunset[d]-jd_sunrise[d])*(3.0/5.0))#madhyahna1 end 
        t_21 = get_tithi(jd_sunrise[d+1]+(jd_sunset[d+1]-jd_sunrise[d+1])*(2.0/5.0))#madhyahna2 start
        t_22 = get_tithi(jd_sunrise[d+1]+(jd_sunset[d+1]-jd_sunrise[d+1])*(3.0/5.0))#madhyahna2 end
        if t_11==4 or t_12==4:
          if t_21==4 or t_22==4:
            festival_day_list[vchaturthi[script]]=[d+1]
          else:
            festival_day_list[vchaturthi[script]]=[d]

  #Add saved festivals
  festival_day_list[gayatri_japam[script]]=[festival_day_list[yajur_upakarma[script]][0]+1]
  festival_day_list[varalakshmi_vratam[script]]=[festival_day_list[yajur_upakarma[script]][0]-((weekday_start-1+festival_day_list[yajur_upakarma[script]][0]-5)%7)]

  for x in iter(festival_day_list.keys()):
    for j in range(0,len(festival_day_list[x])):
      if festivals[festival_day_list[x][j]]!='':
        festivals[festival_day_list[x][j]]+='\\\\'
      festivals[festival_day_list[x][j]]+=x



  ###--- ECLIPSES ---###
  ###--- LUNAR ECLIPSES ---###
  swisseph.set_topo(lon=longitude,lat=latitude,alt=0.0) #Set location
  jd = jd_start
  while 1:
    next_ecl_lun=swisseph.lun_eclipse_when(jd)
    jd=next_ecl_lun[1][0]+(tz_off/24.0)
    jd_ecl_lun_start=next_ecl_lun[1][2]+(tz_off/24.0)
    jd_ecl_lun_end=next_ecl_lun[1][3]+(tz_off/24.0)
    ecl_y=swisseph.revjul(jd-1)[0]# -1 is to not miss an eclipse that occurs after sunset on 31-Dec!
    if ecl_y!=start_year:
      break
    else:
      ecl_lun_start = swisseph.revjul(jd_ecl_lun_start)[3]
      ecl_lun_end   = swisseph.revjul(jd_ecl_lun_end)[3]
      if (jd_ecl_lun_start-(tz_off/24.0))==0.0 or (jd_ecl_lun_end-(tz_off/24.0))==0.0:
        jd=jd+20 #Move towards the next eclipse... at least the next full moon (>=25 days away)
        continue
      fday=int(math.floor(jd_ecl_lun_start)-math.floor(jd_start)+1)
      #print '%%',jd,fday,jd_sunrise[fday],jd_sunrise[fday-1]
      if (jd<(jd_sunrise[fday]+tz_off/24.0)):
        fday-=1
      if ecl_lun_start<swisseph.revjul(jd_sunrise[fday+1]+tz_off/24.0)[3]:
        ecl_lun_start+=24
      #print '%%',jd,fday,jd_sunrise[fday],jd_sunrise[fday-1],ecl_lun_start, ecl_lun_end
      jd_moonrise_ecl_day=swisseph.rise_trans(jd_start=jd_sunrise[fday],body=swisseph.MOON,
        lon=longitude,lat=latitude,rsmi=swisseph.CALC_RISE|swisseph.BIT_DISC_CENTER)[1][0]+(tz_off/24.0)
      jd_moonset_ecl_day=swisseph.rise_trans(jd_start=jd_moonrise_ecl_day,body=swisseph.MOON,
        lon=longitude,lat=latitude,rsmi=swisseph.CALC_SET|swisseph.BIT_DISC_CENTER)[1][0]+(tz_off/24.0)
      #if jd_ecl_lun_start<(jd_sunrise[fday]+(tz_off/24.0)):
      if ecl_lun_end < ecl_lun_start:
        ecl_lun_end+=24
      #print '%%', (jd_ecl_lun_start), (jd_ecl_lun_end), (jd_moonrise_ecl_day), (jd_moonset_ecl_day)
      #print '%%', swisseph.revjul(jd_ecl_lun_start), swisseph.revjul(jd_ecl_lun_end), swisseph.revjul(jd_moonrise_ecl_day), swisseph.revjul(jd_moonset_ecl_day)
      if jd_ecl_lun_end<jd_moonrise_ecl_day or jd_ecl_lun_start>jd_moonset_ecl_day:
        jd=jd+20 #Move towards the next eclipse... at least the next full moon (>=25 days away)
        continue
      lun_ecl_str = chandra_grahanam[script]+'~\\textsf{'+print_time2(ecl_lun_start)+'}{\\RIGHTarrow}\\textsf{'+print_time2(ecl_lun_end)+'}'
      if festivals[fday]!='':
        festivals[fday]+='\\\\'
      festivals[fday]+=lun_ecl_str
    jd=jd+20
      
  ###--- SOLAR ECLIPSES ---###
  swisseph.set_topo(lon=longitude,lat=latitude,alt=0.0) #Set location
  jd = jd_start
  while 1:
    next_ecl_sol=swisseph.sol_eclipse_when_loc(julday=jd,lon=longitude,lat=latitude)
    jd=next_ecl_sol[1][0]+(tz_off/24.0)
    jd_ecl_sol_start=next_ecl_sol[1][1]+(tz_off/24.0)
    jd_ecl_sol_end=next_ecl_sol[1][4]+(tz_off/24.0)
    ecl_y=swisseph.revjul(jd-1)[0]# -1 is to not miss an eclipse that occurs after sunset on 31-Dec!
    if ecl_y!=start_year:
      break
    else:
      #print '%%', fday, (jd_ecl_sol_start), (jd_ecl_sol_end), (jd_sunrise[fday])
      #print '%%', swisseph.revjul(jd_ecl_sol_start), swisseph.revjul(jd_ecl_sol_end), swisseph.revjul(jd_sunrise[fday])
      fday=int(math.floor(jd)-math.floor(jd_start)+1)
      if (jd<(jd_sunrise[fday]+tz_off/24.0)):
        fday-=1
      #print '%%', fday, (jd_ecl_sol_start), (jd_ecl_sol_end), (jd_sunrise[fday])
      #print '%%', swisseph.revjul(jd_ecl_sol_start), swisseph.revjul(jd_ecl_sol_end), swisseph.revjul(jd_sunrise[fday])
      ecl_sol_start = swisseph.revjul(jd_ecl_sol_start)[3]
      ecl_sol_end   = swisseph.revjul(jd_ecl_sol_end)[3]
      if (jd_ecl_sol_start-(tz_off/24.0))==0.0 or (jd_ecl_sol_end-(tz_off/24.0))==0.0:# or jd_ecl_end<jd_sunrise[fday] or jd_ecl_start>jd_sunset[fday]:
        jd=jd+20 #Move towards the next eclipse... at least the next new moon (>=25 days away)
        continue
      if ecl_sol_end < ecl_sol_start:
        ecl_sol_end+=24
      sol_ecl_str = surya_grahanam[script]+'~\\textsf{'+print_time2(ecl_sol_start)+'}{\\RIGHTarrow}\\textsf{'+print_time2(ecl_sol_end)+'}'
      if festivals[fday]!='':
        festivals[fday]+='\\\\'
      festivals[fday]+=sol_ecl_str
    jd=jd+20
  ###--- FESTIVAL ADDITIONS COMPLETE ---###

  ###--- PRINT LIST OF FESTIVALS (Page 2) ---###
  if script=='en':
    cal = Calendar()

  print '\\newpage'
  print '\\centerline {\\LARGE {{%s}}}\\mbox{}\\\\[2cm]' % list_of_festivals[script]
  print '\\begin{center}'
  print '\\begin{minipage}[t]{0.3\\linewidth}'
  print '\\begin{center}'
  print '\\begin{tabular}{>{\\sffamily}r>{\\sffamily}r>{\\sffamily}cp{6cm}}'

  mlast=1
  for d in range(1,367):
    jd = jd_start-1+d
    [y,m,dt,t] = swisseph.revjul(jd)
    weekday = (weekday_start -1 + d)%7 
   
    if festivals[d]!='':
      if m!=mlast:
        mlast=m
        #print '\\hline\\\\'
        print '\\\\'
        if m==5 or m==9:
          print '\\end{tabular}'
          print '\\end{center}'
          print '\\end{minipage}\hspace{1cm}%'
          print '\\begin{minipage}[t]{0.3\\linewidth}'
          print '\\begin{center}'
          print '\\begin{tabular}{>{\\sffamily}r>{\\sffamily}l>{\\sffamily}cp{6cm}}'
          
      print '%s & %s & %s & {\\raggedright %s} \\\\' % (MON[m],dt,WDAY[weekday],festivals[d])

      if script=='en':
        event = Event()
        event.add('summary',festivals[d])
        event.add('dtstart',datetime(y,m,dt))
        event.add('dtend',datetime(y,m,dt))
        cal.add_component(event)

    if m==12 and dt==31:
      break

  print '\\end{tabular}'
  print '\\end{center}'
  print '\\end{minipage}'
  print '\\end{center}'
  print '\\clearpage'

  if script=='en':
    cal_fname = '%s-%4d.ics' %(city_name,start_year)
    cal_file = open(cal_fname,'w')
    cal_file.write(cal.as_string())
    cal_file.close()

  #Layout calendar in LATeX format
  #We use a separate loop here, because of festivals like varalakshmi
  #vratam, for which we backtrack to the previous friday from yajur
  #upakarma and change the list of festivals!

  for d in range(1,367):
    jd = jd_start-1+d
    [y,m,dt,t] = swisseph.revjul(jd)
    weekday = (weekday_start -1 + d)%7 

    if dt==1:
      if m>1:
        if weekday!=0: #Space till Sunday
          for i in range(weekday,6):
            print "{}  &"
          print "\\\\ \hline"
        print '\end{tabular}'
        print '\n\n'
  
      #Begin tabular
      print '\\begin{tabular}{|c|c|c|c|c|c|c|}'
      print '\multicolumn{7}{c}{\Large \\bfseries \sffamily %s %s}\\\\[3mm]' % (month[m],y)
      print '\hline'
      print '\\textbf{\\textsf{SUN}} & \\textbf{\\textsf{MON}} & \\textbf{\\textsf{TUE}} & \\textbf{\\textsf{WED}} & \\textbf{\\textsf{THU}} & \\textbf{\\textsf{FRI}} & \\textbf{\\textsf{SAT}} \\\\ \hline'
      #print '\\textbf{भानु} & \\textbf{इन्दु} & \\textbf{भौम} & \\textbf{बुध} & \\textbf{गुरु} & \\textbf{भृगु} & \\textbf{स्थिर} \\\\ \hline'
  
      #Blanks for previous weekdays
      for i in range(0,weekday):
        print "{}  &"

    print '\caldata{\\textcolor{%s}{%s}}{%s{%s}}{\\sundata{%s}{%s}{%s}}{\\tnyk{%s}{%s}{%s}{%s}}{\\rahuyama{%s}{%s}}{%s} ' % (daycol[weekday],
      dt,month_data[d],get_chandra_masa(moon_month[d],chandra_masa_names,script),sunrise[d],sunset[d],madhya[d],tithi_data_string[d],nakshatram_data_string[d],
      yogam_data_string[d],karanam_data_string[d],rahu[d],yama[d],festivals[d])
  
    if weekday==6:
      print "\\\\ \hline"
    else:
      print "&"
  
    if m==12 and dt==31:
      break
  
    # For debugging specific dates
    #if m==4 and dt==10:
    #  break
  
  for i in range(weekday+1,6):
    print "{}  &"
  if weekday!=6:
    print "\\\\ \hline"
  print '\end{tabular}'
  print '\n\n'
  
  print template_lines[-2][:-1]
  print template_lines[-1][:-1]
Пример #28
0
  total = 0
  for i in range(len(x)):
    numer = 1
    denom = 1
    for j in range(len(x)):
      if j != i:
        numer *= (ya - y[j])
        denom *= (y[i] - y[j])

    total += numer * x[i] / denom

  return total

# Julian Day number as on (year, month, day) at 00:00 UTC
gregorian_to_jd = lambda date: swe.julday(date.year, date.month, date.day, 0.0)
jd_to_gregorian = lambda jd: swe.revjul(jd, swe.GREG_CAL)   # returns (y, m, d, h, min, s)

def local_time_to_jdut1(year, month, day, hour = 0, minutes = 0, seconds = 0, timezone = 0.0):
  """Converts local time to JD(UT1)"""
  y, m, d, h, mnt, s = swe.utc_time_zone(year, month, day, hour, minutes, seconds, timezone)
  # BUG in pyswisseph: replace 0 by s
  jd_et, jd_ut1 = swe.utc_to_jd(y, m, d, h, mnt, 0, flag = swe.GREG_CAL)
  return jd_ut1

def nakshatra_pada(longitude):
  """Gives nakshatra (1..27) and paada (1..4) in which given longitude lies"""
  # 27 nakshatras span 360°
  one_star = (360 / 27)  # = 13°20'
  # Each nakshatra has 4 padas, so 27 x 4 = 108 padas in 360°
  one_pada = (360 / 108) # = 3°20'
  quotient = int(longitude / one_star)
Пример #29
0
    assert(mahadasa[adhipati(satabhisha)] == 18)
    assert(adhipati(citta) == swe.MARS)
    assert(mahadasa[adhipati(citta)] == 7)
    assert(adhipati(aslesha) == swe.MERCURY)
    assert(mahadasa[adhipati(aslesha)] == 17)


if __name__ == "__main__":
    adhipati_tests()
    # YYYY-MM-DD 09:40 IST = 04:10 UTC
    jdut1 = swe.utc_to_jd(1985, 6, 9, 4, 10, 0, flag = swe.GREG_CAL)[1]
    tz = 5.5
    print("jdut1", jdut1)
    dashas = vimsottari_mahadasa(jdut1)
    for i in dashas:
        print(' ---------- ' + get_planet_name(i) + ' Dasa ---------- ')
        bhuktis = vimsottari_bhukti(i, dashas[i])
        for j in bhuktis:
            jd = bhuktis[j]
            y, m, d, h = swe.revjul(round(jd + tz))
            print('%8s: %04d-%02d-%02d\t%.6lf' % (get_planet_name(j), y, m, d, jd))

    jd = 2456950       # Some random date, ex: current date
    i, j, antara = compute_antara_from(jd, dashas)
    print("---- JD %d falls in %s dasa/%s bhukti -----" %
          (jd, get_planet_name(i), get_planet_name(j)))
    for k in antara:
        jd = antara[k]
        y, m, d, h = swe.revjul(round(jd + tz))
        print('%8s: %04d-%02d-%02d\t%.6lf' % (get_planet_name(k), y, m, d, jd))
Пример #30
0
 def logCalc(self, tjd):
     #in GMT!
     jy, jm, jd, jh = swisseph.revjul(tjd, 1)
     d, m, s = util.decToDeg(jh)
     print('GMT: %d.%d.%d %d:%d:%d' % (jy, jm, jd, d, m, s))
Пример #31
0
def calculateNearestEclipse(ecplanet,
                            chrt,
                            year,
                            month,
                            day,
                            hour,
                            minute=0,
                            second=0):
    out = []
    time = hour + minute / 60.0 + second / 3600.0
    tjd = swisseph.julday(year, month, day, time, astrology.SE_GREG_CAL)

    # Calculate the global eclipse nearest to the specified date
    if ecplanet == 'sun':
        retflag = swisseph.sol_eclipse_when_glob(
            tjd, astrology.SEFLG_SWIEPH, astrology.SE_ECL_ALLTYPES_SOLAR, True)
        planet_id = astrology.SE_SUN
    elif ecplanet == 'moon':
        retflag = swisseph.lun_eclipse_when(tjd, astrology.SEFLG_SWIEPH,
                                            astrology.SE_ECL_ALLTYPES_LUNAR,
                                            True)
        planet_id = astrology.SE_MOON
    else:
        print('No valid eclipse ecplanet input at calculateNearestEclipse\n')
        exit(1)

    # Get date and eclipse type
    ejd = retflag[1][0]
    eclflag = retflag[0][0]
    # Convert julian to gregorian date
    eyear, emonth, eday, ejtime = swisseph.revjul(ejd, astrology.SE_GREG_CAL)
    ehour, eminute, esecond = util.decToDeg(ejtime)

    if (eclflag & astrology.SE_ECL_TOTAL):
        ecltype = 'total'
    elif (eclflag & astrology.SE_ECL_ANNULAR):
        ecltype = 'annular'
    elif (eclflag & astrology.SE_ECL_ANNULAR_TOTAL):
        ecltype = 'anntotal'
    elif (eclflag & astrology.SE_ECL_PARTIAL):
        ecltype = 'partial'
    elif (eclflag & astrology.SE_ECL_PENUMBRAL):
        ecltype = 'penumbral'
    else:
        ecltype = ''

    ecldate = 'GMT: %s - %s - %d-%d-%d %d:%d:%d' % (
        ecplanet, ecltype, eyear, emonth, eday, ehour, eminute, esecond)

    # Calculate the sun position for GMT
    if eclipses_cache.has_key(ecldate):
        lon = eclipses_cache[ecldate]
    else:
        day_time = chart.event.DateTime(eyear, emonth, eday, ehour, eminute,
                                        esecond, False, 0, 0, False, 0, 0, 0,
                                        chrt.place)
        day_chart = chart.Chart(chrt.name, chrt.male, day_time, chrt.place,
                                chrt.htype, chrt.notes, chrt.options)
        lon = day_chart.planets.planets[planet_id].data[planets.Planet.LONG]
        eclipses_cache[ecldate] = lon

    # add to out buffer
    out.append("%.2f\t%s\t" % (lon, ecltype))
    # send out
    sys.stdout.write(''.join(out))
Пример #32
0
    for i in range(len(x)):
        numer = 1
        denom = 1
        for j in range(len(x)):
            if j != i:
                numer *= (ya - y[j])
                denom *= (y[i] - y[j])

        total += numer * x[i] / denom

    return total


# Julian Day number as on (year, month, day) at 00:00 UTC
gregorian_to_jd = lambda date: swe.julday(date.year, date.month, date.day, 0.0)
jd_to_gregorian = lambda jd: swe.revjul(jd, swe.GREG_CAL
                                        )  # returns (y, m, d, h, min, s)


def solar_longitude(jd):
    """Solar longitude at given instant (julian day) jd"""
    data = swe.calc_ut(jd, swe.SUN, flag=swe.FLG_SWIEPH)
    return data[0]  # in degrees


def lunar_longitude(jd):
    """Lunar longitude at given instant (julian day) jd"""
    data = swe.calc_ut(jd, swe.MOON, flag=swe.FLG_SWIEPH)
    return data[0]  # in degrees


def lunar_latitude(jd):
Пример #33
0
import swisseph as swe
#swe.set_ephe_path('/usr/share/ephe') # set path to ephemeris files
now = swe.julday(2007, 3, 3)  # get Julian day number
res = swe.lun_eclipse_when(now)  # find next lunar eclipse (from now on)
ecltime = swe.revjul(res[1][0])  # get date UTC
print(ecltime)
Пример #34
0
    def calcTimes(self):
        #the date we get from julianday is the same as year, month day in Time-class but we didn't pass it to the init function.
        oyear, omonth, oday, otim = swisseph.revjul(self.jd, self.calflag)

        numangles = len(RiseSet.Angles)
        for i in range(planets.Planets.PLANETS_NUM):  #Nodes are excluded
            ar = []

            #Rise
            # TODO: ret, risetime = swisseph.rise_trans(jd, astrology.SE_SUN, lon, lat, float(altitude), 0.0, 10.0, astrology.SE_CALC_RISE, astrology.SEFLG_SWIEPH)
            ret, JDRise = swisseph.rise_trans(self.jd, i, self.lon, self.lat,
                                              self.alt, 0.0, 10.0,
                                              RiseSet.Angles[RiseSet.RISE],
                                              astrology.SEFLG_SWIEPH)
            tyear, tmonth, tday, ttim = swisseph.revjul(
                JDRise[0], self.calflag)
            if oyear != tyear or omonth != tmonth or oday != tday:
                ret, JDRise = swisseph.rise_trans(self.jd - 1.0, i, self.lon,
                                                  self.lat, self.alt, 0.0,
                                                  10.0,
                                                  RiseSet.Angles[RiseSet.RISE],
                                                  astrology.SEFLG_SWIEPH)

            #MC
            ret, JDMC = swisseph.rise_trans(self.jd, i, self.lon, self.lat,
                                            self.alt, 0.0, 10.0,
                                            RiseSet.Angles[RiseSet.MC],
                                            astrology.SEFLG_SWIEPH)
            tyear, tmonth, tday, ttim = swisseph.revjul(JDMC[0], self.calflag)
            if oyear != tyear or omonth != tmonth or oday != tday:
                ret, JDMC = swisseph.rise_trans(self.jd - 1.0, i, self.lon,
                                                self.lat, self.alt, 0.0, 10.0,
                                                RiseSet.Angles[RiseSet.MC],
                                                astrology.SEFLG_SWIEPH)

            #Set
            ret, JDSet = swisseph.rise_trans(self.jd, i, self.lon, self.lat,
                                             self.alt, 0.0, 10.0,
                                             RiseSet.Angles[RiseSet.SET],
                                             astrology.SEFLG_SWIEPH)
            tyear, tmonth, tday, ttim = swisseph.revjul(JDSet[0], self.calflag)
            if oyear != tyear or omonth != tmonth or oday != tday:
                ret, JDSet = swisseph.rise_trans(self.jd - 1.0, i, self.lon,
                                                 self.lat, self.alt, 0.0, 10.0,
                                                 RiseSet.Angles[RiseSet.SET],
                                                 astrology.SEFLG_SWIEPH)

            #IC
            ret, JDIC = swisseph.rise_trans(self.jd, i, self.lon, self.lat,
                                            self.alt, 0.0, 10.0,
                                            RiseSet.Angles[RiseSet.IC],
                                            astrology.SEFLG_SWIEPH)
            tyear, tmonth, tday, ttim = swisseph.revjul(JDIC[0], self.calflag)
            if oyear != tyear or omonth != tmonth or oday != tday:
                ret, JDIC = swisseph.rise_trans(self.jd - 1.0, i, self.lon,
                                                self.lat, self.alt, 0.0, 10.0,
                                                RiseSet.Angles[RiseSet.IC],
                                                astrology.SEFLG_SWIEPH)

            #From GMT to Local
#           JDRise += self.offs
            year, month, day, hr = swisseph.revjul(JDRise[0], self.calflag)
            ar.append(hr)

            #           JDMC += self.offs
            year, month, day, hr = swisseph.revjul(JDMC[0], self.calflag)
            ar.append(hr)

            #           JDSet += self.offs
            year, month, day, hr = swisseph.revjul(JDSet[0], self.calflag)
            ar.append(hr)

            #           JDIC += self.offs
            year, month, day, hr = swisseph.revjul(JDIC[0], self.calflag)
            ar.append(hr)

            self.times.append(ar)
Пример #35
0
    min_temp, hour = math.modf(temp[3])
    sec_temp, min = math.modf(min_temp * 60)
    sub_sec, sec = math.modf(sec_temp * 60)
    return datetime.datetime(year, month, day, int(hour), int(min), int(sec))


# ###lunar eclipses
print 'When next Lunar Eclipse'
print '------------------------'
now = swe.julday(2016, 3, 23)
time_zone = 0  # we have to look up time zone from lat/long
res = swe.lun_eclipse_when(now)
res_how = swe.lun_eclipse_how(res[1][0], 139.7, 35.68)
print res
print res_how
eclip_time = swe.revjul(res[1][0])  # utc
# print len(res[1]),res[0],res[1],eclip_time,bin(res[0][0])
ecl_central = int('00000001', 2)
central = res[0][0] & ecl_central
if central == 1:
    print 'Eclipse Central'
ecl_noncentral = int('00000010', 2)
central = res[0][0] & ecl_noncentral
if central == 2:
    print 'Eclipse Non Central'
eclipse_total = int('00000100', 2)
central = res[0][0] & eclipse_total
if central == 4:
    print 'Eclipse Total'
    print 'Start        ', date_convert(res[1][6]) + datetime.timedelta(hours=time_zone)
    print 'Start partial', date_convert(res[1][2]) + datetime.timedelta(hours=time_zone)
Пример #36
0
 def julian_day_to_local_time(self, julian_day):
   [y, m, dt, time_in_hours] = swe.revjul(julian_day)
   (hours, minutes, seconds) = decypher_fractional_hours(time_in_hours=time_in_hours)
   local_time = swe.utc_time_zone(y, m, dt, hours, minutes, seconds, -self.get_timezone_offset_hours_from_jd(julian_day))
   return local_time
def writeDailyTeX(panchangam, template_file, compute_lagnams=True, output_stream=None):
    """Write out the panchangam TeX using a specified template
    """
    # day_colours = {0: 'blue', 1: 'blue', 2: 'blue',
    #                3: 'blue', 4: 'blue', 5: 'blue', 6: 'blue'}
    month = {1: 'JANUARY', 2: 'FEBRUARY', 3: 'MARCH', 4: 'APRIL',
             5: 'MAY', 6: 'JUNE', 7: 'JULY', 8: 'AUGUST', 9: 'SEPTEMBER',
             10: 'OCTOBER', 11: 'NOVEMBER', 12: 'DECEMBER'}
    WDAY = {0: 'Sun', 1: 'Mon', 2: 'Tue', 3: 'Wed', 4: 'Thu', 5: 'Fri', 6: 'Sat'}

    template_lines = template_file.readlines()
    for i in range(len(template_lines)):
        print(template_lines[i][:-1], file=output_stream)

    kali_year_start = panchangam.start_date[0] + 3100 + (panchangam.solar_month[1] == 1)
    kali_year_end = panchangam.end_date[0] + 3100 + (panchangam.solar_month[panchangam.duration] == 1)
    # Aligning to prabhava cycle from Kali start (+12 below)
    samvatsara_names = [jyotisha.panchangam.temporal.NAMES['SAMVATSARA_NAMES'][panchangam.script][(_x + 12) % 60 + 1] for _x in list(range(kali_year_start, kali_year_end + 1))]
    yname = samvatsara_names[0]  # Assign year name until Mesha Sankranti

    print('\\mbox{}', file=output_stream)
    print('\\renewcommand{\\yearname}{%d}' % panchangam.start_date[0], file=output_stream)
    print('\\begin{center}', file=output_stream)
    print('{\\sffamily \\fontsize{20}{20}\\selectfont  %4d-%02d-%02d–%4d-%02d-%02d\\\\[0.5cm]}'
          % (panchangam.start_date[0], panchangam.start_date[1], panchangam.start_date[2], panchangam.end_date[0], panchangam.end_date[1], panchangam.end_date[2]), file=output_stream)

    print('\\mbox{\\fontsize{48}{48}\\selectfont %s}\\\\'
          % ('–'.join(list(set(samvatsara_names[:2])))), file=output_stream)
    print('\\mbox{\\fontsize{32}{32}\\selectfont %s } %%'
          % jyotisha.custom_transliteration.tr('kali', panchangam.script), file=output_stream)
    print('{\\sffamily \\fontsize{43}{43}\\selectfont  %s\\\\[0.5cm]}\n\\hrule\n\\vspace{0.2cm}'
          % '–'.join([str(_y) for _y in set([kali_year_start, kali_year_end])]), file=output_stream)
    print('{\\sffamily \\fontsize{50}{50}\\selectfont  \\uppercase{%s}\\\\[0.2cm]}' % panchangam.city.name, file=output_stream)
    print('{\\sffamily \\fontsize{23}{23}\\selectfont  {%s}\\\\[0.2cm]}'
          % jyotisha.custom_transliteration.print_lat_lon(panchangam.city.latitude, panchangam.city.longitude), file=output_stream)
    print('\\hrule', file=output_stream)
    print('\\end{center}', file=output_stream)
    print('\\clearpage\\pagestyle{fancy}', file=output_stream)

    panchangam.calc_nakshatra_tyajyam(False)
    panchangam.calc_nakshatra_amrita(False)

    for d in range(1, panchangam.duration + 1):

        [y, m, dt, t] = swe.revjul(panchangam.jd_start_utc + d - 1)

        if m == 1 and dt == 1:
            print('\\renewcommand{\\yearname}{%d}' % y, file=output_stream)

        # What is the jd at 00:00 local time today?
        jd = panchangam.jd_midnight[d]

        tithi_data_str = ''
        for tithi_ID, tithi_end_jd in panchangam.tithi_data[d]:
            if tithi_data_str != '':
                tithi_data_str += '\\hspace{1ex}'
            tithi = '\\raisebox{-1pt}{\moon[scale=0.8]{%d}}\\hspace{2pt}' % (tithi_ID) + \
                    jyotisha.panchangam.temporal.NAMES['TITHI_NAMES'][panchangam.script][tithi_ID]
            if tithi_end_jd is None:
                tithi_data_str = '%s\\mbox{%s\\To{}%s\\tridina}' % \
                                 (tithi_data_str, tithi, jyotisha.custom_transliteration.tr('ahOrAtram', panchangam.script))
            else:
                tithi_data_str = '%s\\mbox{%s\\To{}\\textsf{%s (%s)}}' % \
                                 (tithi_data_str, tithi,
                                  jyotisha.panchangam.temporal.Time(24 * (tithi_end_jd - panchangam.jd_sunrise[d])).toString(format='gg-pp'),
                                  jyotisha.panchangam.temporal.Time(24 * (tithi_end_jd - jd)).toString(format=panchangam.fmt))
        if len(panchangam.tithi_data[d]) == 2:
            tithi_data_str += '\\avamA{}'

        nakshatram_data_str = ''
        amritadi_yoga_list = []
        for nakshatram_ID, nakshatram_end_jd in panchangam.nakshatram_data[d]:
            if nakshatram_data_str != '':
                nakshatram_data_str += '\\hspace{1ex}'
            nakshatram = jyotisha.panchangam.temporal.NAMES['NAKSHATRAM_NAMES'][panchangam.script][nakshatram_ID]
            if len(amritadi_yoga_list) == 0:  # Otherwise, we would have already added in the previous run of this for loop
                amritadi_yoga_list.append(jyotisha.panchangam.temporal.AMRITADI_YOGA[panchangam.weekday[d]][nakshatram_ID])
            if nakshatram_end_jd is None:
                nakshatram_data_str = '%s\\mbox{%s\\To{}%s}' % \
                                      (nakshatram_data_str, nakshatram,
                                       jyotisha.custom_transliteration.tr('ahOrAtram', panchangam.script))
            else:
                next_yoga = jyotisha.panchangam.temporal.AMRITADI_YOGA[panchangam.weekday[d]][(nakshatram_ID % 27) + 1]
                if amritadi_yoga_list[-1] != next_yoga:
                    amritadi_yoga_list.append(next_yoga)
                nakshatram_data_str = '%s\\mbox{%s\\To{}\\textsf{%s (%s)}}' % \
                                      (nakshatram_data_str, nakshatram,
                                       jyotisha.panchangam.temporal.Time(24 * (nakshatram_end_jd - panchangam.jd_sunrise[d])).toString(format='gg-pp'),
                                       jyotisha.panchangam.temporal.Time(24 * (nakshatram_end_jd - jd)).toString(format=panchangam.fmt))
        amritadi_yoga_str = '/'.join([jyotisha.custom_transliteration.tr(_x, panchangam.script) for _x in amritadi_yoga_list])
        if len(panchangam.nakshatram_data[d]) == 2:
            nakshatram_data_str += '\\avamA{}'

        if panchangam.tyajyam_data[d] == []:
          tyajyam_data_str = '---'
        else:
            tyajyam_data_str = ''
            for td in panchangam.tyajyam_data[d]:
                tyajyam_data_str += '%s--%s\\hspace{2ex}' % (jyotisha.panchangam.temporal.Time(24 * (td[0] - jd)).toString(format=panchangam.fmt), jyotisha.panchangam.temporal.Time(24 * (td[1] - jd)).toString(format=panchangam.fmt))

        if panchangam.amrita_data[d] == []:
          amrita_data_str = '---'
        else:
            amrita_data_str = ''
            for td in panchangam.amrita_data[d]:
                amrita_data_str += '%s--%s\\hspace{2ex}' % (jyotisha.panchangam.temporal.Time(24 * (td[0] - jd)).toString(format=panchangam.fmt), jyotisha.panchangam.temporal.Time(24 * (td[1] - jd)).toString(format=panchangam.fmt))

        rashi_data_str = 'चन्द्रराशिः—'
        for rashi_ID, rashi_end_jd in panchangam.rashi_data[d]:
            # if rashi_data_str != '':
            #     rashi_data_str += '\\hspace{1ex}'
            rashi = jyotisha.panchangam.temporal.NAMES['RASHI_NAMES'][panchangam.script][rashi_ID]
            if rashi_end_jd is None:
                rashi_data_str = '%s\\mbox{%s}' % (rashi_data_str, rashi)
            else:
                rashi_data_str = '%s\\mbox{%s\\RIGHTarrow\\textsf{%s}}' % \
                                 (rashi_data_str, rashi,
                                  jyotisha.panchangam.temporal.Time(24 * (rashi_end_jd - jd)).toString(format=panchangam.fmt))

        chandrashtama_rashi_data_str = 'चन्द्राष्टम-राशिः—'
        for rashi_ID, rashi_end_jd in panchangam.rashi_data[d]:
            rashi = jyotisha.panchangam.temporal.NAMES['RASHI_NAMES'][panchangam.script][rashi_ID]
            if rashi_end_jd is None:
                chandrashtama_rashi_data_str = '\\mbox{%s%s}' % (chandrashtama_rashi_data_str, jyotisha.panchangam.temporal.NAMES['RASHI_NAMES'][panchangam.script][((rashi_ID - 8) % 12) + 1])
            else:
                chandrashtama_rashi_data_str = '\\mbox{%s%s\To{}\\textsf{%s}}' % (chandrashtama_rashi_data_str, jyotisha.panchangam.temporal.NAMES['RASHI_NAMES'][panchangam.script][((rashi_ID - 8) % 12) + 1], jyotisha.panchangam.temporal.Time(24 * (rashi_end_jd - jd)).toString(format=panchangam.fmt))

        SHULAM = [('pratIcyAm', 12, 'guDam'), ('prAcyAm', 8, 'dadhi'), ('udIcyAm', 12, 'kSIram'),
                  ('udIcyAm', 16, 'kSIram'), ('dakSiNAyAm', 20, 'tailam'), ('pratIcyAm', 12, 'guDam'),
                  ('prAcyAm', 8, 'dadhi')]
        shulam_end_jd = panchangam.jd_sunrise[d] + (panchangam.jd_sunset[d] - panchangam.jd_sunrise[d]) * (SHULAM[panchangam.weekday[d]][1] / 30)
        shulam_data_str = '%s—%s (\\RIGHTarrow\\textsf{%s})  %s–%s' % (jyotisha.custom_transliteration.tr('zUlam', panchangam.script),
                                                                       jyotisha.custom_transliteration.tr(SHULAM[panchangam.weekday[d]][0], panchangam.script),
                                                                       jyotisha.panchangam.temporal.Time(24 * (shulam_end_jd - jd)).toString(format=panchangam.fmt),
                                                                       jyotisha.custom_transliteration.tr('parihAraH', panchangam.script),
                                                                       jyotisha.custom_transliteration.tr(SHULAM[panchangam.weekday[d]][2], panchangam.script))

        if compute_lagnams:
            lagna_data_str = 'लग्नानि–'
            for lagna_ID, lagna_end_jd in panchangam.lagna_data[d]:
                lagna = jyotisha.panchangam.temporal.NAMES['RASHI_NAMES'][panchangam.script][lagna_ID]
                lagna_data_str = '%s\\mbox{%s\\RIGHTarrow\\textsf{%s}} ' % \
                                 (lagna_data_str, lagna,
                                  jyotisha.panchangam.temporal.Time(24 * (lagna_end_jd - jd)).toString(format=panchangam.fmt))

        yoga_data_str = ''
        for yoga_ID, yoga_end_jd in panchangam.yoga_data[d]:
            # if yoga_data_str != '':
            #     yoga_data_str += '\\hspace{1ex}'
            yoga = jyotisha.panchangam.temporal.NAMES['YOGA_NAMES'][panchangam.script][yoga_ID]
            if yoga_end_jd is None:
                yoga_data_str = '%s\\mbox{%s\\To{}%s}' % \
                                (yoga_data_str, yoga, jyotisha.custom_transliteration.tr('ahOrAtram', panchangam.script))
            else:
                yoga_data_str = '%s\\mbox{%s\\To{}\\textsf{%s (%s)}}\\hspace{1ex}' % \
                                (yoga_data_str, yoga,
                                 jyotisha.panchangam.temporal.Time(24 * (yoga_end_jd - panchangam.jd_sunrise[d])).toString(format='gg-pp'),
                                 jyotisha.panchangam.temporal.Time(24 * (yoga_end_jd - jd)).toString(format=panchangam.fmt))
        if yoga_end_jd is not None:
            yoga_data_str += '\\mbox{%s\\Too{}}' % (jyotisha.panchangam.temporal.NAMES['YOGA_NAMES'][panchangam.script][(yoga_ID % 27) + 1])

        karanam_data_str = ''
        for numKaranam, (karanam_ID, karanam_end_jd) in enumerate(panchangam.karanam_data[d]):
            # if numKaranam == 1:
            #     karanam_data_str += '\\hspace{1ex}'
            karanam = jyotisha.panchangam.temporal.NAMES['KARANAM_NAMES'][panchangam.script][karanam_ID]
            if karanam_end_jd is None:
                karanam_data_str = '%s\\mbox{%s\\To{}%s}' % \
                                   (karanam_data_str, karanam, jyotisha.custom_transliteration.tr('ahOrAtram', panchangam.script))
            else:
                karanam_data_str = '%s\\mbox{%s\\To{}\\textsf{%s (%s)}}\\hspace{1ex}' % \
                                   (karanam_data_str, karanam,
                                    jyotisha.panchangam.temporal.Time(24 * (karanam_end_jd - panchangam.jd_sunrise[d])).toString(format='gg-pp'),
                                    jyotisha.panchangam.temporal.Time(24 * (karanam_end_jd - jd)).toString(format=panchangam.fmt))
        if karanam_end_jd is not None:
            karanam_data_str += '\\mbox{%s\\Too{}}' % (jyotisha.panchangam.temporal.NAMES['KARANAM_NAMES'][panchangam.script][(karanam_ID % 60) + 1])

        if panchangam.shraaddha_tithi[d] == [None]:
            stithi_data_str = '---'
        else:
            if panchangam.shraaddha_tithi[d][0] == 0:
                stithi_data_str = jyotisha.custom_transliteration.tr('zUnyatithiH', panchangam.script)
            else:
                t1 = jyotisha.panchangam.temporal.NAMES['TITHI_NAMES'][panchangam.script][panchangam.shraaddha_tithi[d][0]]
                if len(panchangam.shraaddha_tithi[d]) == 2:
                    t2 = jyotisha.panchangam.temporal.NAMES['TITHI_NAMES'][panchangam.script][panchangam.shraaddha_tithi[d][1]]
                    stithi_data_str = '%s/%s (%s)' % \
                                      (t1.split('-')[-1], t2.split('-')[-1], jyotisha.custom_transliteration.tr('tithidvayam', panchangam.script))
                else:
                    stithi_data_str = '%s' % (t1.split('-')[-1])

        sunrise = jyotisha.panchangam.temporal.Time(24 * (panchangam.jd_sunrise[d] - jd)).toString(format=panchangam.fmt)
        sunset = jyotisha.panchangam.temporal.Time(24 * (panchangam.jd_sunset[d] - jd)).toString(format=panchangam.fmt)
        moonrise = jyotisha.panchangam.temporal.Time(24 * (panchangam.jd_moonrise[d] - jd)).toString(format=panchangam.fmt)
        moonset = jyotisha.panchangam.temporal.Time(24 * (panchangam.jd_moonset[d] - jd)).toString(format=panchangam.fmt)

        braahma_start = jyotisha.panchangam.temporal.Time(24 * (panchangam.kaalas[d]['braahma'][0] - jd)).toString(format=panchangam.fmt)
        pratahsandhya_start = jyotisha.panchangam.temporal.Time(24 * (panchangam.kaalas[d]['prAtaH sandhyA'][0] - jd)).toString(format=panchangam.fmt)
        pratahsandhya_end = jyotisha.panchangam.temporal.Time(24 * (panchangam.kaalas[d]['prAtaH sandhyA end'][0] - jd)).toString(format=panchangam.fmt)
        sangava = jyotisha.panchangam.temporal.Time(24 * (panchangam.kaalas[d]['saGgava'][0] - jd)).toString(format=panchangam.fmt)
        madhyaahna = jyotisha.panchangam.temporal.Time(24 * (panchangam.kaalas[d]['madhyAhna'][0] - jd)).toString(format=panchangam.fmt)
        madhyahnika_sandhya_start = jyotisha.panchangam.temporal.Time(24 * (panchangam.kaalas[d]['mAdhyAhnika sandhyA'][0] - jd)).toString(format=panchangam.fmt)
        madhyahnika_sandhya_end = jyotisha.panchangam.temporal.Time(24 * (panchangam.kaalas[d]['mAdhyAhnika sandhyA end'][0] - jd)).toString(format=panchangam.fmt)
        aparahna = jyotisha.panchangam.temporal.Time(24 * (panchangam.kaalas[d]['aparAhna'][0] - jd)).toString(format=panchangam.fmt)
        sayahna = jyotisha.panchangam.temporal.Time(24 * (panchangam.kaalas[d]['sAyAhna'][0] - jd)).toString(format=panchangam.fmt)
        sayamsandhya_start = jyotisha.panchangam.temporal.Time(24 * (panchangam.kaalas[d]['sAyaM sandhyA'][0] - jd)).toString(format=panchangam.fmt)
        sayamsandhya_end = jyotisha.panchangam.temporal.Time(24 * (panchangam.kaalas[d]['sAyaM sandhyA end'][0] - jd)).toString(format=panchangam.fmt)
        ratriyama1 = jyotisha.panchangam.temporal.Time(24 * (panchangam.kaalas[d]['rAtri yAma 1'][0] - jd)).toString(format=panchangam.fmt)
        shayana_time_end = jyotisha.panchangam.temporal.Time(24 * (panchangam.kaalas[d]['zayana'][0] - jd)).toString(format=panchangam.fmt)
        dinanta = jyotisha.panchangam.temporal.Time(24 * (panchangam.kaalas[d]['dinAnta'][0] - jd)).toString(format=panchangam.fmt)

        rahu = '%s--%s' % (
            jyotisha.panchangam.temporal.Time(24 * (panchangam.kaalas[d]['rahu'][0] - jd)).toString(format=panchangam.fmt),
            jyotisha.panchangam.temporal.Time(24 * (panchangam.kaalas[d]['rahu'][1] - jd)).toString(format=panchangam.fmt))
        yama = '%s--%s' % (
            jyotisha.panchangam.temporal.Time(24 * (panchangam.kaalas[d]['yama'][0] - jd)).toString(format=panchangam.fmt),
            jyotisha.panchangam.temporal.Time(24 * (panchangam.kaalas[d]['yama'][1] - jd)).toString(format=panchangam.fmt))
        gulika = '%s--%s' % (
            jyotisha.panchangam.temporal.Time(24 * (panchangam.kaalas[d]['gulika'][0] - jd)).toString(format=panchangam.fmt),
            jyotisha.panchangam.temporal.Time(24 * (panchangam.kaalas[d]['gulika'][1] - jd)).toString(format=panchangam.fmt))

        if panchangam.solar_month[d] == 1 and panchangam.solar_month[d - 1] == 12 and d > 1:
            # Move to next year
            yname = samvatsara_names[samvatsara_names.index(yname) + 1]

        # Assign samvatsara, ayana, rtu #
        sar_data = '{%s}{%s}{%s}' % (yname,
                                     jyotisha.panchangam.temporal.NAMES['AYANA_NAMES'][panchangam.script][panchangam.tropical_month[d]],
                                     jyotisha.panchangam.temporal.NAMES['RTU_NAMES'][panchangam.script][panchangam.tropical_month[d]])

        if panchangam.solar_month_end_time[d] is None:
            month_end_str = ''
        else:
            _m = panchangam.solar_month[d - 1]
            if panchangam.solar_month_end_time[d] >= panchangam.jd_sunrise[d + 1]:
                month_end_str = '\\mbox{%s{\\tiny\\RIGHTarrow}\\textsf{%s}}' % (jyotisha.panchangam.temporal.NAMES['RASHI_NAMES'][panchangam.script][_m], jyotisha.panchangam.temporal.Time(24 * (panchangam.solar_month_end_time[d] - panchangam.jd_midnight[d + 1])).toString(format=panchangam.fmt))
            else:
                month_end_str = '\\mbox{%s{\\tiny\\RIGHTarrow}\\textsf{%s}}' % (jyotisha.panchangam.temporal.NAMES['RASHI_NAMES'][panchangam.script][_m], jyotisha.panchangam.temporal.Time(24 * (panchangam.solar_month_end_time[d] - panchangam.jd_midnight[d])).toString(format=panchangam.fmt))

        month_data = '\\sunmonth{%s}{%d}{%s}' % (jyotisha.panchangam.temporal.NAMES['RASHI_NAMES'][panchangam.script][panchangam.solar_month[d]], panchangam.solar_month_day[d], month_end_str)

        print('\\caldata{%s}{%s}{%s{%s}{%s}{%s}%s}' %
              (month[m], dt, month_data,
               jyotisha.panchangam.temporal.get_chandra_masa(panchangam.lunar_month[d],
                                                             jyotisha.panchangam.temporal.NAMES, panchangam.script),
               jyotisha.panchangam.temporal.NAMES['RTU_NAMES'][panchangam.script][int(ceil(panchangam.lunar_month[d]))],
               jyotisha.panchangam.temporal.NAMES['VARA_NAMES'][panchangam.script][panchangam.weekday[d]], sar_data), file=output_stream)

        if panchangam.jd_moonrise[d] > panchangam.jd_sunrise[d + 1]:
          moonrise = '---'
        if panchangam.jd_moonset[d] > panchangam.jd_sunrise[d + 1]:
          moonset = '---'

        if panchangam.jd_moonrise[d] < panchangam.jd_moonset[d]:
          print('{\\sunmoonrsdata{%s}{%s}{%s}{%s}' % (sunrise, sunset, moonrise, moonset), file=output_stream)
        else:
          print('{\\sunmoonsrdata{%s}{%s}{%s}{%s}' % (sunrise, sunset, moonrise, moonset), file=output_stream)

        print('{\kalas{%s %s %s %s %s %s %s %s %s %s %s %s %s %s}}}' % (braahma_start, pratahsandhya_start, pratahsandhya_end,
                                                                        sangava,
                                                                        madhyahnika_sandhya_start, madhyahnika_sandhya_end,
                                                                        madhyaahna, aparahna, sayahna,
                                                                        sayamsandhya_start, sayamsandhya_end,
                                                                        ratriyama1, shayana_time_end, dinanta), file=output_stream)
        if compute_lagnams:
            print('{\\tnykdata{%s}%%\n{%s}%%\n{%s}%%\n{%s}{%s}\n}'
                  % (tithi_data_str, nakshatram_data_str, yoga_data_str,
                     karanam_data_str, lagna_data_str), file=output_stream)
        else:
            print('{\\tnykdata{%s}%%\n{%s}%%\n{%s}%%\n{%s}{\\scriptsize %s}\n}'
                  % (tithi_data_str, nakshatram_data_str, yoga_data_str,
                     karanam_data_str, ''), file=output_stream)

        # Using set as an ugly workaround since we may have sometimes assigned the same
        # festival to the same day again!
        print('{%s}' % '\\eventsep '.join(
            [jyotisha.custom_transliteration.tr(f, panchangam.script).replace('★', '$^\\star$') for f in sorted(set(panchangam.festivals[d]))]), file=output_stream)

        print('{%s} ' % WDAY[panchangam.weekday[d]], file=output_stream)
        print('\\cfoot{\\rygdata{%s,%s,%s,%s,%s,%s,%s,%s,%s,%s}}' % (stithi_data_str, amritadi_yoga_str, rahu, yama, gulika, tyajyam_data_str, amrita_data_str, rashi_data_str, chandrashtama_rashi_data_str, shulam_data_str), file=output_stream)

    print('\\end{document}', file=output_stream)
def writeDailyText(panchangam,
                   compute_lagnams=True,
                   output_file_stream=sys.stdout):
    """Write out the panchangam TeX using a specified template
    """
    output_stream = StringIO()
    month = {
        1: 'January',
        2: 'February',
        3: 'March',
        4: 'April',
        5: 'May',
        6: 'June',
        7: 'July',
        8: 'August',
        9: 'September',
        10: 'October',
        11: 'November',
        12: 'December'
    }
    WDAY = {
        0: 'Sunday',
        1: 'Monday',
        2: 'Tuesday',
        3: 'Wednesday',
        4: 'Thursday',
        5: 'Friday',
        6: 'Saturday'
    }
    SHULAM = [('pratIcI dik', 12, 'guDam'), ('prAcI dik', 8, 'dadhi'),
              ('udIcI dik', 12, 'kSIram'), ('udIcI dik', 16, 'kSIram'),
              ('dakSiNA dik', 20, 'tailam'), ('pratIcI dik', 12, 'guDam'),
              ('prAcI dik', 8, 'dadhi')]

    samvatsara_id = (panchangam.year - 1568) % 60 + 1  # distance from prabhava
    samvatsara_names = (jyotisha.panchangam.temporal.NAMES['SAMVATSARA_NAMES'][
        panchangam.script][samvatsara_id],
                        jyotisha.panchangam.temporal.NAMES['SAMVATSARA_NAMES'][
                            panchangam.script][(samvatsara_id % 60) + 1])

    yname_solar = samvatsara_names[0]  # Assign year name until Mesha Sankranti
    yname_lunar = samvatsara_names[0]  # Assign year name until Mesha Sankranti

    # print(' \\sffamily \\fontsize 43  43 \\selectfont  %d–%d\\\\[0.5cm] \n\\hrule\n\\vspace 0.2cm '
    #       % (panchangam.year + 3100, panchangam.year + 3101), file=output_stream)
    # print(' \\sffamily \\fontsize 23  23 \\selectfont   %s \\\\[0.2cm] '
    #       % jyotisha.custom_transliteration.print_lat_lon(panchangam.city.latitude, panchangam.city.longitude), file=output_stream)

    panchangam.get_kaalas()

    for d in range(1, jyotisha.panchangam.temporal.MAX_SZ - 1):

        [y, m, dt, t] = swe.revjul(panchangam.jd_start_utc + d - 1)

        print('## %02d-%s-%4d' % (dt, month[m], y), file=output_stream)

        jd = panchangam.jd_midnight[d]

        tithi_data_str = ''
        for tithi_ID, tithi_end_jd in panchangam.tithi_data[d]:
            tithi = jyotisha.panchangam.temporal.NAMES['TITHI_NAMES'][
                panchangam.script][tithi_ID].split('-')[-1]
            paksha = jyotisha.custom_transliteration.tr(
                'zuklapakSaH' if tithi_ID <= 15 else 'kRSNapakSaH',
                panchangam.script)
            if tithi_end_jd is None:
                tithi_data_str = '%s; %s►%s' % \
                                 (tithi_data_str, tithi, jyotisha.custom_transliteration.tr('ahOrAtram (tridinaspRk)', panchangam.script))
            else:
                tithi_data_str = '%s; %s►%s (%s)%s' % \
                                 (tithi_data_str, tithi,
                                  jyotisha.panchangam.temporal.Time(24 * (tithi_end_jd - panchangam.jd_sunrise[d])).toString(format='gg-pp'),
                                  jyotisha.panchangam.temporal.Time(24 * (tithi_end_jd - jd)).toString(format=panchangam.fmt),
                                  ' ')
                if tithi_ID % 15 == 0:
                    paksha = '%s►%s' % (paksha,
                                        jyotisha.panchangam.temporal.Time(
                                            24 * (tithi_end_jd - jd)).toString(
                                                format=panchangam.fmt))
        tithi_data_str = getName('tithiH',
                                 panchangam.script) + '—' + tithi_data_str[2:]
        paksha_data_str = getName('pakSaH', panchangam.script) + '—' + paksha

        nakshatram_data_str = ''
        for nakshatram_ID, nakshatram_end_jd in panchangam.nakshatram_data[d]:
            nakshatram = jyotisha.panchangam.temporal.NAMES[
                'NAKSHATRAM_NAMES'][panchangam.script][nakshatram_ID]
            if nakshatram_end_jd is None:
                nakshatram_data_str = '%s; %s►%s' % \
                                      (nakshatram_data_str, nakshatram,
                                       jyotisha.custom_transliteration.tr('ahOrAtram', panchangam.script))
            else:
                nakshatram_data_str = '%s; %s►%s (%s)' % \
                                      (nakshatram_data_str, nakshatram,
                                       jyotisha.panchangam.temporal.Time(24 * (nakshatram_end_jd - panchangam.jd_sunrise[d])).toString(format='gg-pp'),
                                       jyotisha.panchangam.temporal.Time(24 * (nakshatram_end_jd - jd)).toString(format=panchangam.fmt),
                                       )
        nakshatram_data_str = getName(
            'nakSatram', panchangam.script) + '—' + nakshatram_data_str[2:]

        chandrashtama_rashi_data_str = ''
        for rashi_ID, rashi_end_jd in panchangam.rashi_data[d]:
            rashi = jyotisha.panchangam.temporal.NAMES['RASHI_SUFFIXED_NAMES'][
                panchangam.script][rashi_ID]
            if rashi_end_jd is None:
                rashi_data_str = '%s' % (rashi)
                chandrashtama_rashi_data_str = getName(
                    'candrASTama-rAziH', panchangam.script) + '—%s' % (
                        jyotisha.panchangam.temporal.NAMES['RASHI_NAMES'][
                            panchangam.script][((rashi_ID - 8) % 12) + 1])
            else:
                rashi_data_str = '%s►%s' % (rashi,
                                            jyotisha.panchangam.temporal.Time(
                                                24 *
                                                (rashi_end_jd - jd)).toString(
                                                    format=panchangam.fmt))
                chandrashtama_rashi_data_str = getName(
                    'candrASTama-rAziH',
                    panchangam.script) + '—%s►%s; %s ➥' % (
                        jyotisha.panchangam.temporal.NAMES['RASHI_NAMES'][
                            panchangam.script][((rashi_ID - 8) % 12) + 1],
                        jyotisha.panchangam.temporal.Time(24 *
                                                          (rashi_end_jd - jd)).
                        toString(format=panchangam.fmt), jyotisha.panchangam.
                        temporal.NAMES['RASHI_NAMES'][panchangam.script][(
                            (rashi_ID - 7) % 12) + 1])

        if compute_lagnams:
            lagna_data_str = ''
            for lagna_ID, lagna_end_jd in panchangam.lagna_data[d]:
                lagna = jyotisha.panchangam.temporal.NAMES['RASHI_NAMES'][
                    panchangam.script][lagna_ID]
                lagna_data_str = '%s; %s►%s' % \
                                 (lagna_data_str, lagna,
                                  jyotisha.panchangam.temporal.Time(24 * (lagna_end_jd - jd)).toString(format=panchangam.fmt))
            lagna_data_str = getName(
                'lagnam', panchangam.script) + '—' + lagna_data_str[2:]

        yoga_data_str = ''
        for yoga_ID, yoga_end_jd in panchangam.yoga_data[d]:
            # if yoga_data_str != '':
            #     yoga_data_str += ' '
            yoga = jyotisha.panchangam.temporal.NAMES['YOGA_NAMES'][
                panchangam.script][yoga_ID]
            if yoga_end_jd is None:
                yoga_data_str = '%s; %s►%s' % (
                    yoga_data_str, yoga,
                    jyotisha.custom_transliteration.tr('ahOrAtram',
                                                       panchangam.script))
            else:
                yoga_data_str = '%s; %s►%s (%s)' % (
                    yoga_data_str, yoga,
                    jyotisha.panchangam.temporal.Time(
                        24 *
                        (yoga_end_jd - panchangam.jd_sunrise[d])).toString(
                            format='gg-pp'),
                    jyotisha.panchangam.temporal.Time(
                        24 *
                        (yoga_end_jd - jd)).toString(format=panchangam.fmt))
        if yoga_end_jd is not None:
            yoga_data_str += '; %s ➥' % (jyotisha.panchangam.temporal.NAMES[
                'YOGA_NAMES'][panchangam.script][(yoga_ID % 27) + 1])
        yoga_data_str = getName('yOgaH',
                                panchangam.script) + '—' + yoga_data_str[2:]

        karanam_data_str = ''
        for numKaranam, (karanam_ID, karanam_end_jd) in enumerate(
                panchangam.karanam_data[d]):
            # if numKaranam == 1:
            #     karanam_data_str += ' '
            karanam = jyotisha.panchangam.temporal.NAMES['KARANAM_NAMES'][
                panchangam.script][karanam_ID]
            if karanam_end_jd is None:
                karanam_data_str = '%s; %s►%s' % \
                                   (karanam_data_str, karanam, jyotisha.custom_transliteration.tr('ahOrAtram', panchangam.script))
            else:
                karanam_data_str = '%s; %s►%s (%s)' % \
                                   (karanam_data_str, karanam,
                                    jyotisha.panchangam.temporal.Time(24 * (karanam_end_jd - panchangam.jd_sunrise[d])).toString(format='gg-pp'),
                                    jyotisha.panchangam.temporal.Time(24 * (karanam_end_jd - jd)).toString(format=panchangam.fmt))
        if karanam_end_jd is not None:
            karanam_data_str += '; %s ➥' % (jyotisha.panchangam.temporal.NAMES[
                'KARANAM_NAMES'][panchangam.script][(karanam_ID % 60) + 1])
        karanam_data_str = getName(
            'karaNam', panchangam.script) + '—' + karanam_data_str[2:]

        sunrise = jyotisha.panchangam.temporal.Time(
            24 *
            (panchangam.jd_sunrise[d] - jd)).toString(format=panchangam.fmt)
        sunset = jyotisha.panchangam.temporal.Time(
            24 *
            (panchangam.jd_sunset[d] - jd)).toString(format=panchangam.fmt)
        moonrise = jyotisha.panchangam.temporal.Time(
            24 *
            (panchangam.jd_moonrise[d] - jd)).toString(format=panchangam.fmt)
        moonset = jyotisha.panchangam.temporal.Time(
            24 *
            (panchangam.jd_moonset[d] - jd)).toString(format=panchangam.fmt)

        # braahma = jyotisha.panchangam.temporal.Time(24 * (panchangam.kaalas[d]['braahma'][0] - jd)).toString(format=panchangam.fmt)
        # pratahsandhya = jyotisha.panchangam.temporal.Time(24 * (panchangam.kaalas[d]['prAtaH sandhyA'][0] - jd)).toString(format=panchangam.fmt)
        # pratahsandhya_end = jyotisha.panchangam.temporal.Time(24 * (panchangam.kaalas[d]['prAtaH sandhyA end'][0] - jd)).toString(format=panchangam.fmt)
        # sangava = jyotisha.panchangam.temporal.Time(24 * (panchangam.kaalas[d]['saGgava'][0] - jd)).toString(format=panchangam.fmt)
        # madhyaahna = jyotisha.panchangam.temporal.Time(24 * (panchangam.kaalas[d]['madhyAhna'][0] - jd)).toString(format=panchangam.fmt)
        # madhyahnika_sandhya = jyotisha.panchangam.temporal.Time(24 * (panchangam.kaalas[d]['mAdhyAhnika sandhyA'][0] - jd)).toString(format=panchangam.fmt)
        # madhyahnika_sandhya_end = jyotisha.panchangam.temporal.Time(24 * (panchangam.kaalas[d]['mAdhyAhnika sandhyA end'][0] - jd)).toString(format=panchangam.fmt)
        aparahna = jyotisha.panchangam.temporal.Time(
            24 * (panchangam.kaalas[d]['aparAhna'][0] - jd)).toString(
                format=panchangam.fmt)
        sayahna = jyotisha.panchangam.temporal.Time(
            24 * (panchangam.kaalas[d]['sAyAhna'][0] - jd)).toString(
                format=panchangam.fmt)
        # sayamsandhya = jyotisha.panchangam.temporal.Time(24 * (panchangam.kaalas[d]['sAyaM sandhyA'][0] - jd)).toString(format=panchangam.fmt)
        # sayamsandhya_end = jyotisha.panchangam.temporal.Time(24 * (panchangam.kaalas[d]['sAyaM sandhyA end'][0] - jd)).toString(format=panchangam.fmt)
        # ratriyama1 = jyotisha.panchangam.temporal.Time(24 * (panchangam.kaalas[d]['rAtri yAma 1'][0] - jd)).toString(format=panchangam.fmt)
        # sayana_time = jyotisha.panchangam.temporal.Time(24 * (panchangam.kaalas[d]['zayana'][0] - jd)).toString(format=panchangam.fmt)
        dinanta = jyotisha.panchangam.temporal.Time(
            24 * (panchangam.kaalas[d]['dinAnta'][0] - jd)).toString(
                format=panchangam.fmt)

        rahu = '%s–%s' % (jyotisha.panchangam.temporal.Time(
            24 * (panchangam.kaalas[d]['rahu'][0] - jd)).toString(
                format=panchangam.fmt),
                          jyotisha.panchangam.temporal.Time(
                              24 *
                              (panchangam.kaalas[d]['rahu'][1] - jd)).toString(
                                  format=panchangam.fmt))
        yama = '%s–%s' % (jyotisha.panchangam.temporal.Time(
            24 * (panchangam.kaalas[d]['yama'][0] - jd)).toString(
                format=panchangam.fmt),
                          jyotisha.panchangam.temporal.Time(
                              24 *
                              (panchangam.kaalas[d]['yama'][1] - jd)).toString(
                                  format=panchangam.fmt))
        gulika = '%s–%s' % (jyotisha.panchangam.temporal.Time(
            24 * (panchangam.kaalas[d]['gulika'][0] - jd)).toString(
                format=panchangam.fmt),
                            jyotisha.panchangam.temporal.Time(
                                24 * (panchangam.kaalas[d]['gulika'][1] -
                                      jd)).toString(format=panchangam.fmt))

        if panchangam.solar_month[d] == 1:
            # Flip the year name for the remaining days
            yname_solar = samvatsara_names[1]
        if panchangam.lunar_month[d] == 1:
            # Flip the year name for the remaining days
            yname_lunar = samvatsara_names[1]

        # Assign samvatsara, ayana, rtu #
        ayanam = jyotisha.panchangam.temporal.NAMES['AYANA_NAMES'][
            panchangam.script][panchangam.solar_month[d]]
        rtu_solar = jyotisha.panchangam.temporal.NAMES['RTU_NAMES'][
            panchangam.script][panchangam.solar_month[d]]
        rtu_lunar = jyotisha.panchangam.temporal.NAMES['RTU_NAMES'][
            panchangam.script][int(ceil(panchangam.lunar_month[d]))]

        if panchangam.solar_month_end_time[d] is None:
            month_end_str = ''
        else:
            _m = panchangam.solar_month[d - 1]
            if panchangam.solar_month_end_time[d] >= panchangam.jd_sunrise[d +
                                                                           1]:
                month_end_str = '%s►%s' % (
                    jyotisha.panchangam.temporal.NAMES['RASHI_NAMES'][
                        panchangam.script][_m],
                    jyotisha.panchangam.temporal.Time(
                        24 * (panchangam.solar_month_end_time[d] -
                              panchangam.jd_midnight[d + 1])).toString(
                                  format=panchangam.fmt))
            else:
                month_end_str = '%s►%s' % (
                    jyotisha.panchangam.temporal.NAMES['RASHI_NAMES'][
                        panchangam.script][_m],
                    jyotisha.panchangam.temporal.Time(
                        24 * (panchangam.solar_month_end_time[d] -
                              panchangam.jd_midnight[d])).toString(
                                  format=panchangam.fmt))
        if month_end_str == '':
            month_data = '%s (%s %d)' % (jyotisha.panchangam.temporal.NAMES[
                'RASHI_NAMES'][panchangam.script][panchangam.solar_month[d]],
                                         getName('dinaM', panchangam.script),
                                         panchangam.solar_month_day[d])
        else:
            month_data = '%s (%s %d); %s' % (
                jyotisha.panchangam.temporal.NAMES['RASHI_NAMES'][
                    panchangam.script][panchangam.solar_month[d]],
                getName('dinaM', panchangam.script),
                panchangam.solar_month_day[d], month_end_str)

        vara = jyotisha.panchangam.temporal.NAMES['VARA_NAMES'][
            panchangam.script][panchangam.weekday[d]]

        if yname_lunar == yname_solar:
            print(getName('saMvatsaraH', panchangam.script) +
                  '—%s' % yname_lunar,
                  file=output_stream)
            print(getName('ayanam', panchangam.script) + '—%s' % ayanam,
                  file=output_stream)
        if rtu_lunar == rtu_solar:
            print(getName('RtuH', panchangam.script) + '—%s' % rtu_lunar,
                  file=output_stream)

        print('°' * 25, file=output_stream)
        print('☀ ' + getName('sauramAnam', panchangam.script),
              file=output_stream)
        if yname_lunar != yname_solar:
            print(getName('saMvatsaraH', panchangam.script) +
                  '—%s' % yname_solar,
                  file=output_stream)
            print(getName('ayanam', panchangam.script) + '—%s' % ayanam,
                  file=output_stream)
        if rtu_lunar != rtu_solar:
            print(getName('RtuH', panchangam.script) + '—%s' % rtu_solar,
                  file=output_stream)
        print(getName('mAsaH', panchangam.script) + '—%s' % month_data,
              file=output_stream)
        print('°' * 25, file=output_stream)

        print('⚪ ' + getName('cAndramAnam', panchangam.script),
              file=output_stream)
        if yname_lunar != yname_solar:
            print(getName('saMvatsaraH', panchangam.script) +
                  '—%s' % yname_lunar,
                  file=output_stream)
            print(getName('ayanam', panchangam.script) + '—%s' % ayanam,
                  file=output_stream)
        if rtu_lunar != rtu_solar:
            print(getName('RtuH', panchangam.script) + '—%s' % rtu_lunar,
                  file=output_stream)
        print(getName('mAsaH', panchangam.script) +
              '—%s' % jyotisha.panchangam.temporal.get_chandra_masa(
                  panchangam.lunar_month[d],
                  jyotisha.panchangam.temporal.NAMES, panchangam.script),
              file=output_stream)
        print('°' * 25, file=output_stream)
        # braahma
        # pratahsandhya, pratahsandhya_end
        # sangava
        # madhyahnika_sandhya, madhyahnika_sandhya_end
        # madhyaahna
        # aparahna
        # sayahna
        # sayamsandhya, sayamsandhya_end
        # dinanta
        print('%s' % (paksha_data_str), file=output_stream)
        print('%s' % (tithi_data_str), file=output_stream)
        print('%s—%s' % (getName('vAsaraH', panchangam.script), vara),
              file=output_stream)
        print('%s (%s)' % (nakshatram_data_str, rashi_data_str),
              file=output_stream)
        print('%s' % (yoga_data_str), file=output_stream)
        print('%s' % (karanam_data_str), file=output_stream)
        print('%s' % (chandrashtama_rashi_data_str), file=output_stream)

        if panchangam.jd_moonrise[d] > panchangam.jd_sunrise[d + 1]:
            moonrise = '---'
        if panchangam.jd_moonset[d] > panchangam.jd_sunrise[d + 1]:
            moonset = '---'

        print(
            '### **%s (%s)**' % (getName('LOC', panchangam.script),
                                 jyotisha.custom_transliteration.tr(
                                     panchangam.city.name, panchangam.script)),
            file=output_stream)

        if compute_lagnams:
            print('%s' % (lagna_data_str), file=output_stream)

        if panchangam.jd_moonrise[d] < panchangam.jd_moonset[d]:
            print('%s—%s; %s—%s' %
                  (getName('sUryOdayaH', panchangam.script), sunrise,
                   getName('sUryAstamayaH', panchangam.script), sunset),
                  file=output_stream)
            print('%s—%s; %s—%s' %
                  (getName('candrOdayaH', panchangam.script), moonrise,
                   getName('candrAstamayaH', panchangam.script), moonset),
                  file=output_stream)
        else:
            print('%s—%s; %s—%s' %
                  (getName('sUryOdayaH', panchangam.script), sunrise,
                   getName('sUryAstamayaH', panchangam.script), sunset),
                  file=output_stream)
            print('%s—%s; %s—%s' %
                  (getName('candrAstamayaH', panchangam.script), moonset,
                   getName('candrOdayaH', panchangam.script), moonrise),
                  file=output_stream)

        print(
            '%s—%s►%s' %
            (getName('aparAhNa-kAlaH', panchangam.script), aparahna, sayahna),
            file=output_stream)
        print('%s—%s' % (getName('dinAntaH', panchangam.script), dinanta),
              file=output_stream)
        print('%s—%s\n%s—%s\n%s—%s' %
              (getName('rAhukAlaH', panchangam.script), rahu,
               getName('yamaghaNTaH', panchangam.script), yama,
               getName('gulikakAlaH', panchangam.script), gulika),
              file=output_stream)

        shulam_end_jd = panchangam.jd_sunrise[d] + (
            panchangam.jd_sunset[d] -
            panchangam.jd_sunrise[d]) * (SHULAM[panchangam.weekday[d]][1] / 30)
        print('%s—%s (►%s); %s–%s' %
              (getName('zUlam', panchangam.script),
               getName(SHULAM[panchangam.weekday[d]][0], panchangam.script),
               jyotisha.panchangam.temporal.Time(
                   24 * (shulam_end_jd - jd)).toString(format=panchangam.fmt),
               getName('parihAraH', panchangam.script),
               getName(SHULAM[panchangam.weekday[d]][2], panchangam.script)),
              file=output_stream)
        # Using set as an ugly workaround since we may have sometimes assigned the same
        # festival to the same day again!
        fest_list = []
        for f in sorted(set(panchangam.festivals[d])):
            fest_name_cleaned = jyotisha.custom_transliteration.tr(
                f, panchangam.script).replace('~', ' ').replace('tamil', '')
            fest_name_cleaned = re.sub('[{}]', '', fest_name_cleaned).replace(
                '\\', '').replace('textsf',
                                  '').replace('To',
                                              '►').replace('RIGHTarrow', '►')
            fest_list.append(fest_name_cleaned)

        if len(fest_list):
            print('#### %s\n%s\n' % (getName(
                'dina-vizESAH', panchangam.script), '; '.join(fest_list)),
                  file=output_stream)
        else:
            print('', file=output_stream)

        output_text = cleanTamilNa(output_stream.getvalue())
        output_text = output_text.replace('\n', '\\\n')
        output_text = output_text.replace('\n\\', '\n')
        output_text = output_text.replace('\\\n\n', '\n\n')
        output_text = output_text.replace('\\\n#', '\n#')
        output_text = re.sub(r'(#.*)\\\n', r'\1\n', output_text)
        # output_text = re.sub(r'^\\', r'', output_text)
        print(output_text, file=output_file_stream)
        output_stream = StringIO()

        if m == 12 and dt == 31:
            break
def writeDailyTeX(panchangam,
                  template_file,
                  compute_lagnams=True,
                  output_stream=None):
    """Write out the panchangam TeX using a specified template
    """
    # day_colours = {0: 'blue', 1: 'blue', 2: 'blue',
    #                3: 'blue', 4: 'blue', 5: 'blue', 6: 'blue'}
    month = {
        1: 'JANUARY',
        2: 'FEBRUARY',
        3: 'MARCH',
        4: 'APRIL',
        5: 'MAY',
        6: 'JUNE',
        7: 'JULY',
        8: 'AUGUST',
        9: 'SEPTEMBER',
        10: 'OCTOBER',
        11: 'NOVEMBER',
        12: 'DECEMBER'
    }
    WDAY = {
        0: 'Sun',
        1: 'Mon',
        2: 'Tue',
        3: 'Wed',
        4: 'Thu',
        5: 'Fri',
        6: 'Sat'
    }

    template_lines = template_file.readlines()
    for i in range(len(template_lines)):
        print(template_lines[i][:-1], file=output_stream)

    samvatsara_id = (panchangam.year - 1568) % 60 + 1  # distance from prabhava
    samvatsara_names = (jyotisha.panchangam.temporal.NAMES['SAMVATSARA_NAMES'][
        panchangam.script][samvatsara_id],
                        jyotisha.panchangam.temporal.NAMES['SAMVATSARA_NAMES'][
                            panchangam.script][(samvatsara_id % 60) + 1])

    yname = samvatsara_names[0]  # Assign year name until Mesha Sankranti

    print('\\mbox{}', file=output_stream)
    print('\\renewcommand{\\yearname}{%d}' % panchangam.year,
          file=output_stream)
    print('\\begin{center}', file=output_stream)
    print('{\\sffamily \\fontsize{80}{80}\\selectfont  %d\\\\[0.5cm]}' %
          panchangam.year,
          file=output_stream)
    print('\\mbox{\\fontsize{48}{48}\\selectfont %s–%s}\\\\' %
          samvatsara_names,
          file=output_stream)
    print('\\mbox{\\fontsize{32}{32}\\selectfont %s } %%' %
          jyotisha.custom_transliteration.tr('kali', panchangam.script),
          file=output_stream)
    print(
        '{\\sffamily \\fontsize{43}{43}\\selectfont  %d–%d\\\\[0.5cm]}\n\\hrule\n\\vspace{0.2cm}'
        % (panchangam.year + 3100, panchangam.year + 3101),
        file=output_stream)
    print(
        '{\\sffamily \\fontsize{50}{50}\\selectfont  \\uppercase{%s}\\\\[0.2cm]}'
        % panchangam.city.name,
        file=output_stream)
    print('{\\sffamily \\fontsize{23}{23}\\selectfont  {%s}\\\\[0.2cm]}' %
          jyotisha.custom_transliteration.print_lat_lon(
              panchangam.city.latitude, panchangam.city.longitude),
          file=output_stream)
    print('\\hrule', file=output_stream)
    print('\\end{center}', file=output_stream)
    print('\\clearpage\\pagestyle{fancy}', file=output_stream)

    panchangam.get_kaalas()

    for d in range(1, jyotisha.panchangam.temporal.MAX_SZ - 1):

        [y, m, dt, t] = swe.revjul(panchangam.jd_start_utc + d - 1)

        # checking @ 6am local - can we do any better?
        local_time = tz(panchangam.city.timezone).localize(
            datetime(y, m, dt, 6, 0, 0))
        # compute offset from UTC in hours
        tz_off = (datetime.utcoffset(local_time).days * 86400 +
                  datetime.utcoffset(local_time).seconds) / 3600.0

        # What is the jd at 00:00 local time today?
        jd = panchangam.jd_midnight[d]

        tithi_data_str = ''
        for tithi_ID, tithi_end_jd in panchangam.tithi_data[d]:
            # if tithi_data_str != '':
            #     tithi_data_str += '\\hspace{1ex}'
            tithi = '\\raisebox{-1pt}{\moon[scale=0.8]{%d}}\\hspace{2pt}' % (tithi_ID) + \
                    jyotisha.panchangam.temporal.NAMES['TITHI_NAMES'][panchangam.script][tithi_ID]
            if tithi_end_jd is None:
                tithi_data_str = '%s\\mbox{%s\\To{}%s}' % \
                                 (tithi_data_str, tithi, jyotisha.custom_transliteration.tr('ahOrAtram (tridinaspRk)', panchangam.script))
            else:
                tithi_data_str = '%s\\mbox{%s\\To{}\\textsf{%s (%s)}}\\hspace{1ex}' % \
                                 (tithi_data_str, tithi,
                                  jyotisha.panchangam.temporal.Time(24 * (tithi_end_jd - panchangam.jd_sunrise[d])).toString(format='gg-pp'),
                                  jyotisha.panchangam.temporal.Time(24 * (tithi_end_jd - jd)).toString(format=panchangam.fmt))

        nakshatram_data_str = ''
        for nakshatram_ID, nakshatram_end_jd in panchangam.nakshatram_data[d]:
            if nakshatram_data_str != '':
                nakshatram_data_str += '\\hspace{1ex}'
            nakshatram = jyotisha.panchangam.temporal.NAMES[
                'NAKSHATRAM_NAMES'][panchangam.script][nakshatram_ID]
            if nakshatram_end_jd is None:
                nakshatram_data_str = '%s\\mbox{%s\\To{}%s}' % \
                                      (nakshatram_data_str, nakshatram,
                                       jyotisha.custom_transliteration.tr('ahOrAtram', panchangam.script))
            else:
                nakshatram_data_str = '%s\\mbox{%s\\To{}\\textsf{%s (%s)}}' % \
                                      (nakshatram_data_str, nakshatram,
                                       jyotisha.panchangam.temporal.Time(24 * (nakshatram_end_jd - panchangam.jd_sunrise[d])).toString(format='gg-pp'),
                                       jyotisha.panchangam.temporal.Time(24 * (nakshatram_end_jd - jd)).toString(format=panchangam.fmt))

        rashi_data_str = ''
        for rashi_ID, rashi_end_jd in panchangam.rashi_data[d]:
            # if rashi_data_str != '':
            #     rashi_data_str += '\\hspace{1ex}'
            rashi = jyotisha.panchangam.temporal.NAMES['RASHI_SUFFIXED_NAMES'][
                panchangam.script][rashi_ID]
            if rashi_end_jd is None:
                rashi_data_str = '%s\\mbox{%s}' % (rashi_data_str, rashi)
            else:
                rashi_data_str = '%s\\mbox{%s \\RIGHTarrow \\textsf{%s}}' % \
                                 (rashi_data_str, rashi,
                                  jyotisha.panchangam.temporal.Time(24 * (rashi_end_jd - jd)).toString(format=panchangam.fmt))
        if compute_lagnams:
            lagna_data_str = 'लग्नम्–'
            for lagna_ID, lagna_end_jd in panchangam.lagna_data[d]:
                lagna = jyotisha.panchangam.temporal.NAMES['RASHI_NAMES'][
                    panchangam.script][lagna_ID]
                lagna_data_str = '%s\\mbox{%s\\RIGHTarrow\\textsf{%s}} ' % \
                                 (lagna_data_str, lagna,
                                  jyotisha.panchangam.temporal.Time(24 * (lagna_end_jd - jd)).toString(format=panchangam.fmt))

        yoga_data_str = ''
        for yoga_ID, yoga_end_jd in panchangam.yoga_data[d]:
            # if yoga_data_str != '':
            #     yoga_data_str += '\\hspace{1ex}'
            yoga = jyotisha.panchangam.temporal.NAMES['YOGA_NAMES'][
                panchangam.script][yoga_ID]
            if yoga_end_jd is None:
                yoga_data_str = '%s\\mbox{%s\\To{}%s}' % \
                                 (yoga_data_str, yoga, jyotisha.custom_transliteration.tr('ahOrAtram', panchangam.script))
            else:
                yoga_data_str = '%s\\mbox{%s\\To{}\\textsf{%s (%s)}}\\hspace{1ex}' % \
                                 (yoga_data_str, yoga,
                                  jyotisha.panchangam.temporal.Time(24 * (yoga_end_jd - panchangam.jd_sunrise[d])).toString(format='gg-pp'),
                                  jyotisha.panchangam.temporal.Time(24 * (yoga_end_jd - jd)).toString(format=panchangam.fmt))
        if yoga_end_jd is not None:
            yoga_data_str += '\\mbox{%s\\Too{}}' % (
                jyotisha.panchangam.temporal.NAMES['YOGA_NAMES'][
                    panchangam.script][(yoga_ID % 27) + 1])

        karanam_data_str = ''
        for numKaranam, (karanam_ID, karanam_end_jd) in enumerate(
                panchangam.karanam_data[d]):
            # if numKaranam == 1:
            #     karanam_data_str += '\\hspace{1ex}'
            karanam = jyotisha.panchangam.temporal.NAMES['KARANAM_NAMES'][
                panchangam.script][karanam_ID]
            if karanam_end_jd is None:
                karanam_data_str = '%s\\mbox{%s\\To{}%s}' % \
                                   (karanam_data_str, karanam, jyotisha.custom_transliteration.tr('ahOrAtram', panchangam.script))
            else:
                karanam_data_str = '%s\\mbox{%s\\To{}\\textsf{%s (%s)}}\\hspace{1ex}' % \
                                   (karanam_data_str, karanam,
                                    jyotisha.panchangam.temporal.Time(24 * (karanam_end_jd - panchangam.jd_sunrise[d])).toString(format='gg-pp'),
                                    jyotisha.panchangam.temporal.Time(24 * (karanam_end_jd - jd)).toString(format=panchangam.fmt))
        if karanam_end_jd is not None:
            karanam_data_str += '\\mbox{%s\\Too{}}' % (
                jyotisha.panchangam.temporal.NAMES['KARANAM_NAMES'][
                    panchangam.script][(karanam_ID % 60) + 1])

        sunrise = jyotisha.panchangam.temporal.Time(
            24 *
            (panchangam.jd_sunrise[d] - jd)).toString(format=panchangam.fmt)
        sunset = jyotisha.panchangam.temporal.Time(
            24 *
            (panchangam.jd_sunset[d] - jd)).toString(format=panchangam.fmt)
        moonrise = jyotisha.panchangam.temporal.Time(
            24 *
            (panchangam.jd_moonrise[d] - jd)).toString(format=panchangam.fmt)
        moonset = jyotisha.panchangam.temporal.Time(
            24 *
            (panchangam.jd_moonset[d] - jd)).toString(format=panchangam.fmt)

        braahma = jyotisha.panchangam.temporal.Time(
            24 * (panchangam.kaalas[d]['braahma'][0] - jd)).toString(
                format=panchangam.fmt)
        pratahsandhya = jyotisha.panchangam.temporal.Time(
            24 * (panchangam.kaalas[d]['prAtaH sandhyA'][0] - jd)).toString(
                format=panchangam.fmt)
        pratahsandhya_end = jyotisha.panchangam.temporal.Time(
            24 *
            (panchangam.kaalas[d]['prAtaH sandhyA end'][0] - jd)).toString(
                format=panchangam.fmt)
        sangava = jyotisha.panchangam.temporal.Time(
            24 * (panchangam.kaalas[d]['saGgava'][0] - jd)).toString(
                format=panchangam.fmt)
        madhyaahna = jyotisha.panchangam.temporal.Time(
            24 * (panchangam.kaalas[d]['madhyAhna'][0] - jd)).toString(
                format=panchangam.fmt)
        madhyahnika_sandhya = jyotisha.panchangam.temporal.Time(
            24 *
            (panchangam.kaalas[d]['mAdhyAhnika sandhyA'][0] - jd)).toString(
                format=panchangam.fmt)
        madhyahnika_sandhya_end = jyotisha.panchangam.temporal.Time(
            24 * (panchangam.kaalas[d]['mAdhyAhnika sandhyA end'][0] -
                  jd)).toString(format=panchangam.fmt)
        aparahna = jyotisha.panchangam.temporal.Time(
            24 * (panchangam.kaalas[d]['aparAhna'][0] - jd)).toString(
                format=panchangam.fmt)
        sayahna = jyotisha.panchangam.temporal.Time(
            24 * (panchangam.kaalas[d]['sAyAhna'][0] - jd)).toString(
                format=panchangam.fmt)
        sayamsandhya = jyotisha.panchangam.temporal.Time(
            24 * (panchangam.kaalas[d]['sAyaM sandhyA'][0] - jd)).toString(
                format=panchangam.fmt)
        sayamsandhya_end = jyotisha.panchangam.temporal.Time(
            24 * (panchangam.kaalas[d]['sAyaM sandhyA end'][0] - jd)).toString(
                format=panchangam.fmt)
        ratriyama1 = jyotisha.panchangam.temporal.Time(
            24 * (panchangam.kaalas[d]['rAtri yAma 1'][0] - jd)).toString(
                format=panchangam.fmt)
        sayana_time = jyotisha.panchangam.temporal.Time(
            24 * (panchangam.kaalas[d]['zayana'][0] - jd)).toString(
                format=panchangam.fmt)
        dinanta = jyotisha.panchangam.temporal.Time(
            24 * (panchangam.kaalas[d]['dinAnta'][0] - jd)).toString(
                format=panchangam.fmt)

        rahu = '%s--%s' % (jyotisha.panchangam.temporal.Time(
            24 * (panchangam.kaalas[d]['rahu'][0] - jd)).toString(
                format=panchangam.fmt),
                           jyotisha.panchangam.temporal.Time(
                               24 * (panchangam.kaalas[d]['rahu'][1] -
                                     jd)).toString(format=panchangam.fmt))
        yama = '%s--%s' % (jyotisha.panchangam.temporal.Time(
            24 * (panchangam.kaalas[d]['yama'][0] - jd)).toString(
                format=panchangam.fmt),
                           jyotisha.panchangam.temporal.Time(
                               24 * (panchangam.kaalas[d]['yama'][1] -
                                     jd)).toString(format=panchangam.fmt))
        gulika = '%s--%s' % (jyotisha.panchangam.temporal.Time(
            24 * (panchangam.kaalas[d]['gulika'][0] - jd)).toString(
                format=panchangam.fmt),
                             jyotisha.panchangam.temporal.Time(
                                 24 * (panchangam.kaalas[d]['gulika'][1] -
                                       jd)).toString(format=panchangam.fmt))

        if panchangam.solar_month[d] == 1:
            # Flip the year name for the remaining days
            yname = samvatsara_names[1]

        # Assign samvatsara, ayana, rtu #
        sar_data = '{%s}{%s}{%s}' % (
            yname, jyotisha.panchangam.temporal.NAMES['AYANA_NAMES'][
                panchangam.script][panchangam.solar_month[d]],
            jyotisha.panchangam.temporal.NAMES['RTU_NAMES'][panchangam.script][
                panchangam.solar_month[d]])

        if panchangam.solar_month_end_time[d] is None:
            month_end_str = ''
        else:
            _m = panchangam.solar_month[d - 1]
            if panchangam.solar_month_end_time[d] >= panchangam.jd_sunrise[d +
                                                                           1]:
                month_end_str = '\\mbox{%s{\\tiny\\RIGHTarrow}\\textsf{%s}}' % (
                    jyotisha.panchangam.temporal.NAMES['RASHI_NAMES'][
                        panchangam.script][_m],
                    jyotisha.panchangam.temporal.Time(
                        24 * (panchangam.solar_month_end_time[d] -
                              panchangam.jd_midnight[d + 1])).toString(
                                  format=panchangam.fmt))
            else:
                month_end_str = '\\mbox{%s{\\tiny\\RIGHTarrow}\\textsf{%s}}' % (
                    jyotisha.panchangam.temporal.NAMES['RASHI_NAMES'][
                        panchangam.script][_m],
                    jyotisha.panchangam.temporal.Time(
                        24 * (panchangam.solar_month_end_time[d] -
                              panchangam.jd_midnight[d])).toString(
                                  format=panchangam.fmt))

        month_data = '\\sunmonth{%s}{%d}{%s}' % (
            jyotisha.panchangam.temporal.NAMES['RASHI_NAMES'][
                panchangam.script][panchangam.solar_month[d]],
            panchangam.solar_month_day[d], month_end_str)

        print('\\caldata{%s}{%s}{%s{%s}{%s}{%s}%s}' %
              (month[m], dt, month_data,
               jyotisha.panchangam.temporal.get_chandra_masa(
                   panchangam.lunar_month[d],
                   jyotisha.panchangam.temporal.NAMES, panchangam.script),
               jyotisha.panchangam.temporal.NAMES['RTU_NAMES'][
                   panchangam.script][int(ceil(panchangam.lunar_month[d]))],
               jyotisha.panchangam.temporal.NAMES['VARA_NAMES'][
                   panchangam.script][panchangam.weekday[d]], sar_data),
              file=output_stream)

        if panchangam.jd_moonrise[d] > panchangam.jd_sunrise[d + 1]:
            moonrise = '---'
        if panchangam.jd_moonset[d] > panchangam.jd_sunrise[d + 1]:
            moonset = '---'

        if panchangam.jd_moonrise[d] < panchangam.jd_moonset[d]:
            print('{\\sunmoonrsdata{%s}{%s}{%s}{%s}' %
                  (sunrise, sunset, moonrise, moonset),
                  file=output_stream)
        else:
            print('{\\sunmoonsrdata{%s}{%s}{%s}{%s}' %
                  (sunrise, sunset, moonrise, moonset),
                  file=output_stream)

        print('{\kalas{%s %s %s %s %s %s %s %s %s %s %s %s %s %s}}}' %
              (braahma, pratahsandhya, pratahsandhya_end, sangava,
               madhyahnika_sandhya, madhyahnika_sandhya_end, madhyaahna,
               aparahna, sayahna, sayamsandhya, sayamsandhya_end, ratriyama1,
               sayana_time, dinanta),
              file=output_stream)
        if compute_lagnams:
            print('{\\tnykdata{%s}%%\n{%s}{%s}%%\n{%s}%%\n{%s}{%s}\n}' %
                  (tithi_data_str, nakshatram_data_str, rashi_data_str,
                   yoga_data_str, karanam_data_str, lagna_data_str),
                  file=output_stream)
        else:
            print(
                '{\\tnykdata{%s}%%\n{%s}{%s}%%\n{%s}%%\n{%s}{\\scriptsize %s}\n}'
                % (tithi_data_str, nakshatram_data_str, rashi_data_str,
                   yoga_data_str, karanam_data_str, ''),
                file=output_stream)

        # Using set as an ugly workaround since we may have sometimes assigned the same
        # festival to the same day again!
        print('{%s}' % '\\eventsep '.join([
            jyotisha.custom_transliteration.tr(f, panchangam.script).replace(
                '★', '$^\\star$') for f in sorted(set(panchangam.festivals[d]))
        ]),
              file=output_stream)

        print('{%s} ' % WDAY[panchangam.weekday[d]], file=output_stream)
        print('\\cfoot{\\rygdata{%s}{%s}{%s}}' % (rahu, yama, gulika),
              file=output_stream)

        if m == 12 and dt == 31:
            break

    print('\\end{document}', file=output_stream)
Пример #40
0
def compute_calendar(panchangam, all_tags=True, brief=False):
    festival_rules_main = read_old_festival_rules_dict(
        os.path.join(
            CODE_ROOT,
            'panchangam/temporal/festival/legacy/festival_rules.json'))
    festival_rules_rel = read_old_festival_rules_dict(
        os.path.join(
            CODE_ROOT,
            'panchangam/temporal/festival/legacy/relative_festival_rules.json')
    )
    festival_rules_desc_only = read_old_festival_rules_dict(
        os.path.join(
            CODE_ROOT,
            'panchangam/temporal/festival/legacy/festival_rules_desc_only.json'
        ))

    festival_rules = {
        **festival_rules_main,
        **festival_rules_rel,
        **festival_rules_desc_only
    }

    ics_calendar = Calendar()
    # uid_list = []

    alarm = Alarm()
    alarm.add('action', 'DISPLAY')
    alarm.add('trigger',
              timedelta(hours=-4))  # default alarm, with a 4 hour reminder

    year_start = swe.revjul(panchangam.jd_start_utc +
                            1)[0]  # 1 helps ignore local time etc.

    for d in range(1, len(panchangam.festivals)):
        [y, m, dt, t] = swe.revjul(panchangam.jd_start_utc + d - 1)

        if len(panchangam.festivals[d]) > 0:
            # Eliminate repeat festivals on the same day, and keep the list arbitrarily sorted
            panchangam.festivals[d] = sorted(list(set(
                panchangam.festivals[d])))
            summary_text = panchangam.festivals[d]
            # this will work whether we have one or more events on the same day
            for stext in sorted(summary_text):
                desc = ''
                event = Event()

                if not all_tags:
                    fest_num_loc = stext.find('~\#')
                    if fest_num_loc != -1:
                        stext_chk = stext[:fest_num_loc]
                    else:
                        stext_chk = stext
                    if stext_chk in festival_rules:
                        tag_list = (
                            festival_rules[stext_chk]['tags'].split(','))
                        incl_tags = [
                            'CommonFestivals', 'MonthlyVratams', 'RareDays',
                            'AmavasyaDays', 'Dashavataram', 'SunSankranti'
                        ]
                        if set(tag_list).isdisjoint(set(incl_tags)):
                            continue

                if stext == 'kRttikA-maNDala-pArAyaNam':
                    event.add(
                        'summary',
                        jyotisha.custom_transliteration.tr(
                            stext.replace('-', ' '), panchangam.script))
                    fest_num_loc = stext.find('~\#')
                    if fest_num_loc != -1:
                        stext = stext[:fest_num_loc]
                    event.add('dtstart', date(y, m, dt))
                    event.add('dtend',
                              (datetime(y, m, dt) + timedelta(48)).date())

                    if stext in festival_rules:
                        desc = festival.HinduCalendarEventOld.make_from_dict(
                            festival_rules[stext]).get_description_string(
                                script=panchangam.script,
                                include_url=True,
                                include_shlokas=True,
                                truncate=True)
                    else:
                        logging.warning(
                            'No description found for festival %s!' % stext)

                    event.add_component(alarm)
                    event.add('description',
                              desc.strip().replace('\n', '<br/>'))
                    event['X-MICROSOFT-CDO-ALLDAYEVENT'] = 'TRUE'
                    event['TRANSP'] = 'TRANSPARENT'
                    event['X-MICROSOFT-CDO-BUSYSTATUS'] = 'FREE'
                    ics_calendar.add_component(event)
                elif stext.find('RIGHTarrow') != -1:
                    if y != year_start:
                        continue
                    # It's a grahanam/yogam, with a start and end time
                    if stext.find('{}') != -1:
                        # Starting or ending time is empty, e.g. harivasara, so no ICS entry
                        continue
                    [stext, t1, arrow, t2] = stext.split('\\')
                    stext = stext.strip('-~')
                    event.add(
                        'summary',
                        jyotisha.custom_transliteration.tr(
                            stext, panchangam.script))
                    # we know that t1 is something like 'textsf{hh:mm(+1)}{'
                    # so we know the exact positions of min and hour
                    if t1[12] in '(':  # (+1), next day
                        event.add(
                            'dtstart',
                            datetime(y,
                                     m,
                                     dt,
                                     int(t1[7:9]),
                                     int(t1[10:12]),
                                     tzinfo=tz(panchangam.city.timezone)) +
                            timedelta(1))
                    else:
                        if t1[12] == '*':
                            event.add(
                                'dtstart',
                                datetime(y,
                                         m,
                                         dt,
                                         int(t1[7:9]) - 24,
                                         int(t1[10:12]),
                                         tzinfo=tz(panchangam.city.timezone)) +
                                timedelta(1))
                        else:
                            event.add(
                                'dtstart',
                                datetime(y,
                                         m,
                                         dt,
                                         int(t1[7:9]),
                                         int(t1[10:12]),
                                         tzinfo=tz(panchangam.city.timezone)))

                    if t2[12] == '(':  # (+1), next day
                        event.add(
                            'dtend',
                            datetime(y,
                                     m,
                                     dt,
                                     int(t2[7:9]),
                                     int(t2[10:12]),
                                     tzinfo=tz(panchangam.city.timezone)) +
                            timedelta(1))
                    else:
                        if t2[12] == '*':
                            event.add(
                                'dtend',
                                datetime(y,
                                         m,
                                         dt,
                                         int(t2[7:9]) - 24,
                                         int(t2[10:12]),
                                         tzinfo=tz(panchangam.city.timezone)) +
                                timedelta(1))
                        else:
                            event.add(
                                'dtend',
                                datetime(y,
                                         m,
                                         dt,
                                         int(t2[7:9]),
                                         int(t2[10:12]),
                                         tzinfo=tz(panchangam.city.timezone)))

                    if stext in festival_rules:
                        festival_event = festival.HinduCalendarEventOld.make_from_dict(
                            festival_rules[stext])
                        desc = festival_event.get_description_string(
                            script=panchangam.script,
                            include_url=True,
                            include_shlokas=True,
                            truncate=True)
                    else:
                        logging.warning(
                            'No description found for festival %s!\n' % stext)
                    event.add('description',
                              desc.strip().replace('\n', '<br/>'))
                    event.add_component(alarm)
                    ics_calendar.add_component(event)
                elif stext.find('samApanam') != -1:
                    # It's an ending event
                    event.add(
                        'summary',
                        jyotisha.custom_transliteration.tr(
                            stext, panchangam.script))
                    event.add('dtstart', date(y, m, dt))
                    event.add('dtend',
                              (datetime(y, m, dt) + timedelta(1)).date())

                    if stext in festival_rules:
                        festival_event = festival.HinduCalendarEventOld.make_from_dict(
                            festival_rules[stext])
                        desc = festival_event.get_description_string(
                            script=panchangam.script,
                            include_url=True,
                            include_shlokas=True,
                            truncate=True)
                    else:
                        logging.warning(
                            'No description found for festival %s!' % stext)

                    event.add_component(alarm)
                    event.add('description',
                              desc.strip().replace('\n', '<br/>'))
                    event['X-MICROSOFT-CDO-ALLDAYEVENT'] = 'TRUE'
                    event['TRANSP'] = 'TRANSPARENT'
                    event['X-MICROSOFT-CDO-BUSYSTATUS'] = 'FREE'
                    ics_calendar.add_component(event)

                    # Find start and add entire event as well
                    event = Event()
                    check_d = d
                    stext_start = stext[:stext.find(
                        'samApanam'
                    )] + 'ArambhaH'  # This discards any bracketed info after the word ArambhaH
                    start_d = None
                    while check_d > 1:
                        check_d -= 1
                        if stext_start in panchangam.festivals[check_d]:
                            start_d = check_d
                            break

                    if start_d is None:
                        # Look for approx match
                        check_d = d
                        while check_d > 1:
                            check_d -= 1
                            for fest_key in panchangam.festivals[check_d]:
                                if fest_key.startswith(stext_start):
                                    logging.debug(
                                        'Found approx match for %s: %s' %
                                        (stext_start, fest_key))
                                    start_d = check_d
                                    break

                    if start_d is None:
                        logging.error('Unable to find start date for %s' %
                                      stext_start)
                    else:
                        # logging.debug(stext)
                        event_summary_text = stext
                        REPLACEMENTS = {
                            'samApanam': '',
                            'rAtri-': 'rAtriH',
                            'rAtra-': 'rAtraH',
                            'nakSatra-': 'nakSatram',
                            'pakSa-': 'pakSaH',
                            'puSkara-': 'puSkaram',
                            'dIpa-': 'dIpaH',
                            'snAna-': 'snAnam',
                            'tsava-': 'tsavaH',
                            'vrata-': 'vratam'
                        }
                        for _orig, _repl in REPLACEMENTS.items():
                            event_summary_text = event_summary_text.replace(
                                _orig, _repl)
                        event.add(
                            'summary',
                            jyotisha.custom_transliteration.tr(
                                event_summary_text, panchangam.script))
                        event.add('dtstart', (datetime(y, m, dt) -
                                              timedelta(d - start_d)).date())
                        event.add('dtend',
                                  (datetime(y, m, dt) + timedelta(1)).date())

                        # print(event)
                        event.add_component(alarm)
                        event.add('description',
                                  desc.strip().replace('\n', '<br/>'))
                        event['X-MICROSOFT-CDO-ALLDAYEVENT'] = 'TRUE'
                        event['TRANSP'] = 'TRANSPARENT'
                        event['X-MICROSOFT-CDO-BUSYSTATUS'] = 'FREE'
                        ics_calendar.add_component(event)
                else:
                    if y != year_start:
                        continue
                    summary = jyotisha.custom_transliteration.tr(
                        stext.replace('~',
                                      ' ').replace('\#',
                                                   '#').replace('\\To{}', '▶'),
                        panchangam.script)
                    summary = re.sub('.tamil{(.*)}', '\\1', summary)
                    summary = re.sub('{(.*)}', '\\1',
                                     summary)  # strip braces around numbers
                    event.add('summary', summary)
                    fest_num_loc = stext.find('~\#')
                    if fest_num_loc != -1:
                        stext = stext[:fest_num_loc]
                    event.add('dtstart', date(y, m, dt))
                    event.add('dtend',
                              (datetime(y, m, dt) + timedelta(1)).date())

                    if re.match('.*-.*-EkAdazI', stext) is None and stext.find(
                            'saGkrAntiH') == -1:
                        if stext in festival_rules:
                            desc = festival.HinduCalendarEventOld.make_from_dict(
                                festival_rules[stext]).get_description_string(
                                    script=panchangam.script,
                                    include_url=True,
                                    include_shlokas=True,
                                    truncate=True,
                                    include_images=False)
                        else:
                            if re.match(
                                    'aGgArakI.*saGkaTahara-caturthI-vratam',
                                    stext):
                                stext = stext.replace('aGgArakI~', '')
                                if stext in festival_rules:
                                    desc = festival.HinduCalendarEventOld.make_from_dict(
                                        festival_rules[stext]
                                    ).get_description_string(
                                        script=panchangam.script)
                                    desc += 'When `caturthI` occurs on a Tuesday, it is known as `aGgArakI` and is even more sacred.'
                                else:
                                    logging.warning(
                                        'No description found for caturthI festival %s!'
                                        % stext)
                            else:
                                # Check approx. match
                                matched_festivals = []
                                for fest_key in festival_rules:
                                    if stext.startswith(fest_key):
                                        matched_festivals += [fest_key]
                                if matched_festivals == []:
                                    logging.warning(
                                        'No description found for festival %s!'
                                        % stext)
                                elif len(matched_festivals) > 1:
                                    logging.warning(
                                        'No exact match found for festival %s! Found more than one approximate match: %s'
                                        % (stext, str(matched_festivals)))
                                else:
                                    desc = festival.HinduCalendarEventOld.make_from_dict(
                                        festival_rules[matched_festivals[0]]
                                    ).get_description_string(
                                        script=panchangam.script,
                                        include_url=True,
                                        include_shlokas=True,
                                        truncate=True)

                    elif stext.find('saGkrAntiH') != -1:
                        # Handle Sankranti descriptions differently
                        planet_trans = stext.split('~')[
                            0]  # get rid of ~(rAshi name) etc.
                        if planet_trans in festival_rules:
                            desc = festival.HinduCalendarEventOld.make_from_dict(
                                festival_rules[planet_trans]
                            ).get_description_string(script=panchangam.script,
                                                     include_url=True,
                                                     include_shlokas=True,
                                                     truncate=True)
                        else:
                            logging.warning(
                                'No description found for festival %s!' %
                                planet_trans)
                    else:
                        # logging.debug(stext)
                        # Handle ekadashi descriptions differently
                        ekad = '-'.join(stext.split('-')
                                        [1:])  # get rid of sarva etc. prefix!
                        ekad_suff_pos = ekad.find(' (')
                        if ekad_suff_pos != -1:
                            # ekad_suff = ekad[ekad_suff_pos + 1:-1]
                            ekad = ekad[:ekad_suff_pos]
                        if ekad in festival_rules:
                            desc = festival.HinduCalendarEventOld.make_from_dict(
                                festival_rules[ekad]).get_description_string(
                                    script=panchangam.script,
                                    include_url=True,
                                    include_shlokas=True,
                                    truncate=True)
                        else:
                            logging.warning(
                                'No description found for Ekadashi festival %s (%s)!'
                                % (ekad, stext))
                    event.add_component(alarm)
                    event.add('description',
                              desc.strip().replace('\n', '<br/>'))
                    event['X-MICROSOFT-CDO-ALLDAYEVENT'] = 'TRUE'
                    event['TRANSP'] = 'TRANSPARENT'
                    event['X-MICROSOFT-CDO-BUSYSTATUS'] = 'FREE'
                    ics_calendar.add_component(event)

        # if m == 12 and dt == 31:
        #     break

    return ics_calendar
def main():
  city_name = sys.argv[1]
  latitude = sexastr2deci(sys.argv[2])
  longitude = sexastr2deci(sys.argv[3])
  tz = sys.argv[4]
  
  start_year = int(sys.argv[5])
  year = start_year
  jd=swisseph.julday(year,1,1,0)
  jd_start=jd
  start_date = datetime(year=year,month=1,day=1,hour=0,minute=0,second=0)
  
  day_of_year=0
  
  swisseph.set_sid_mode(swisseph.SIDM_LAHIRI) #Force Lahiri Ayanamsha
  
  sun_month_day = jd-get_last_dhanur_transit(jd,latitude,longitude)
  #this has to be done in a generic fashion, by scanning for the transit into dhanur of the last year!
  
  month_start_after_set = 0
  
  template_file=open('cal_template_compre.tex')
  template_lines=template_file.readlines()
  for i in range(0,len(template_lines)-3):
    print template_lines[i][:-1]
  
  samvatsara_id = (year - 1568)%60 + 1; #distance from prabhava
  samvatsara_names = '%s–%s' % (year_names[samvatsara_id], year_names[(samvatsara_id%60)+1])
  
  print '\\mbox{}'
  print '{\\font\\x="Warnock Pro" at 60 pt\\x %d\\\\[0.3cm]}' % year
  print '\\mbox{\\font\\x="Sanskrit 2003:script=deva" at 48 pt\\x %s}\\\\[0.5cm]' % samvatsara_names
  print '{\\font\\x="Warnock Pro" at 48 pt\\x \\uppercase{%s}\\\\[0.3cm]}' % city_name
  print '\hrule'
  
  while year<=start_year:

    day_of_year = day_of_year + 1  
  
    [y,m,d,t] = swisseph.revjul(jd)
    weekday = (swisseph.day_of_week(jd) + 1)%7 #swisseph has Mon = 0, non-intuitively!
  
    local_time = pytz.timezone(tz).localize(datetime(y,m, d, 6, 0, 0)) #checking @ 6am local - can we do any better?
    tz_off=datetime.utcoffset(local_time).seconds/3600.0 #compute offset from UTC
  
    jd_rise=swisseph.rise_trans(jd_start=jd,body=swisseph.SUN,lon=longitude,lat=latitude,rsmi=swisseph.CALC_RISE|swisseph.BIT_DISC_CENTER)[1][0]
    jd_rise_tmrw=swisseph.rise_trans(jd_start=jd+1,body=swisseph.SUN,lon=longitude,lat=latitude,rsmi=swisseph.CALC_RISE|swisseph.BIT_DISC_CENTER)[1][0]
    jd_set =swisseph.rise_trans(jd_start=jd,body=swisseph.SUN,lon=longitude,lat=latitude,rsmi=swisseph.CALC_SET|swisseph.BIT_DISC_CENTER)[1][0]
  
    [_y,_m,_d, t_rise]=swisseph.revjul(jd_rise+tz_off/24.0)
    [_y,_m,_d, t_set]=swisseph.revjul(jd_set+tz_off/24.0)
  
    longitude_moon=swisseph.calc_ut(jd_rise,swisseph.MOON)[0]-swisseph.get_ayanamsa(jd_rise)
    longitude_moon_tmrw=swisseph.calc_ut(jd_rise+1,swisseph.MOON)[0]-swisseph.get_ayanamsa(jd_rise+1)
  
    longitude_sun=swisseph.calc_ut(jd_rise,swisseph.SUN)[0]-swisseph.get_ayanamsa(jd_rise)
    longitude_sun_set=swisseph.calc_ut(jd_set,swisseph.SUN)[0]-swisseph.get_ayanamsa(jd_set)
    sun_month_rise = masa_names[int(1+math.floor(((longitude_sun)%360)/30.0))]
    sun_month = masa_names[int(1+math.floor(((longitude_sun_set)%360)/30.0))]
    longitude_sun_tmrw=swisseph.calc_ut(jd_rise+1,swisseph.SUN)[0]-swisseph.get_ayanamsa(jd_rise+1)
    sun_month_tmrw = masa_names[int(1+math.floor(((longitude_sun_tmrw)%360)/30.0))]
  
    daily_motion_moon = (longitude_moon_tmrw-longitude_moon)%360
    daily_motion_sun = (longitude_sun_tmrw-longitude_sun)%360
  
    #Solar month calculations
    if month_start_after_set==1:
      sun_month_day = 0
      month_start_after_set = 0
  
    if sun_month_rise!=sun_month_tmrw:
      if sun_month!=sun_month_tmrw:
        month_start_after_set=1
        sun_month_day = sun_month_day + 1
      #mAsa pirappu!
      #sun_month = sun_month_tmrw #sun moves into next rAsi before sunset -- check rules!
      else:
        sun_month_day = 1
      month_remaining = 30-(longitude_sun%30.0)
      month_end = month_remaining/daily_motion_sun*24.0
      me = deci2sexa(t_rise+month_end)
      if me[0]>=24:
        suff='(+1)'
        me[0] = me[0] - 24
      else:
        suff='\\hspace{2ex}'
      sun_month_end_time = '{\\textsf{%s} {\\tiny \\RIGHTarrow} %02d:%02d%s}' % (last_sun_month,me[0],me[1],suff)
    else:
      sun_month_day = sun_month_day + 1
      sun_month_end_time = ''
    
    month_data = '\\sunmonth{%s}{%d}{%s}' % (sun_month,sun_month_day,sun_month_end_time)
  
    #Compute tithi details
    tithi = int(1+math.floor((longitude_moon-longitude_sun)%360 / 12.0))
    tithi_tmrw = int(1+math.floor((longitude_moon_tmrw-longitude_sun_tmrw)%360 / 12.0))

    if (tithi_tmrw-tithi)%30 > 1:
      #double change
      tithi_2=(tithi%30)+1
      if tithi_2%15 != 0:
        paksha = (paksha_names['shukla'] if tithi_2<15 else paksha_names['krishna'])
      else:
        if tithi_2 == 15:
          paksha = '\\fullmoon'
        elif tithi_2 == 30:
          paksha = '\\newmoon'
    
      if tithi_2%15 == 0:
        tithi_str_2 = paksha + tithi_names[tithi_2]
      else:
        tithi_str_2 = paksha + tithi_names[tithi_2%15]
      
      tithi_remaining_2 = 12+12-(((longitude_moon-longitude_sun)%360)%12)
      tithi_end_2 = tithi_remaining_2/(daily_motion_moon-daily_motion_sun)*24.0
      tithi_end_str_2 = print_end_time(tithi_end_2,jd_rise_tmrw-jd_rise,t_rise)
      if tithi_end_str_2 == '\\textsf{अहोरात्रम्}':
        #needs correction, owing to the fact that we compute longitude every 24h, rather than at next sunrise
        #the second tithi cannot be 'all day'! It's ending will reflect in tomorrow's calendar
        tithi_str_2 = ''
        tithi_end_str_2 = ''
    else:
     tithi_str_2 = ''
     tithi_end_str_2 = ''
    
    if tithi%15 != 0:
      paksha = (paksha_names['shukla'] if tithi<15 else paksha_names['krishna'])
    else:
      if tithi == 15:
        paksha = '\\fullmoon'
      elif tithi == 30:
        paksha = '\\newmoon'
  
    if tithi%15 == 0:
      tithi_str = paksha + tithi_names[tithi]
    else:
      tithi_str = paksha + tithi_names[tithi%15]
    
    tithi_remaining = 12-(((longitude_moon-longitude_sun)%360)%12)
    tithi_end = tithi_remaining/(daily_motion_moon-daily_motion_sun)*24.0
    tithi_end_str = print_end_time(tithi_end,jd_rise_tmrw-jd_rise,t_rise)
  
    #Compute nakshatram details
    n_id = int(1+math.floor((longitude_moon%360) /(360.0/27)))
    n_id_tmrw = int(1+math.floor((longitude_moon_tmrw%360) /(360.0/27)))
    if (n_id_tmrw-n_id)%27 > 1:
      #there is a double change
      nakshatram_str_2 = nakshatra_names[n_id%27+1]
      nakshatram_remaining_2 = (360.0/27)+(360.0/27) - ((longitude_moon%360) % (360.0/27))
      nakshatram_end_2 = nakshatram_remaining_2/daily_motion_moon*24
      nakshatram_end_str_2 = print_end_time(nakshatram_end_2,jd_rise_tmrw-jd_rise,t_rise)
      if nakshatram_end_str_2 == '\\textsf{अहोरात्रम्}':
        #needs correction, owing to the fact that we compute longitude every 24h, rather than at next sunrise
        #the second nakshatram cannot be 'all day'! It's ending will reflect in tomorrow's calendar
        nakshatram_str_2 = ''
        nakshatram_end_str_2 = ''
    else:
      nakshatram_str_2 = ''
      nakshatram_end_str_2 = ''
    
    nakshatram_str = nakshatra_names[n_id]
    nakshatram_remaining = (360.0/27) - ((longitude_moon%360) % (360.0/27))
    nakshatram_end = nakshatram_remaining/daily_motion_moon*24
    nakshatram_end_str = print_end_time(nakshatram_end,jd_rise_tmrw-jd_rise,t_rise)
   
    #Compute karanam details
    karanam = int(1+math.floor((longitude_moon-longitude_sun)%360 / 6.0))
    karanam_tmrw = int(1+math.floor((longitude_moon_tmrw-longitude_sun_tmrw)%360 / 6.0))

#    There cannot be more than 3 karanams in a day, because total arc ~ 12 deg and per yogam is 6 deg

    if (karanam_tmrw-karanam)%60 > 2:
      #triple change
      karanam_3=((karanam+1)%60)+1
      karanam_str_3 = karanam_names[karanam_3]
      
      karanam_remaining_3 = 6*2+6-(((longitude_moon-longitude_sun)%360)%6)
      karanam_end_3 = karanam_remaining_3/(daily_motion_moon-daily_motion_sun)*24.0
      karanam_end_str_3 = print_end_time(karanam_end_3,jd_rise_tmrw-jd_rise,t_rise)
      if karanam_end_str_3 == '\\textsf{अहोरात्रम्}':
        #needs correction, owing to the fact that we compute longitude every 24h, rather than at next sunrise
        #the second karanam cannot be 'all day'! It's ending will reflect in tomorrow's calendar
        karanam_str_3 = ''
        karanam_end_str_3 = ''
    else:
     karanam_str_3 = ''
     karanam_end_str_3 = ''

    if (karanam_tmrw-karanam)%60 > 1:
      #double change
      karanam_2=(karanam%60)+1
      karanam_str_2 = karanam_names[karanam_2]
      
      karanam_remaining_2 = 6+6-(((longitude_moon-longitude_sun)%360)%6)
      karanam_end_2 = karanam_remaining_2/(daily_motion_moon-daily_motion_sun)*24.0
      karanam_end_str_2 = print_end_time(karanam_end_2,jd_rise_tmrw-jd_rise,t_rise)
      if karanam_end_str_2 == '\\textsf{अहोरात्रम्}':
        #needs correction, owing to the fact that we compute longitude every 24h, rather than at next sunrise
        #the second karanam cannot be 'all day'! It's ending will reflect in tomorrow's calendar
        karanam_str_2 = ''
        karanam_end_str_2 = ''
    else:
     karanam_str_2 = ''
     karanam_end_str_2 = ''
    
    karanam_str = karanam_names[karanam]
    
    karanam_remaining = 6-(((longitude_moon-longitude_sun)%6)%6)
    karanam_end = karanam_remaining/(daily_motion_moon-daily_motion_sun)*24.0
    karanam_end_str = print_end_time(karanam_end,jd_rise_tmrw-jd_rise,t_rise)

    #Compute yogam details
    yogam = int(1+math.floor((longitude_moon+longitude_sun)%360 / (360.0/27.0)))
    yogam_tmrw = int(1+math.floor((longitude_moon_tmrw+longitude_sun_tmrw)%360 / (360.0/27.0)))

    #There cannot be more than 2 yogams in a day, because total arc = 13 deg and per yogam is 13.333 deg

    if (yogam_tmrw-yogam)%27 > 1:
      #double change
      yogam_2=(yogam%27)+1
      yogam_str_2 = yogam_names[yogam_2]
      
      yogam_remaining_2 = 2.0*(360.0/27.0)-(((longitude_moon+longitude_sun)%360)%(360.0/27.0))
      yogam_end_2 = yogam_remaining_2/(daily_motion_moon+daily_motion_sun)*24.0
      yogam_end_str_2 = print_end_time(yogam_end_2,jd_rise_tmrw-jd_rise,t_rise)
      if yogam_end_str_2 == '\\textsf{अहोरात्रम्}':
        #needs correction, owing to the fact that we compute longitude every 24h, rather than at next sunrise
        #the second yogam cannot be 'all day'! It's ending will reflect in tomorrow's calendar
        yogam_str_2 = ''
        yogam_end_str_2 = ''
    else:
     yogam_str_2 = ''
     yogam_end_str_2 = ''
    
    yogam_str = yogam_names[yogam]
    
    yogam_remaining = (360.0/27.0)-(((longitude_moon+longitude_sun)%360)%(360.0/27.0))
    yogam_end = yogam_remaining/(daily_motion_moon+daily_motion_sun)*24.0
    yogam_end_str = print_end_time(yogam_end,jd_rise_tmrw-jd_rise,t_rise)

    #Sunrise/sunset and related stuff (like rahu, yama)
    [rh, rm, rs] = deci2sexa(t_rise) #rise_t hour, rise minute
    [sh, sm, ss] = deci2sexa(t_set) #set_t hour, set minute
  
    present_day = start_date + timedelta(days=day_of_year)
    rise_t = present_day + timedelta(hours=rh,minutes=rm)
    set_t = present_day + timedelta(hours=sh,minutes=sm)
  
    length_of_day = set_t-rise_t
    yamakandam_start = rise_t + timedelta(seconds=(1/8.0)*(yamakandam_octets[weekday]-1)*length_of_day.seconds)
    yamakandam_end = yamakandam_start + timedelta(seconds=(1/8.0)*length_of_day.seconds)
    rahukalam_start = rise_t + timedelta(seconds=(1/8.0)*(rahukalam_octets[weekday]-1)*length_of_day.seconds)
    rahukalam_end = rahukalam_start + timedelta(seconds=(1/8.0)*length_of_day.seconds)
    madhyahnikam_start = rise_t + timedelta(seconds=(1/5.0)*length_of_day.seconds)
  
    rise = '%02d:%02d' % (rh,rm)
    set = '%02d:%02d' % (sh,sm)
    madhya = print_time(madhyahnikam_start)
    rahu = '%s--%s' % (print_time(rahukalam_start), print_time(rahukalam_end))
    yama = '%s--%s' % (print_time(yamakandam_start),print_time(yamakandam_end))
    
    if nakshatram_end_str_2!='':
      nakshatram_data_string = '\\mbox{\\textsf{%s} {\\tiny \\RIGHTarrow} %s}\\mbox{\\textsf{%s} {\\tiny \\RIGHTarrow} %s}' % (nakshatram_str,nakshatram_end_str,nakshatram_str_2,nakshatram_end_str_2)
    else:
      nakshatram_data_string = '{\\textsf{%s} {\\tiny \\RIGHTarrow} %s}' % (nakshatram_str,nakshatram_end_str)

    if tithi_end_str_2!='':
      tithi_data_string = '\\mbox{\\textsf{%s} {\\tiny \\RIGHTarrow} %s}\\mbox{\\textsf{%s} {\\tiny \\RIGHTarrow} %s}' % (tithi_str,tithi_end_str,tithi_str_2,tithi_end_str_2)
    else:
      tithi_data_string = '{\\textsf{%s} {\\tiny \\RIGHTarrow} %s}' % (tithi_str,tithi_end_str)

    if karanam_end_str_3!='':
      karanam_data_string = '\\mbox{\\textsf{%s} {\\tiny \\RIGHTarrow} %s}\\mbox{\\textsf{%s} {\\tiny \\RIGHTarrow} %s}\\\\\\mbox{\\textsf{%s} {\\tiny \\RIGHTarrow} %s}' % (karanam_str,karanam_end_str,karanam_str_2,karanam_end_str_2,karanam_str_3,karanam_end_str_3)
    elif karanam_end_str_2!='':
      karanam_data_string = '\\mbox{\\textsf{%s} {\\tiny \\RIGHTarrow} %s}\\mbox{\\textsf{%s} {\\tiny \\RIGHTarrow} %s}' % (karanam_str,karanam_end_str,karanam_str_2,karanam_end_str_2)
    else:
      karanam_data_string = '\\mbox{\\textsf{%s} {\\tiny \\RIGHTarrow} %s}' % (karanam_str,karanam_end_str)

    if yogam_end_str_2!='':
      yogam_data_string = '\\mbox{\\textsf{%s} {\\tiny \\RIGHTarrow} %s}\\mbox{\\textsf{%s} {\\tiny \\RIGHTarrow} %s}' % (yogam_str,yogam_end_str,yogam_str_2,yogam_end_str_2)
    else:
      yogam_data_string = '\\mbox{\\textsf{%s} {\\tiny \\RIGHTarrow} %s}' % (yogam_str,yogam_end_str)

    #Layout calendar in LATeX format
    if d==1:
      if m>1:
        if weekday!=0: #Space till Sunday
          for i in range(weekday,6):
            print "{}  &"
          print "\\\\ \hline"
        print '\end{tabular}'
        print '\n\n'
  
      #Begin tabular
      print '\\begin{tabular}{|c|c|c|c|c|c|c|}'
      print '\multicolumn{7}{c}{\Large \\bfseries %s %s}\\\\[3mm]' % (month[m],y)
      print '\hline'
      print '\\textbf{SUN} & \\textbf{MON} & \\textbf{TUE} & \\textbf{WED} & \\textbf{THU} & \\textbf{FRI} & \\textbf{SAT} \\\\ \hline'
      #print '\\textbf{भानु} & \\textbf{इन्दु} & \\textbf{भौम} & \\textbf{बुध} & \\textbf{गुरु} & \\textbf{भृगु} & \\textbf{स्थिर} \\\\ \hline'
  
      #Blanks for previous weekdays
      for i in range(0,weekday):
        print "{}  &"

    print '\caldata{\\textcolor{%s}{%s}}{%s}{\\sundata{%s}{%s}{%s}}{\\tnyk{%s}{%s}{%s}{%s}}{\\textsf{राहु}~%s~~\\textsf{यम}~%s} ' % (daycol[weekday],d,month_data,rise,set,madhya,tithi_data_string,nakshatram_data_string,yogam_data_string,karanam_data_string,rahu,yama)
  
    if weekday==6:
      print "\\\\ \hline"
    else:
      print "&"
  
    jd = jd + 1

    last_sun_month = sun_month

    if m==12 and d==31:
      year = year + 1
  
    # For debugging specific dates
    #if m==4 and d==10:
    #  break
  
  for i in range(weekday+1,6):
    print "{}  &"
  if weekday!=6:
    print "\\\\ \hline"
  print '\end{tabular}'
  print '\n\n'
  
  print template_lines[-2][:-1]
  print template_lines[-1][:-1]
Пример #42
0
 def revTime(self, tjd):
     jy, jm, jd, jh = swisseph.revjul(tjd, 1)
     d, m, s = util.decToDeg(jh)
     return (d, m, s)
def writeDailyICS(panchangam, compute_lagnams=True):
    """Write out the panchangam TeX using a specified template
    """
    output_stream = StringIO()
    month = {
        1: 'January',
        2: 'February',
        3: 'March',
        4: 'April',
        5: 'May',
        6: 'June',
        7: 'July',
        8: 'August',
        9: 'September',
        10: 'October',
        11: 'November',
        12: 'December'
    }
    WDAY = {
        0: 'Sunday',
        1: 'Monday',
        2: 'Tuesday',
        3: 'Wednesday',
        4: 'Thursday',
        5: 'Friday',
        6: 'Saturday'
    }
    SHULAM = [('pratIcI dik', 12, 'guDam'), ('prAcI dik', 8, 'dadhi'),
              ('udIcI dik', 12, 'kSIram'), ('udIcI dik', 16, 'kSIram'),
              ('dakSiNA dik', 20, 'tailam'), ('pratIcI dik', 12, 'guDam'),
              ('prAcI dik', 8, 'dadhi')]

    samvatsara_id = (panchangam.year - 1568) % 60 + 1  # distance from prabhava
    samvatsara_names = (jyotisha.panchangam.temporal.NAMES['SAMVATSARA_NAMES'][
        panchangam.script][samvatsara_id],
                        jyotisha.panchangam.temporal.NAMES['SAMVATSARA_NAMES'][
                            panchangam.script][(samvatsara_id % 60) + 1])

    yname_solar = samvatsara_names[0]  # Assign year name until Mesha Sankranti
    yname_lunar = samvatsara_names[0]  # Assign year name until Mesha Sankranti

    # print(' \\sffamily \\fontsize 43  43 \\selectfont  %d–%d\\\\[0.5cm] \n\\hrule\n\\vspace 0.2cm '
    #       % (panchangam.year + 3100, panchangam.year + 3101), file=output_stream)
    # print(' \\sffamily \\fontsize 23  23 \\selectfont   %s \\\\[0.2cm] '
    #       % jyotisha.custom_transliteration.print_lat_lon(panchangam.city.latitude, panchangam.city.longitude), file=output_stream)

    panchangam.get_kaalas()

    ics_calendar = Calendar()

    alarm = Alarm()
    alarm.add('action', 'DISPLAY')
    alarm.add('trigger',
              timedelta(hours=-4))  # default alarm, with a 4 hour reminder

    for d in range(1, jyotisha.panchangam.temporal.MAX_SZ - 1):

        [y, m, dt, t] = swe.revjul(panchangam.jd_start_utc + d - 1)

        print('*%s*' % jyotisha.custom_transliteration.tr(
            'zrI kAJcI-kAmakOTi-pITham vEda-dharmazAstra-paripAlana-sabhA dRggaNita-paJcAGgam',
            panchangam.script),
              file=output_stream)
        print('*%02d-%s-%4d*' % (dt, month[m], y), file=output_stream)
        event = Event()
        event.add(
            'summary', '%s %02d-%s-%4d (%s)' %
            (WDAY[panchangam.weekday[d]][:3].upper(), dt, month[m], y,
             cleanTamilNa(
                 jyotisha.custom_transliteration.tr(panchangam.city.name,
                                                    panchangam.script))))

        jd = panchangam.jd_midnight[d]

        paksha_data_str = ''
        tithi_data_str = ''
        for tithi_ID, tithi_end_jd in panchangam.tithi_data[d]:
            tithi = jyotisha.panchangam.temporal.NAMES['TITHI_NAMES'][
                panchangam.script][tithi_ID].split('-')[-1]
            paksha = jyotisha.custom_transliteration.tr(
                'zuklapakSaH' if tithi_ID <= 15 else 'kRSNapakSaH',
                panchangam.script)
            if tithi_end_jd is None:
                tithi_data_str = '%s; %s►%s' % \
                                 (tithi_data_str, tithi, jyotisha.custom_transliteration.tr('ahOrAtram (tridinaspRk)', panchangam.script))
            else:
                tithi_data_str = '%s; %s►%s%s' % \
                                 (tithi_data_str, tithi,
                                  jyotisha.panchangam.temporal.Time(24 * (tithi_end_jd - jd)).toString(format=panchangam.fmt),
                                  ' ')
        tithi_data_str = '*' + getName(
            'tithiH', panchangam.script) + '*—' + tithi_data_str[2:]
        paksha_data_str = '*' + getName('pakSaH',
                                        panchangam.script) + '*—' + paksha

        nakshatram_data_str = ''
        for nakshatram_ID, nakshatram_end_jd in panchangam.nakshatram_data[d]:
            nakshatram = jyotisha.panchangam.temporal.NAMES[
                'NAKSHATRAM_NAMES'][panchangam.script][nakshatram_ID]
            if nakshatram_end_jd is None:
                nakshatram_data_str = '%s; %s►%s' % \
                                      (nakshatram_data_str, nakshatram,
                                       jyotisha.custom_transliteration.tr('ahOrAtram', panchangam.script))
            else:
                nakshatram_data_str = '%s; %s►%s' % \
                                      (nakshatram_data_str, nakshatram,
                                       jyotisha.panchangam.temporal.Time(24 * (nakshatram_end_jd -
                                                                               jd)).toString(format=panchangam.fmt))
        nakshatram_data_str = '*' + getName(
            'nakSatram', panchangam.script) + '*—' + nakshatram_data_str[2:]

        chandrashtama_rashi_data_str = ''
        for rashi_ID, rashi_end_jd in panchangam.rashi_data[d]:
            rashi = jyotisha.panchangam.temporal.NAMES['RASHI_SUFFIXED_NAMES'][
                panchangam.script][rashi_ID]
            if rashi_end_jd is None:
                rashi_data_str = '%s' % (rashi)
                chandrashtama_rashi_data_str = '*' + getName(
                    'candrASTama-rAziH', panchangam.script) + '*—%s' % (
                        jyotisha.panchangam.temporal.NAMES['RASHI_NAMES'][
                            panchangam.script][((rashi_ID - 8) % 12) + 1])
            else:
                rashi_data_str = '%s►%s' % (rashi,
                                            jyotisha.panchangam.temporal.Time(
                                                24 *
                                                (rashi_end_jd - jd)).toString(
                                                    format=panchangam.fmt))
                chandrashtama_rashi_data_str = '*' + getName(
                    'candrASTama-rAziH',
                    panchangam.script) + '*—%s►%s; %s ➥' % (
                        jyotisha.panchangam.temporal.NAMES['RASHI_NAMES'][
                            panchangam.script][((rashi_ID - 8) % 12) + 1],
                        jyotisha.panchangam.temporal.Time(24 *
                                                          (rashi_end_jd - jd)).
                        toString(format=panchangam.fmt), jyotisha.panchangam.
                        temporal.NAMES['RASHI_NAMES'][panchangam.script][(
                            (rashi_ID - 7) % 12) + 1])

        if compute_lagnams:
            lagna_data_str = ''
            for lagna_ID, lagna_end_jd in panchangam.lagna_data[d]:
                lagna = jyotisha.panchangam.temporal.NAMES['RASHI_NAMES'][
                    panchangam.script][lagna_ID]
                lagna_data_str = '%s; %s►%s' % \
                                 (lagna_data_str, lagna,
                                  jyotisha.panchangam.temporal.Time(24 * (lagna_end_jd - jd)).toString(format=panchangam.fmt))
            lagna_data_str = '*' + getName(
                'lagnam', panchangam.script) + '*—' + lagna_data_str[2:]

        yoga_data_str = ''
        for yoga_ID, yoga_end_jd in panchangam.yoga_data[d]:
            # if yoga_data_str != '':
            #     yoga_data_str += ' '
            yoga = jyotisha.panchangam.temporal.NAMES['YOGA_NAMES'][
                panchangam.script][yoga_ID]
            if yoga_end_jd is None:
                yoga_data_str = '%s; %s►%s' % (
                    yoga_data_str, yoga,
                    jyotisha.custom_transliteration.tr('ahOrAtram',
                                                       panchangam.script))
            else:
                yoga_data_str = '%s; %s►%s' % (
                    yoga_data_str, yoga,
                    jyotisha.panchangam.temporal.Time(
                        24 *
                        (yoga_end_jd - jd)).toString(format=panchangam.fmt))
        if yoga_end_jd is not None:
            yoga_data_str += '; %s ➥' % (jyotisha.panchangam.temporal.NAMES[
                'YOGA_NAMES'][panchangam.script][(yoga_ID % 27) + 1])
        yoga_data_str = '*' + getName(
            'yOgaH', panchangam.script) + '*—' + yoga_data_str[2:]

        karanam_data_str = ''
        for numKaranam, (karanam_ID, karanam_end_jd) in enumerate(
                panchangam.karanam_data[d]):
            # if numKaranam == 1:
            #     karanam_data_str += ' '
            karanam = jyotisha.panchangam.temporal.NAMES['KARANAM_NAMES'][
                panchangam.script][karanam_ID]
            if karanam_end_jd is None:
                karanam_data_str = '%s; %s►%s' % \
                                   (karanam_data_str, karanam, jyotisha.custom_transliteration.tr('ahOrAtram', panchangam.script))
            else:
                karanam_data_str = '%s; %s►%s' % \
                                   (karanam_data_str, karanam,
                                    jyotisha.panchangam.temporal.Time(24 * (karanam_end_jd - jd)).toString(format=panchangam.fmt))
        if karanam_end_jd is not None:
            karanam_data_str += '; %s ➥' % (jyotisha.panchangam.temporal.NAMES[
                'KARANAM_NAMES'][panchangam.script][(karanam_ID % 60) + 1])
        karanam_data_str = '*' + getName(
            'karaNam', panchangam.script) + '*—' + karanam_data_str[2:]

        sunrise = jyotisha.panchangam.temporal.Time(
            24 *
            (panchangam.jd_sunrise[d] - jd)).toString(format=panchangam.fmt)
        sunset = jyotisha.panchangam.temporal.Time(
            24 *
            (panchangam.jd_sunset[d] - jd)).toString(format=panchangam.fmt)
        moonrise = jyotisha.panchangam.temporal.Time(
            24 *
            (panchangam.jd_moonrise[d] - jd)).toString(format=panchangam.fmt)
        moonset = jyotisha.panchangam.temporal.Time(
            24 *
            (panchangam.jd_moonset[d] - jd)).toString(format=panchangam.fmt)

        # braahma = jyotisha.panchangam.temporal.Time(24 * (panchangam.kaalas[d]['braahma'][0] - jd)).toString(format=panchangam.fmt)
        # pratahsandhya = jyotisha.panchangam.temporal.Time(24 * (panchangam.kaalas[d]['prAtaH sandhyA'][0] - jd)).toString(format=panchangam.fmt)
        # pratahsandhya_end = jyotisha.panchangam.temporal.Time(24 * (panchangam.kaalas[d]['prAtaH sandhyA end'][0] - jd)).toString(format=panchangam.fmt)
        # sangava = jyotisha.panchangam.temporal.Time(24 * (panchangam.kaalas[d]['saGgava'][0] - jd)).toString(format=panchangam.fmt)
        # madhyaahna = jyotisha.panchangam.temporal.Time(24 * (panchangam.kaalas[d]['madhyAhna'][0] - jd)).toString(format=panchangam.fmt)
        # madhyahnika_sandhya = jyotisha.panchangam.temporal.Time(24 * (panchangam.kaalas[d]['mAdhyAhnika sandhyA'][0] - jd)).toString(format=panchangam.fmt)
        # madhyahnika_sandhya_end = jyotisha.panchangam.temporal.Time(24 * (panchangam.kaalas[d]['mAdhyAhnika sandhyA end'][0] - jd)).toString(format=panchangam.fmt)
        aparahna = jyotisha.panchangam.temporal.Time(
            24 * (panchangam.kaalas[d]['aparAhna'][0] - jd)).toString(
                format=panchangam.fmt)
        sayahna = jyotisha.panchangam.temporal.Time(
            24 * (panchangam.kaalas[d]['sAyAhna'][0] - jd)).toString(
                format=panchangam.fmt)
        # sayamsandhya = jyotisha.panchangam.temporal.Time(24 * (panchangam.kaalas[d]['sAyaM sandhyA'][0] - jd)).toString(format=panchangam.fmt)
        # sayamsandhya_end = jyotisha.panchangam.temporal.Time(24 * (panchangam.kaalas[d]['sAyaM sandhyA end'][0] - jd)).toString(format=panchangam.fmt)
        # ratriyama1 = jyotisha.panchangam.temporal.Time(24 * (panchangam.kaalas[d]['rAtri yAma 1'][0] - jd)).toString(format=panchangam.fmt)
        # sayana_time = jyotisha.panchangam.temporal.Time(24 * (panchangam.kaalas[d]['zayana'][0] - jd)).toString(format=panchangam.fmt)
        dinanta = jyotisha.panchangam.temporal.Time(
            24 * (panchangam.kaalas[d]['dinAnta'][0] - jd)).toString(
                format=panchangam.fmt)

        rahu = '%s–%s' % (jyotisha.panchangam.temporal.Time(
            24 * (panchangam.kaalas[d]['rahu'][0] - jd)).toString(
                format=panchangam.fmt),
                          jyotisha.panchangam.temporal.Time(
                              24 *
                              (panchangam.kaalas[d]['rahu'][1] - jd)).toString(
                                  format=panchangam.fmt))
        yama = '%s–%s' % (jyotisha.panchangam.temporal.Time(
            24 * (panchangam.kaalas[d]['yama'][0] - jd)).toString(
                format=panchangam.fmt),
                          jyotisha.panchangam.temporal.Time(
                              24 *
                              (panchangam.kaalas[d]['yama'][1] - jd)).toString(
                                  format=panchangam.fmt))
        gulika = '%s–%s' % (jyotisha.panchangam.temporal.Time(
            24 * (panchangam.kaalas[d]['gulika'][0] - jd)).toString(
                format=panchangam.fmt),
                            jyotisha.panchangam.temporal.Time(
                                24 * (panchangam.kaalas[d]['gulika'][1] -
                                      jd)).toString(format=panchangam.fmt))

        if panchangam.solar_month[d] == 1:
            # Flip the year name for the remaining days
            yname_solar = samvatsara_names[1]
        if panchangam.lunar_month[d] == 1:
            # Flip the year name for the remaining days
            yname_lunar = samvatsara_names[1]

        # Assign samvatsara, ayana, rtu #
        ayanam = jyotisha.panchangam.temporal.NAMES['AYANA_NAMES'][
            panchangam.script][panchangam.solar_month[d]]
        rtu_solar = jyotisha.panchangam.temporal.NAMES['RTU_NAMES'][
            panchangam.script][panchangam.solar_month[d]]
        rtu_lunar = jyotisha.panchangam.temporal.NAMES['RTU_NAMES'][
            panchangam.script][int(ceil(panchangam.lunar_month[d]))]

        if panchangam.solar_month_end_time[d] is None:
            month_end_str = ''
        else:
            _m = panchangam.solar_month[d - 1]
            if panchangam.solar_month_end_time[d] >= panchangam.jd_sunrise[d +
                                                                           1]:
                month_end_str = '%s►%s' % (
                    jyotisha.panchangam.temporal.NAMES['RASHI_NAMES'][
                        panchangam.script][_m],
                    jyotisha.panchangam.temporal.Time(
                        24 * (panchangam.solar_month_end_time[d] -
                              panchangam.jd_midnight[d + 1])).toString(
                                  format=panchangam.fmt))
            else:
                month_end_str = '%s►%s' % (
                    jyotisha.panchangam.temporal.NAMES['RASHI_NAMES'][
                        panchangam.script][_m],
                    jyotisha.panchangam.temporal.Time(
                        24 * (panchangam.solar_month_end_time[d] -
                              panchangam.jd_midnight[d])).toString(
                                  format=panchangam.fmt))
        if month_end_str == '':
            month_data = '%s (%s %d)' % (jyotisha.panchangam.temporal.NAMES[
                'RASHI_NAMES'][panchangam.script][panchangam.solar_month[d]],
                                         getName('dinaM', panchangam.script),
                                         panchangam.solar_month_day[d])
        else:
            month_data = '%s (%s %d); %s' % (
                jyotisha.panchangam.temporal.NAMES['RASHI_NAMES'][
                    panchangam.script][panchangam.solar_month[d]],
                getName('dinaM', panchangam.script),
                panchangam.solar_month_day[d], month_end_str)

        vara = jyotisha.panchangam.temporal.NAMES['VARA_NAMES'][
            panchangam.script][panchangam.weekday[d]]

        if yname_lunar == yname_solar:
            print('*' + getName('saMvatsaraH', panchangam.script) +
                  '*—%s' % yname_lunar,
                  file=output_stream)
            print('*' + getName('ayanam', panchangam.script) + '*—%s' % ayanam,
                  file=output_stream)
        if rtu_lunar == rtu_solar:
            print('*' + getName('RtuH', panchangam.script) +
                  '*—%s' % rtu_lunar,
                  file=output_stream)

        print('°' * 25, file=output_stream)
        print('☀ ' + getName('sauramAnam', panchangam.script),
              file=output_stream)
        if yname_lunar != yname_solar:
            print('*' + getName('saMvatsaraH', panchangam.script) +
                  '*—%s' % yname_solar,
                  file=output_stream)
            print('*' + getName('ayanam', panchangam.script) + '*—%s' % ayanam,
                  file=output_stream)
        if rtu_lunar != rtu_solar:
            print('*' + getName('RtuH', panchangam.script) +
                  '*—%s' % rtu_solar,
                  file=output_stream)
        print('*' + getName('mAsaH', panchangam.script) + '*—%s' % month_data,
              file=output_stream)
        print('°' * 25, file=output_stream)

        print('⚪ ' + getName('cAndramAnam', panchangam.script),
              file=output_stream)
        if yname_lunar != yname_solar:
            print('*' + getName('saMvatsaraH', panchangam.script) +
                  '*—%s' % yname_lunar,
                  file=output_stream)
            print('*' + getName('ayanam', panchangam.script) + '*—%s' % ayanam,
                  file=output_stream)
        if rtu_lunar != rtu_solar:
            print('*' + getName('RtuH', panchangam.script) +
                  '*—%s' % rtu_lunar,
                  file=output_stream)
        print('*' + getName('mAsaH', panchangam.script) +
              '*—%s' % jyotisha.panchangam.temporal.get_chandra_masa(
                  panchangam.lunar_month[d],
                  jyotisha.panchangam.temporal.NAMES, panchangam.script),
              file=output_stream)
        print('°' * 25, file=output_stream)
        # braahma
        # pratahsandhya, pratahsandhya_end
        # sangava
        # madhyahnika_sandhya, madhyahnika_sandhya_end
        # madhyaahna
        # aparahna
        # sayahna
        # sayamsandhya, sayamsandhya_end
        # dinanta
        print('%s' % (paksha_data_str), file=output_stream)
        print('%s' % (tithi_data_str), file=output_stream)
        print('*%s*—%s' % (getName('vAsaraH', panchangam.script), vara),
              file=output_stream)
        print('%s (%s)' % (nakshatram_data_str, rashi_data_str),
              file=output_stream)
        print('%s' % (yoga_data_str), file=output_stream)
        print('%s' % (karanam_data_str), file=output_stream)
        print('%s' % (chandrashtama_rashi_data_str), file=output_stream)

        if panchangam.jd_moonrise[d] > panchangam.jd_sunrise[d + 1]:
            moonrise = '---'
        if panchangam.jd_moonset[d] > panchangam.jd_sunrise[d + 1]:
            moonset = '---'

        print('\nLocation-specific data (for %s):' %
              jyotisha.custom_transliteration.tr(panchangam.city.name,
                                                 panchangam.script),
              file=output_stream)

        if compute_lagnams:
            print('%s' % (lagna_data_str), file=output_stream)

        if panchangam.jd_moonrise[d] < panchangam.jd_moonset[d]:
            print('*%s*—%s; *%s*—%s' %
                  (getName('sUryOdayaH', panchangam.script), sunrise,
                   getName('sUryAstamayaH', panchangam.script), sunset),
                  file=output_stream)
            print('*%s*—%s; *%s*—%s' %
                  (getName('candrOdayaH', panchangam.script), moonrise,
                   getName('candrAstamayaH', panchangam.script), moonset),
                  file=output_stream)
        else:
            print('*%s*—%s; *%s*—%s' %
                  (getName('sUryOdayaH', panchangam.script), sunrise,
                   getName('sUryAstamayaH', panchangam.script), sunset),
                  file=output_stream)
            print('*%s*—%s; *%s*—%s' %
                  (getName('candrAstamayaH', panchangam.script), moonset,
                   getName('candrOdayaH', panchangam.script), moonrise),
                  file=output_stream)

        print(
            '*%s*—%s►%s' %
            (getName('aparAhNa-kAlaH', panchangam.script), aparahna, sayahna),
            file=output_stream)
        print('*%s*—%s' % (getName('dinAntaH', panchangam.script), dinanta),
              file=output_stream)
        print('*%s*—%s;\n*%s*—%s;\n*%s*—%s' %
              (getName('rAhukAlaH', panchangam.script), rahu,
               getName('yamaghaNTaH', panchangam.script), yama,
               getName('gulikakAlaH', panchangam.script), gulika),
              file=output_stream)

        shulam_end_jd = panchangam.jd_sunrise[d] + (
            panchangam.jd_sunset[d] -
            panchangam.jd_sunrise[d]) * (SHULAM[panchangam.weekday[d]][1] / 30)
        print('*%s*—%s (►%s); *%s*–%s' %
              (getName('zUlam', panchangam.script),
               getName(SHULAM[panchangam.weekday[d]][0], panchangam.script),
               jyotisha.panchangam.temporal.Time(
                   24 * (shulam_end_jd - jd)).toString(format=panchangam.fmt),
               getName('parihAraH', panchangam.script),
               getName(SHULAM[panchangam.weekday[d]][2], panchangam.script)),
              file=output_stream)
        # Using set as an ugly workaround since we may have sometimes assigned the same
        # festival to the same day again!
        fest_list = []
        fest_classes = ['kAJcI', 'EkAdazI']
        for f in sorted(set(panchangam.festivals[d])):
            for fcl in fest_classes:
                if f.find(fcl) != -1:
                    fest_name_cleaned = jyotisha.custom_transliteration.tr(
                        f.replace('kAJcI jagadguru', 'jagadguru'),
                        panchangam.script).replace('~', ' ')
                    fest_name_cleaned = re.sub('[{}]', '',
                                               fest_name_cleaned).replace(
                                                   '\\', '')
                    fest_list.append(
                        fest_name_cleaned.replace('ஆராதநா', 'ஆராதனை'))
        if len(fest_list):
            print('\n*%s*—%s' % (getName(
                'dina-vizESAH', panchangam.script), '; '.join(fest_list)),
                  file=output_stream)

        dinanta_hh, dinanta_mm = dinanta.split(':')
        dinanta_hh = int(dinanta_hh) - 24
        dinanta_mm = int(dinanta_mm[:-1])
        footer_text = 'Note: All times are shown in 24h format. Times beyond midnight are shown as %s, meaning %02d:%02d am tomorrow.' % (
            dinanta, dinanta_hh, dinanta_mm)
        output_text = cleanTamilNa(
            output_stream.getvalue()) + '\n\n%s' % footer_text

        event.add('dtstart', date(y, m, dt))
        event.add('dtend', (datetime(y, m, dt) + timedelta(1)).date())
        event.add_component(alarm)
        event.add('description', output_text.replace('\n', '<br/>'))
        event['X-MICROSOFT-CDO-ALLDAYEVENT'] = 'TRUE'
        event['TRANSP'] = 'TRANSPARENT'
        event['X-MICROSOFT-CDO-BUSYSTATUS'] = 'FREE'

        ics_calendar.add_component(event)

        output_stream = StringIO()

        if m == 12 and dt == 31:
            break

    return ics_calendar
def writeMonthlyTeX(panchangam, template_file):
    """Write out the panchangam TeX using a specified template
    """
    day_colours = {0: 'blue', 1: 'blue', 2: 'blue',
                   3: 'blue', 4: 'blue', 5: 'blue', 6: 'blue'}
    month = {1: 'JANUARY', 2: 'FEBRUARY', 3: 'MARCH', 4: 'APRIL',
             5: 'MAY', 6: 'JUNE', 7: 'JULY', 8: 'AUGUST', 9: 'SEPTEMBER',
             10: 'OCTOBER', 11: 'NOVEMBER', 12: 'DECEMBER'}
    MON = {1: 'January', 2: 'February', 3: 'March', 4: 'April',
           5: 'May', 6: 'June', 7: 'July', 8: 'August', 9: 'September',
           10: 'October', 11: 'November', 12: 'December'}
    WDAY = {0: 'Sun', 1: 'Mon', 2: 'Tue',
            3: 'Wed', 4: 'Thu', 5: 'Fri', 6: 'Sat'}

    template_lines = template_file.readlines()
    for i in range(0, len(template_lines) - 3):
        print(template_lines[i][:-1])

    samvatsara_id = (panchangam.year - 1568) % 60 + 1  # distance from prabhava
    samvatsara_names = '%s–%s' % (jyotisha.panchangam.temporal.NAMES['SAMVATSARA_NAMES'][panchangam.script][samvatsara_id],
                                  jyotisha.panchangam.temporal.NAMES['SAMVATSARA_NAMES'][panchangam.script][(samvatsara_id % 60) + 1])

    print('\\mbox{}')
    print('{\\font\\x="Noto Sans UI" at 60 pt\\x %d\\\\[0.5cm]}' % panchangam.year)
    print('\\mbox{\\font\\x="Siddhanta:script=deva" at 48 pt\\x %s}\\\\[0.5cm]' %
          samvatsara_names)
    print('\\mbox{\\font\\x="Siddhanta:script=deva" at 32 pt\\x %s } %%'
          % jyotisha.custom_transliteration.tr('kali', panchangam.script))
    print('{\\font\\x="Noto Sans UI" at 32 pt\\x %d–%d\\\\[0.5cm]}'
          % (panchangam.year + 3100, panchangam.year + 3101))
    print('{\\font\\x="Noto Sans UI" at 48 pt\\x \\uppercase{%s}\\\\[0.2cm]}' %
          panchangam.city.name)
    print('{\\font\\x="Noto Sans UI" at 16 pt\\x {%s}\\\\[0.5cm]}' %
          jyotisha.custom_transliteration.print_lat_lon(panchangam.city.latstr, panchangam.city.lonstr))
    print('\hrule')

    print('\\newpage')
    print('\\centering')
    print('\\centerline{\\LARGE {{%s}}}' % jyotisha.custom_transliteration.tr('mAsAntara-vizESAH', panchangam.script))
    print('\\begin{multicols*}{3}')
    print('\\TrickSupertabularIntoMulticols')
    print('\\begin{supertabular}' +
          '{>{\\sffamily}r>{\\sffamily}r>{\\sffamily}c>{\\hangindent=2ex}p{8cm}}')

    mlast = 1
    for d in range(1, jyotisha.panchangam.temporal.MAX_SZ - 1):
        [y, m, dt, t] = swe.revjul(panchangam.jd_start + d - 1)

        # checking @ 6am local - can we do any better?
        local_time = tz(panchangam.city.timezone).localize(datetime(y, m, dt, 6, 0, 0))
        # compute offset from UTC in hours
        tz_off = (datetime.utcoffset(local_time).days * 86400 +
                  datetime.utcoffset(local_time).seconds) / 3600.0

        # What is the jd at 00:00 local time today?
        jd = panchangam.jd_start - tz_off / 24.0 + d - 1

        if len(panchangam.festivals[d]) != 0:
            if m != mlast:
                mlast = m
                print('\\\\')

            print('%s & %s & %s & {\\raggedright %s} \\\\' %
                  (MON[m], dt, WDAY[panchangam.weekday[d]],
                   '\\\\'.join([jyotisha.custom_transliteration.tr(f, panchangam.script)
                                for f in sorted(set(panchangam.festivals[d]))])))

        if m == 12 and dt == 31:
            break

    print('\\end{supertabular}')
    print('\\end{multicols*}')
    print('\\renewcommand{\\tamil}[1]{%')
    print('{\\fontspec[Scale=0.9,FakeStretch=0.9]{Noto Sans Tamil}\\fontsize{7}{12}\\selectfont #1}}')

    # print('\\clearpage')

    for d in range(1, jyotisha.panchangam.temporal.MAX_SZ - 1):
        [y, m, dt, t] = swe.revjul(panchangam.jd_start + d - 1)

        # checking @ 6am local - can we do any better?
        local_time = tz(panchangam.city.timezone).localize(datetime(y, m, dt, 6, 0, 0))
        # compute offset from UTC in hours
        tz_off = (datetime.utcoffset(local_time).days * 86400 +
                  datetime.utcoffset(local_time).seconds) / 3600.0

        # What is the jd at 00:00 local time today?
        jd = panchangam.jd_start - (tz_off / 24.0) + d - 1

        if dt == 1:
            if m > 1:
                if panchangam.weekday[d] != 0:  # Space till Sunday
                    for i in range(panchangam.weekday[d], 6):
                        print("{}  &")
                    print("\\\\ \hline")
                print('\end{tabular}')
                print('\n\n')

            # Begin tabular
            print('\\begin{tabular}{|c|c|c|c|c|c|c|}')
            print('\multicolumn{7}{c}{\Large \\bfseries \sffamily %s %s}\\\\[3mm]' % (
                month[m], y))
            print('\hline')
            WDAY_NAMES = ['SUN', 'MON', 'TUE', 'WED', 'THU', 'FRI', 'SAT']
            print(' & '.join(['\\textbf{\\textsf{%s}}' %
                              _day for _day in WDAY_NAMES]) + ' \\\\ \hline')

            # Blanks for previous weekdays
            for i in range(0, panchangam.weekday[d]):
                print("{}  &")

        tithi_data_str = ''
        for tithi_ID, tithi_end_jd in panchangam.tithi_data[d]:
            # if tithi_data_str != '':
            #     tithi_data_str += '\\hspace{2ex}'
            tithi = '\moon[scale=0.6]{%d}\\hspace{2pt}' % (tithi_ID) + \
                    jyotisha.panchangam.temporal.NAMES['TITHI_NAMES'][panchangam.script][tithi_ID]
            if tithi_end_jd is None:
                tithi_data_str = '%s\\mbox{%s\\To{}%s}' % \
                                 (tithi_data_str, tithi, jyotisha.custom_transliteration.tr('ahOrAtram', panchangam.script))
            else:
                tithi_data_str = '%s\\mbox{%s\\To{}\\textsf{%s%s}}' % \
                                 (tithi_data_str, tithi,
                                  jyotisha.panchangam.temporal.Time(24 * (tithi_end_jd - jd)).toString(format=panchangam.fmt),
                                  '\\hspace{2ex}')

        nakshatram_data_str = ''
        for nakshatram_ID, nakshatram_end_jd in panchangam.nakshatram_data[d]:
            # if nakshatram_data_str != '':
            #     nakshatram_data_str += '\\hspace{2ex}'
            nakshatram = jyotisha.panchangam.temporal.NAMES['NAKSHATRAM_NAMES'][panchangam.script][nakshatram_ID]
            if nakshatram_end_jd is None:
                nakshatram_data_str = '%s\\mbox{%s\\To{}%s}' % \
                                      (nakshatram_data_str, nakshatram,
                                       jyotisha.custom_transliteration.tr('ahOrAtram', panchangam.script))
            else:
                nakshatram_data_str = '%s\\mbox{%s\\To{}\\textsf{%s%s}}' % \
                                      (nakshatram_data_str, nakshatram,
                                       jyotisha.panchangam.temporal.Time(24 * (nakshatram_end_jd -
                                                                               jd)).toString(format=panchangam.fmt),
                                       '\\hspace{2ex}')

        yogam_data_str = ''
        for yogam_ID, yogam_end_jd in panchangam.yogam_data[d]:
            # if yogam_data_str != '':
            #     yogam_data_str += '\\hspace{2ex}'
            yogam = jyotisha.panchangam.temporal.NAMES['YOGAM_NAMES'][panchangam.script][yogam_ID]
            if yogam_end_jd is None:
                yogam_data_str = '%s\\mbox{%s\\To{}%s}' % \
                                 (yogam_data_str, yogam, jyotisha.custom_transliteration.tr('ahOrAtram', panchangam.script))
            else:
                yogam_data_str = '%s\\mbox{%s\\To{}\\textsf{%s%s}}' % \
                                 (yogam_data_str, yogam,
                                  jyotisha.panchangam.temporal.Time(24 * (yogam_end_jd - jd)).toString(format=panchangam.fmt),
                                  '\\hspace{2ex}')

        karanam_data_str = ''
        for numKaranam, (karanam_ID, karanam_end_jd) in enumerate(panchangam.karanam_data[d]):
            # if numKaranam == 1:
            #     karanam_data_str += '\\hspace{2ex}'
            if numKaranam == 2:
                karanam_data_str = karanam_data_str + '\\\\'
            karanam = jyotisha.panchangam.temporal.NAMES['KARANAM_NAMES'][panchangam.script][karanam_ID]
            if karanam_end_jd is None:
                karanam_data_str = '%s\\mbox{%s\\To{}%s}' % \
                                   (karanam_data_str, karanam,
                                    jyotisha.custom_transliteration.tr('ahOrAtram', panchangam.script))
            else:
                karanam_data_str = '%s\\mbox{%s\\To{}\\textsf{%s%s}}' % \
                                   (karanam_data_str, karanam,
                                    jyotisha.panchangam.temporal.Time(24 * (karanam_end_jd -
                                                                            jd)).toString(format=panchangam.fmt), '\\hspace{2ex}')

        sunrise = jyotisha.panchangam.temporal.Time(24 * (panchangam.jd_sunrise[d] - jd)).toString(format=panchangam.fmt)
        sunset = jyotisha.panchangam.temporal.Time(24 * (panchangam.jd_sunset[d] - jd)).toString(format=panchangam.fmt)
        sangava = jyotisha.panchangam.temporal.Time(24 * (panchangam.kaalas[d]['saGgava'][0] - jd)).toString(format=panchangam.fmt)
        rahu = '%s--%s' % (
            jyotisha.panchangam.temporal.Time(24 * (panchangam.kaalas[d]['rahu'][0] - jd)).toString(format=panchangam.fmt),
            jyotisha.panchangam.temporal.Time(24 * (panchangam.kaalas[d]['rahu'][1] - jd)).toString(format=panchangam.fmt))
        yama = '%s--%s' % (
            jyotisha.panchangam.temporal.Time(24 * (panchangam.kaalas[d]['yama'][0] - jd)).toString(format=panchangam.fmt),
            jyotisha.panchangam.temporal.Time(24 * (panchangam.kaalas[d]['yama'][1] - jd)).toString(format=panchangam.fmt))

        print('\caldata{\\textcolor{%s}{%s}}{%s{%s}}%%' %
              (day_colours[panchangam.weekday[d]], dt, panchangam.month_data[d],
               jyotisha.panchangam.temporal.get_chandra_masa(panchangam.lunar_month[d],
                                                             jyotisha.panchangam.temporal.NAMES, panchangam.script)))
        print('{\\sundata{%s}{%s}{%s}}%%' % (sunrise, sunset, sangava))
        print('{\\tnyk{%s}%%\n{%s}%%\n{%s}%%\n{%s}}%%' % (tithi_data_str, nakshatram_data_str,
                                                          yogam_data_str, karanam_data_str))
        print('{\\rahuyama{%s}{%s}}%%' % (rahu, yama))

        # Using set as an ugly workaround since we may have sometimes assigned the same
        # festival to the same day again!
        print('{%s}' % '\\eventsep '.join(
            [jyotisha.custom_transliteration.tr(f, panchangam.script) for f in sorted(set(panchangam.festivals[d]))]))

        if panchangam.weekday[d] == 6:
            print("\\\\ \hline")
        else:
            print("&")

        if m == 12 and dt == 31:
            break

            # For debugging specific dates
            # if m==4 and dt==10:
            #  break

    for i in range(panchangam.weekday[d] + 1, 6):
        print("{}  &")
    if panchangam.weekday[d] != 6:
        print("\\\\ \hline")
    print('\end{tabular}')
    print('\n\n')

    print(template_lines[-2][:-1])
    print(template_lines[-1][:-1])
def main():
    city_name = sys.argv[1]
    latitude = sexastr2deci(sys.argv[2])
    longitude = sexastr2deci(sys.argv[3])
    tz = sys.argv[4]

    start_year = int(sys.argv[5])
    year = start_year
    jd = swisseph.julday(year, 1, 1, 0)
    jd_start = jd

    if len(sys.argv) == 7:
        script = sys.argv[6]
    else:
        script = 'deva'  #Default script is devanagari

    swisseph.set_sid_mode(swisseph.SIDM_LAHIRI)  #Force Lahiri Ayanamsha

    sun_month_day = jd - get_last_dhanur_transit(jd, latitude, longitude)

    month_start_after_set = 0

    template_file = open('cal_template_compre.tex')
    template_lines = template_file.readlines()
    for i in range(0, len(template_lines) - 3):
        print template_lines[i][:-1]

    samvatsara_id = (year - 1568) % 60 + 1
    #distance from prabhava
    samvatsara_names = '%s–%s' % (year_names[script][samvatsara_id],
                                  year_names[script][(samvatsara_id % 60) + 1])
    new_yr = mesha_sankranti[script] + '~(' + year_names[script][
        (samvatsara_id % 60) + 1] + '-' + samvatsara[script] + ')'

    print '\\mbox{}'
    print '{\\font\\x="Candara" at 60 pt\\x %d\\\\[0.5cm]}' % year
    print '\\mbox{\\font\\x="Sanskrit 2003:script=deva" at 48 pt\\x %s}\\\\[0.5cm]' % samvatsara_names
    print '{\\font\\x="Candara" at 48 pt\\x \\uppercase{%s}\\\\[0.5cm]}' % city_name
    print '\hrule'

    #INITIALISE VARIABLES
    jd_sunrise = [None] * 368
    jd_sunset = [None] * 368
    jd_moonrise = [None] * 368
    longitude_moon = [None] * 368
    longitude_sun = [None] * 368
    longitude_sun_set = [None] * 368
    sun_month_id = [None] * 368
    sun_month = [None] * 368
    sun_month_rise = [None] * 368
    moon_month = [None] * 368
    month_data = [None] * 368
    tithi_data_string = [None] * 368
    tithi_sunrise = [None] * 368
    nakshatram_data_string = [None] * 368
    nakshatram_sunrise = [None] * 368
    karanam_data_string = [None] * 368
    karanam_sunrise = [None] * 368
    yogam_data_string = [None] * 368
    yogam_sunrise = [None] * 368
    weekday = [None] * 368
    sunrise = [None] * 368
    sunset = [None] * 368
    madhya = [None] * 368
    rahu = [None] * 368
    yama = [None] * 368
    festival_day_list = {}
    festivals = [''] * 368

    weekday_start = swisseph.day_of_week(jd) + 1
    #swisseph has Mon = 0, non-intuitively!

    ##################################################
    #Compute all parameters -- latitude/longitude etc#
    ##################################################

    for d in range(-1, 367):
        jd = jd_start - 1 + d
        [y, m, dt, t] = swisseph.revjul(jd)
        weekday = (weekday_start - 1 + d) % 7

        local_time = pytz.timezone(tz).localize(datetime(y, m, dt, 6, 0, 0))
        #checking @ 6am local - can we do any better?
        tz_off = datetime.utcoffset(local_time).seconds / 3600.0
        #compute offset from UTC

        jd_sunrise[d + 1] = swisseph.rise_trans(
            jd_start=jd + 1,
            body=swisseph.SUN,
            lon=longitude,
            lat=latitude,
            rsmi=swisseph.CALC_RISE | swisseph.BIT_DISC_CENTER)[1][0]
        jd_sunset[d + 1] = swisseph.rise_trans(
            jd_start=jd + 1,
            body=swisseph.SUN,
            lon=longitude,
            lat=latitude,
            rsmi=swisseph.CALC_SET | swisseph.BIT_DISC_CENTER)[1][0]
        jd_moonrise[d + 1] = swisseph.rise_trans(
            jd_start=jd + 1,
            body=swisseph.MOON,
            lon=longitude,
            lat=latitude,
            rsmi=swisseph.CALC_RISE | swisseph.BIT_DISC_CENTER)[1][0]

        longitude_sun[d + 1] = swisseph.calc_ut(
            jd_sunrise[d + 1], swisseph.SUN)[0] - swisseph.get_ayanamsa(
                jd_sunrise[d + 1])
        longitude_moon[d + 1] = swisseph.calc_ut(
            jd_sunrise[d + 1], swisseph.MOON)[0] - swisseph.get_ayanamsa(
                jd_sunrise[d + 1])
        longitude_sun_set[d + 1] = swisseph.calc_ut(
            jd_sunset[d + 1], swisseph.SUN)[0] - swisseph.get_ayanamsa(
                jd_sunset[d + 1])

        sun_month_id[d + 1] = int(1 + math.floor((
            (longitude_sun_set[d + 1]) % 360) / 30.0))
        sun_month[d + 1] = int(1 + math.floor((
            (longitude_sun_set[d + 1]) % 360) / 30.0))

        sun_month_rise[d + 1] = int(1 + math.floor((
            (longitude_sun[d + 1]) % 360) / 30.0))

        if (d <= 0):
            continue

        t_sunrise = (jd_sunrise[d] - jd) * 24.0 + tz_off
        t_sunset = (jd_sunset[d] - jd) * 24.0 + tz_off

        #Solar month calculations
        if month_start_after_set == 1:
            sun_month_day = 0
            month_start_after_set = 0

        if sun_month[d] != sun_month[d + 1]:
            sun_month_day = sun_month_day + 1

            if sun_month[d] != sun_month_rise[d + 1]:
                month_start_after_set = 1
                [_m, sun_month_end_time] = get_angam_data_string(
                    masa_names[script], 30, jd_sunrise[d], jd_sunrise[d + 1],
                    t_sunrise, longitude_moon[d], longitude_sun[d],
                    longitude_moon[d + 1], longitude_sun[d + 1], [0, 1],
                    script)

        elif sun_month_rise[d] != sun_month[d]:
            #mAsa pirappu!
            #sun moves into next rAsi before sunset -- check rules!
            sun_month_day = 1

            [_m, sun_month_end_time] = get_angam_data_string(
                masa_names[script], 30, jd_sunrise[d], jd_sunrise[d + 1],
                t_sunrise, longitude_moon[d], longitude_sun[d],
                longitude_moon[d + 1], longitude_sun[d + 1], [0, 1], script)

        else:
            sun_month_day = sun_month_day + 1
            sun_month_end_time = ''

        month_data[d] = '\\sunmonth{%s}{%d}{%s}' % (masa_names[script][
            sun_month[d]], sun_month_day, sun_month_end_time)

        #KARADAYAN NOMBU -- easy to check here
        if sun_month_end_time != '':  #month ends today
            if (sun_month[d] == 12
                    and sun_month_day == 1) or (sun_month[d] == 11
                                                and sun_month_day != 1):
                festival_day_list[karadayan_nombu[script]] = [d]

        #Sunrise/sunset and related stuff (like rahu, yama)
        [rhs, rms, rss] = deci2sexa(
            t_sunrise)  #rise hour sun, rise minute sun, rise sec sun
        [shs, sms, sss] = deci2sexa(t_sunset)

        length_of_day = t_sunset - t_sunrise
        yamagandam_start = t_sunrise + (1 / 8.0) * (
            yamagandam_octets[weekday] - 1) * length_of_day
        yamagandam_end = yamagandam_start + (1 / 8.0) * length_of_day
        rahukalam_start = t_sunrise + (1 / 8.0) * (rahukalam_octets[weekday] -
                                                   1) * length_of_day
        rahukalam_end = rahukalam_start + (1 / 8.0) * length_of_day
        madhyahnikam_start = t_sunrise + (1 / 5.0) * length_of_day

        sunrise[d] = '%02d:%02d' % (rhs, rms)
        sunset[d] = '%02d:%02d' % (shs, sms)
        madhya[d] = print_time(madhyahnikam_start)
        rahu[d] = '%s--%s' % (print_time(rahukalam_start),
                              print_time(rahukalam_end))
        yama[d] = '%s--%s' % (print_time(yamagandam_start),
                              print_time(yamagandam_end))

        [tithi_sunrise[d], tithi_data_string[d]] = get_angam_data_string(
            tithi_names[script], 12, jd_sunrise[d], jd_sunrise[d + 1],
            t_sunrise, longitude_moon[d], longitude_sun[d],
            longitude_moon[d + 1], longitude_sun[d + 1], [1, -1], script)
        [nakshatram_sunrise[d],
         nakshatram_data_string[d]] = get_angam_data_string(
             nakshatra_names[script], (360.0 / 27.0), jd_sunrise[d],
             jd_sunrise[d + 1], t_sunrise, longitude_moon[d], longitude_sun[d],
             longitude_moon[d + 1], longitude_sun[d + 1], [1, 0], script)
        [karanam_sunrise[d], karanam_data_string[d]] = get_angam_data_string(
            karanam_names[script], 6, jd_sunrise[d], jd_sunrise[d + 1],
            t_sunrise, longitude_moon[d], longitude_sun[d],
            longitude_moon[d + 1], longitude_sun[d + 1], [1, -1], script)
        [yogam_sunrise[d], yogam_data_string[d]] = get_angam_data_string(
            yogam_names[script], (360.0 / 27.0), jd_sunrise[d],
            jd_sunrise[d + 1], t_sunrise, longitude_moon[d], longitude_sun[d],
            longitude_moon[d + 1], longitude_sun[d + 1], [1, 1], script)

    #ASSIGN MOON MONTHS
    last_month_change = 1
    last_moon_month = None
    for d in range(1, 367):
        #Assign moon_month for each day
        if (tithi_sunrise[d] == 1):
            for i in range(last_month_change, d):
                #print '%%#Setting moon_month to sun_month_id, for i=%d:%d to %d' %(last_month_change,d-1,sun_month_id[d])
                if (sun_month_id[d] == last_moon_month):
                    moon_month[i] = sun_month_id[d] % 12 + 0.5
                else:
                    moon_month[i] = sun_month_id[d]
            last_month_change = d
            last_moon_month = sun_month_id[d]
        elif (tithi_sunrise[d] == 2 and tithi_sunrise[d - 1] == 30):
            #prathama tithi was never seen @ sunrise
            for i in range(last_month_change, d):
                #print '%%@Setting moon_month to sun_month_id, for i=%d:%d to %d (last month = %d)' %(last_month_change,d-1,sun_month_id[d],last_moon_month)
                if (sun_month_id[d - 1] == last_moon_month):
                    moon_month[i] = sun_month_id[d - 1] % 12 + 0.5
                else:
                    moon_month[i] = sun_month_id[d - 1]
            last_month_change = d
            last_moon_month = sun_month_id[d - 1]

    for i in range(last_month_change, 367):
        moon_month[i] = sun_month_id[last_month_change - 1] + 1

    #for d in range(1,367):
    #jd = jd_start-1+d
    #[y,m,dt,t] = swisseph.revjul(jd)
    #print '%%#%02d-%02d-%4d: %3d:%s (sunrise tithi=%d) {%s}' % (dt,m,y,d,moon_month[d],tithi_sunrise[d],tithi_data_string[d])

    log_file = open('cal_log_%4d.txt' % year, 'w')
    for d in range(1, 367):
        jd = jd_start - 1 + d
        [y, m, dt, t] = swisseph.revjul(jd)
        log_data = '%02d-%02d-%4d\t[%3d]\tsun_rashi=%8.3f\ttithi=%8.3f\tsun_month=%2d\tmoon_month=%4.1f\n' % (
            dt, m, y, d, (longitude_sun_set[d] % 360) / 30.0,
            get_angam_float(jd_sunrise[d], 12.0,
                            [1, -1]), sun_month[d], moon_month[d])
        log_file.write(log_data)

    #PRINT CALENDAR

    for d in range(1, 367):
        jd = jd_start - 1 + d
        [y, m, dt, t] = swisseph.revjul(jd)
        weekday = (weekday_start - 1 + d) % 7

        ##################
        #Festival details#
        ##################

        ###--- MONTHLY VRATAMS ---###

        #EKADASHI Vratam
        if tithi_sunrise[d] == 11 or tithi_sunrise[
                d] == 12:  #One of two consecutive tithis must appear @ sunrise!
            #check for shukla ekadashi[script]
            if (tithi_sunrise[d] == 11 and tithi_sunrise[d + 1] == 11):
                festivals[d + 1] = sarva[script] + '~' + get_ekadashi_name(
                    paksha='shukla', month=moon_month[d],
                    script=script)  #moon_month[d] or [d+1]?
                if moon_month[d + 1] == 4:
                    festivals[d + 1] += '\\\\' + chaturmasya_start[script]
                if moon_month[d + 1] == 8:
                    festivals[d + 1] += '\\\\' + chaturmasya_end[script]
            elif (tithi_sunrise[d] == 11 and tithi_sunrise[d + 1] != 11):
                #Check dashami end time to decide for whether this is sarva[script]/smartha[script]
                tithi_arunodayam = get_tithi(
                    jd_sunrise[d] - (1 / 15.0) *
                    (jd_sunrise[d] - jd_sunrise[d - 1])
                )  #Two muhurtams is 1/15 of day-length
                if tithi_arunodayam == 10:
                    festivals[d] = smartha[script] + '~' + get_ekadashi_name(
                        paksha='shukla', month=moon_month[d], script=script)
                    festivals[d +
                              1] = vaishnava[script] + '~' + get_ekadashi_name(
                                  paksha='shukla',
                                  month=moon_month[d],
                                  script=script)
                    if moon_month[d] == 4:
                        festivals[d] += '\\\\' + chaturmasya_start[script]
                    if moon_month[d] == 8:
                        festivals[d] += '\\\\' + chaturmasya_end[script]
                else:
                    festivals[d] = sarva[script] + '~' + get_ekadashi_name(
                        paksha='shukla', month=moon_month[d], script=script)
                    if moon_month[d] == 4:
                        festivals[d] += '\\\\' + chaturmasya_start[script]
                    if moon_month[d] == 8:
                        festivals[d] += '\\\\' + chaturmasya_end[script]
            elif (tithi_sunrise[d - 1] != 11 and tithi_sunrise[d] == 12):
                festivals[d] = sarva[script] + '~' + get_ekadashi_name(
                    paksha='shukla', month=moon_month[d], script=script)
                if moon_month[d] == 4:
                    festivals[d] += '\\\\' + chaturmasya_start[script]
                if moon_month[d] == 8:
                    festivals[d] += '\\\\' + chaturmasya_end[script]

        if tithi_sunrise[d] == 26 or tithi_sunrise[
                d] == 27:  #One of two consecutive tithis must appear @ sunrise!
            #check for krishna ekadashi[script]
            if (tithi_sunrise[d] == 26 and tithi_sunrise[d + 1] == 26):
                festivals[d + 1] = sarva[script] + '~' + get_ekadashi_name(
                    paksha='krishna', month=moon_month[d],
                    script=script)  #moon_month[d] or [d+1]?
            elif (tithi_sunrise[d] == 26 and tithi_sunrise[d + 1] != 26):
                #Check dashami end time to decide for whether this is sarva[script]/smartha[script]
                tithi_arunodayam = get_tithi(
                    jd_sunrise[d] - (1 / 15.0) *
                    (jd_sunrise[d] - jd_sunrise[d - 1])
                )  #Two muhurtams is 1/15 of day-length
                if tithi_arunodayam == 25:
                    festivals[d] = smartha[script] + '~' + get_ekadashi_name(
                        paksha='krishna', month=moon_month[d], script=script)
                    festivals[d +
                              1] = vaishnava[script] + '~' + get_ekadashi_name(
                                  paksha='krishna',
                                  month=moon_month[d],
                                  script=script)
                else:
                    festivals[d] = sarva[script] + '~' + get_ekadashi_name(
                        paksha='krishna', month=moon_month[d], script=script)
            elif (tithi_sunrise[d - 1] != 26 and tithi_sunrise[d] == 27):
                festivals[d] = sarva[script] + '~' + get_ekadashi_name(
                    paksha='krishna', month=moon_month[d], script=script)

        #PRADOSHA Vratam
        if tithi_sunrise[d] == 12 or tithi_sunrise[d] == 13:
            ldiff_set = (swisseph.calc_ut(jd_sunset[d], swisseph.MOON)[0] -
                         swisseph.calc_ut(jd_sunset[d], swisseph.SUN)[0]) % 360
            ldiff_set_tmrw = (
                swisseph.calc_ut(jd_sunset[d + 1], swisseph.MOON)[0] -
                swisseph.calc_ut(jd_sunset[d + 1], swisseph.SUN)[0]) % 360
            tithi_sunset = int(1 + math.floor(ldiff_set / 12.0))
            tithi_sunset_tmrw = int(1 + math.floor(ldiff_set_tmrw / 12.0))
            if tithi_sunset <= 13 and tithi_sunset_tmrw != 13:
                festivals[d] = pradosham[script]
            elif tithi_sunset_tmrw == 13:
                festivals[d + 1] = pradosham[script]

        if tithi_sunrise[d] == 27 or tithi_sunrise[d] == 28:
            ldiff_set = (swisseph.calc_ut(jd_sunset[d], swisseph.MOON)[0] -
                         swisseph.calc_ut(jd_sunset[d], swisseph.SUN)[0]) % 360
            ldiff_set_tmrw = (
                swisseph.calc_ut(jd_sunset[d + 1], swisseph.MOON)[0] -
                swisseph.calc_ut(jd_sunset[d + 1], swisseph.SUN)[0]) % 360
            tithi_sunset = int(1 + math.floor(ldiff_set / 12.0))
            tithi_sunset_tmrw = int(1 + math.floor(ldiff_set_tmrw / 12.0))
            if tithi_sunset <= 28 and tithi_sunset_tmrw != 28:
                festivals[d] = pradosham[script]
            elif tithi_sunset_tmrw == 28:
                festivals[d + 1] = pradosham[script]

        #SANKATAHARA chaturthi[script]
        if tithi_sunrise[d] == 18 or tithi_sunrise[d] == 19:
            ldiff_moonrise_yest = (
                swisseph.calc_ut(jd_moonrise[d - 1], swisseph.MOON)[0] -
                swisseph.calc_ut(jd_moonrise[d - 1], swisseph.SUN)[0]) % 360
            ldiff_moonrise = (
                swisseph.calc_ut(jd_moonrise[d], swisseph.MOON)[0] -
                swisseph.calc_ut(jd_moonrise[d], swisseph.SUN)[0]) % 360
            ldiff_moonrise_tmrw = (
                swisseph.calc_ut(jd_moonrise[d + 1], swisseph.MOON)[0] -
                swisseph.calc_ut(jd_moonrise[d + 1], swisseph.SUN)[0]) % 360
            tithi_moonrise_yest = int(1 +
                                      math.floor(ldiff_moonrise_yest / 12.0))
            tithi_moonrise = int(1 + math.floor(ldiff_moonrise / 12.0))
            tithi_moonrise_tmrw = int(1 +
                                      math.floor(ldiff_moonrise_tmrw / 12.0))

            if tithi_moonrise == 19:
                if tithi_moonrise_yest != 19:  #otherwise yesterday would have already been assigned
                    festivals[d] = chaturthi[script]
                    if moon_month[d] == 5:  #shravana krishna chaturthi[script]
                        festivals[d] = maha[script] + festivals[d]
            elif tithi_moonrise_tmrw == 19:
                festivals[d + 1] = chaturthi[script]
                if moon_month[
                        d] == 5:  #moon_month[d] and[d+1] are same, so checking [d] is enough
                    festivals[d + 1] = maha[script] + festivals[d + 1]

        #SHASHTHI Vratam
        if tithi_sunrise[d] == 5 or tithi_sunrise[d] == 6:
            if tithi_sunrise[d] == 6 or (tithi_sunrise[d] == 5
                                         and tithi_sunrise[d + 1] == 7):
                if tithi_sunrise[
                        d -
                        1] != 6:  #otherwise yesterday would have already been assigned
                    festivals[d] = shashthi[script]
                    if moon_month[d] == 8:  #kArtika krishna shashthi[script]
                        festivals[d] = skanda[script] + festivals[d]
            elif tithi_sunrise[d + 1] == 6:
                festivals[d + 1] = shashthi[script]
                if moon_month[
                        d] == 8:  #moon_month[d] and[d+1] are same, so checking [d] is enough
                    festivals[d + 1] = skanda[script] + festivals[d + 1]

        ###--- OTHER (MAJOR) FESTIVALS ---###
        #type of month | month number | type of angam (tithi|nakshatram) | angam number | min_t cut off for considering prev day (without sunrise_angam) as festival date
        purvaviddha_rules = {
            akshaya_tritiya[script]: ['moon_month', 2, 'tithi', 3, 0],
            chitra_purnima[script]: ['sun_month', 1, 'tithi', 15, 0],
            durgashtami[script]: ['moon_month', 7, 'tithi', 8, 0],
            mahanavami[script]: ['moon_month', 7, 'tithi', 9, 0],
            vijayadashami[script]: ['moon_month', 7, 'tithi', 10, 0],
            dipavali[script]: ['moon_month', 7, 'tithi', 29, 0],
            shankara_jayanti[script]: ['moon_month', 2, 'tithi', 5, 0],
            yajur_upakarma[script]: ['moon_month', 5, 'tithi', 15, 0],
            rg_upakarma[script]: ['moon_month', 5, 'nakshatram', 22, 0],
            sama_upakarma[script]: ['sun_month', 5, 'nakshatram', 13, 0],
            rishi_panchami[script]: ['moon_month', 6, 'tithi', 5, 0],
            ananta_chaturdashi[script]: ['moon_month', 6, 'tithi', 14, 0],
            mahalaya_paksham[script]: ['moon_month', 6, 'tithi', 16, 0],
            hanumat_jayanti[script]: ['sun_month', 9, 'tithi', 30, 0],
            ardra_darshanam[script]: ['sun_month', 9, 'nakshatram', 6, 0],
            ratha_saptami[script]: ['sun_month', 10, 'tithi', 7, 0],
            goda_jayanti[script]: ['sun_month', 4, 'nakshatram', 11, 0],
            adi_krittika[script]: ['sun_month', 4, 'nakshatram', 3, 0],
            phalguni_uttaram[script]: ['sun_month', 12, 'nakshatram', 12, 4],
            mahalaya_amavasya[script]: ['moon_month', 6, 'tithi', 30, 0],
            uma_maheshvara_vratam[script]: ['moon_month', 6, 'tithi', 15, 0]
        }

        for x in iter(purvaviddha_rules.keys()):
            rule = purvaviddha_rules[x]
            if rule[0] == 'moon_month':
                if moon_month[d] == rule[1]:
                    if rule[2] == 'tithi':
                        fday = get_festival_day_purvaviddha(
                            rule[3], tithi_sunrise, d, jd_sunrise[d],
                            jd_sunrise[d + 1], get_tithi, rule[4])
                    elif rule[2] == 'nakshatram':
                        fday = get_festival_day_purvaviddha(
                            rule[3], nakshatram_sunrise, d, jd_sunrise[d],
                            jd_sunrise[d + 1], get_nakshatram, rule[4])
                    if fday is not None:
                        if festival_day_list.has_key(x):
                            if festival_day_list[x][0] != fday:
                                #Second occurrence of a festival within a Gregorian calendar year
                                festival_day_list[x] = [
                                    festival_day_list[x][0], fday
                                ]
                        else:
                            festival_day_list[x] = [fday]
            elif rule[0] == 'sun_month':
                if sun_month[d] == rule[1]:
                    if rule[2] == 'tithi':
                        fday = get_festival_day_purvaviddha(
                            rule[3], tithi_sunrise, d, jd_sunrise[d],
                            jd_sunrise[d + 1], get_tithi, rule[4])
                    elif rule[2] == 'nakshatram':
                        fday = get_festival_day_purvaviddha(
                            rule[3], nakshatram_sunrise, d, jd_sunrise[d],
                            jd_sunrise[d + 1], get_nakshatram, rule[4])
                    if fday is not None:
                        if festival_day_list.has_key(x):
                            if festival_day_list[x][0] != fday:
                                #Second occurrence of a festival within a Gregorian calendar year
                                festival_day_list[x] = [
                                    festival_day_list[x][0], fday
                                ]
                        else:
                            festival_day_list[x] = [fday]
            else:
                print 'Error; unknown string in rule: %s' % (rule[0])
                return

        #NAVARATRI START
        if moon_month[d] == 7 and moon_month[d - 1] == 6:
            festival_day_list[navaratri_start[script]] = [d]

        #PONGAL/AYANAM
        if sun_month[d] == 10 and sun_month[d - 1] == 9:
            festival_day_list[uttarayanam[script]] = [d]

        if sun_month[d] == 4 and sun_month[d - 1] == 3:
            festival_day_list[dakshinayanam[script]] = [d]

        if sun_month[d] == 1 and sun_month[d - 1] == 12:
            festival_day_list[new_yr] = [d]

        if moon_month[d] == 1 and moon_month[d - 1] != 1:
            festival_day_list[yugadi[script]] = [d]

        #SHRIRAMANAVAMI
        if moon_month[d] == 1:
            if tithi_sunrise[d] == 8 or tithi_sunrise[d] == 9:
                t_11 = get_tithi(jd_sunrise[d] +
                                 (jd_sunset[d] - jd_sunrise[d]) *
                                 (2.0 / 5.0))  #madhyahna1 start
                t_12 = get_tithi(jd_sunrise[d] +
                                 (jd_sunset[d] - jd_sunrise[d]) *
                                 (3.0 / 5.0))  #madhyahna1 end
                t_21 = get_tithi(jd_sunrise[d + 1] +
                                 (jd_sunset[d + 1] - jd_sunrise[d + 1]) *
                                 (2.0 / 5.0))  #madhyahna2 start
                t_22 = get_tithi(jd_sunrise[d + 1] +
                                 (jd_sunset[d + 1] - jd_sunrise[d + 1]) *
                                 (3.0 / 5.0))  #madhyahna2 end
                if t_11 == 9 or t_12 == 9:
                    if t_21 == 9 or t_22 == 9:
                        festival_day_list[ramanavami[script]] = [d + 1]
                    else:
                        festival_day_list[ramanavami[script]] = [d]

        #JANMASHTAMI
        if moon_month[d] == 5:
            if tithi_sunrise[d] == 22 or tithi_sunrise[d] == 23:
                t_11 = get_tithi(jd_sunset[d] +
                                 (jd_sunrise[d + 1] - jd_sunset[d]) *
                                 (7.0 / 15.0))  #nishita1 start
                t_12 = get_tithi(jd_sunset[d] +
                                 (jd_sunrise[d + 1] - jd_sunset[d]) *
                                 (8.0 / 15.0))  #nishita1 end
                #t_11 = get_tithi(jd_sunset[d]+(jd_sunrise[d+1]-jd_sunset[d])*(2.0/5.0))#madhyaratri1 start
                #t_12 = get_tithi(jd_sunset[d]+(jd_sunrise[d+1]-jd_sunset[d])*(3.0/5.0))#madhyaratri1 end
                t_21 = get_tithi(jd_sunset[d + 1] +
                                 (jd_sunrise[d + 2] - jd_sunset[d + 1]) *
                                 (7.0 / 15.0))  #nishita2 start
                t_22 = get_tithi(jd_sunset[d + 1] +
                                 (jd_sunrise[d + 2] - jd_sunset[d + 1]) *
                                 (8.0 / 15.0))  #nishita2 end
                #t_21 = get_tithi(jd_sunset[d+1]+(jd_sunrise[d+2]-jd_sunset[d+1])*(2.0/5.0))#madhyaratri2 start
                #t_22 = get_tithi(jd_sunset[d+1]+(jd_sunrise[d+2]-jd_sunset[d+1])*(3.0/5.0))#madhyaratri2 end
                if t_11 == 23 or t_12 == 23:
                    if t_21 == 23 or t_22 == 23:
                        festival_day_list[janmashtami[script]] = [d + 1]
                    else:
                        festival_day_list[janmashtami[script]] = [d]

        #SHIVARATRI
        if moon_month[d] == 11:
            if tithi_sunrise[d] == 28 or tithi_sunrise[d] == 29:
                t_11 = get_tithi(jd_sunset[d] +
                                 (jd_sunrise[d + 1] - jd_sunset[d]) *
                                 (7.0 / 15.0))  #nishita1 start
                t_12 = get_tithi(jd_sunset[d] +
                                 (jd_sunrise[d + 1] - jd_sunset[d]) *
                                 (8.0 / 15.0))  #nishita1 end
                t_21 = get_tithi(jd_sunset[d + 1] +
                                 (jd_sunrise[d + 2] - jd_sunset[d + 1]) *
                                 (7.0 / 15.0))  #nishita2 start
                t_22 = get_tithi(jd_sunset[d + 1] +
                                 (jd_sunrise[d + 2] - jd_sunset[d + 1]) *
                                 (8.0 / 15.0))  #nishita2 end
                if t_11 == 29 or t_12 == 29:
                    if t_21 == 29 or t_22 == 29:
                        festival_day_list[shivaratri[script]] = [d + 1]
                    else:
                        festival_day_list[shivaratri[script]] = [d]

        #VINAYAKA CHATURTHI
        if moon_month[d] == 6:
            if tithi_sunrise[d] == 3 or tithi_sunrise[d] == 4:
                t_11 = get_tithi(jd_sunrise[d] +
                                 (jd_sunset[d] - jd_sunrise[d]) *
                                 (2.0 / 5.0))  #madhyahna1 start
                t_12 = get_tithi(jd_sunrise[d] +
                                 (jd_sunset[d] - jd_sunrise[d]) *
                                 (3.0 / 5.0))  #madhyahna1 end
                t_21 = get_tithi(jd_sunrise[d + 1] +
                                 (jd_sunset[d + 1] - jd_sunrise[d + 1]) *
                                 (2.0 / 5.0))  #madhyahna2 start
                t_22 = get_tithi(jd_sunrise[d + 1] +
                                 (jd_sunset[d + 1] - jd_sunrise[d + 1]) *
                                 (3.0 / 5.0))  #madhyahna2 end
                if t_11 == 4 or t_12 == 4:
                    if t_21 == 4 or t_22 == 4:
                        festival_day_list[vchaturthi[script]] = [d + 1]
                    else:
                        festival_day_list[vchaturthi[script]] = [d]

    #Add saved festivals
    festival_day_list[gayatri_japam[script]] = [
        festival_day_list[yajur_upakarma[script]][0] + 1
    ]
    festival_day_list[varalakshmi_vratam[script]] = [
        festival_day_list[yajur_upakarma[script]][0] -
        ((weekday_start - 1 + festival_day_list[yajur_upakarma[script]][0] - 5)
         % 7)
    ]
    #KARADAYAN_NOMBU
    for x in iter(festival_day_list.keys()):
        for j in range(0, len(festival_day_list[x])):
            if festivals[festival_day_list[x][j]] != '':
                festivals[festival_day_list[x][j]] += '\\\\'
            festivals[festival_day_list[x][j]] += x

    ###--- ECLIPSES ---###
    ###--- LUNAR ECLIPSES ---###
    swisseph.set_topo(lon=longitude, lat=latitude, alt=0.0)  #Set location
    jd = jd_start
    while 1:
        next_ecl_lun = swisseph.lun_eclipse_when(jd)
        jd = next_ecl_lun[1][0] + (tz_off / 24.0)
        jd_ecl_lun_start = next_ecl_lun[1][2] + (tz_off / 24.0)
        jd_ecl_lun_end = next_ecl_lun[1][3] + (tz_off / 24.0)
        ecl_y = swisseph.revjul(
            jd - 1
        )[0]  # -1 is to not miss an eclipse that occurs after sunset on 31-Dec!
        if ecl_y != start_year:
            break
        else:
            ecl_lun_start = swisseph.revjul(jd_ecl_lun_start)[3]
            ecl_lun_end = swisseph.revjul(jd_ecl_lun_end)[3]
            if (jd_ecl_lun_start -
                (tz_off / 24.0)) == 0.0 or (jd_ecl_lun_end -
                                            (tz_off / 24.0)) == 0.0:
                jd = jd + 20  #Move towards the next eclipse... at least the next full moon (>=25 days away)
                continue
            fday = int(math.floor(jd_ecl_lun_start) - math.floor(jd_start) + 1)
            #print '%%',jd,fday,jd_sunrise[fday],jd_sunrise[fday-1]
            if (jd < (jd_sunrise[fday] + tz_off / 24.0)):
                fday -= 1
            if ecl_lun_start < swisseph.revjul(jd_sunrise[fday + 1] +
                                               tz_off / 24.0)[3]:
                ecl_lun_start += 24
            #print '%%',jd,fday,jd_sunrise[fday],jd_sunrise[fday-1],ecl_lun_start, ecl_lun_end
            jd_moonrise_ecl_day = swisseph.rise_trans(
                jd_start=jd_sunrise[fday],
                body=swisseph.MOON,
                lon=longitude,
                lat=latitude,
                rsmi=swisseph.CALC_RISE
                | swisseph.BIT_DISC_CENTER)[1][0] + (tz_off / 24.0)
            jd_moonset_ecl_day = swisseph.rise_trans(
                jd_start=jd_moonrise_ecl_day,
                body=swisseph.MOON,
                lon=longitude,
                lat=latitude,
                rsmi=swisseph.CALC_SET
                | swisseph.BIT_DISC_CENTER)[1][0] + (tz_off / 24.0)
            #if jd_ecl_lun_start<(jd_sunrise[fday]+(tz_off/24.0)):
            if ecl_lun_end < ecl_lun_start:
                ecl_lun_end += 24
            #print '%%', (jd_ecl_lun_start), (jd_ecl_lun_end), (jd_moonrise_ecl_day), (jd_moonset_ecl_day)
            #print '%%', swisseph.revjul(jd_ecl_lun_start), swisseph.revjul(jd_ecl_lun_end), swisseph.revjul(jd_moonrise_ecl_day), swisseph.revjul(jd_moonset_ecl_day)
            if jd_ecl_lun_end < jd_moonrise_ecl_day or jd_ecl_lun_start > jd_moonset_ecl_day:
                jd = jd + 20  #Move towards the next eclipse... at least the next full moon (>=25 days away)
                continue
            lun_ecl_str = chandra_grahanam[script] + '~\\textsf{' + print_time2(
                ecl_lun_start) + '}{\\RIGHTarrow}\\textsf{' + print_time2(
                    ecl_lun_end) + '}'
            if festivals[fday] != '':
                festivals[fday] += '\\\\'
            festivals[fday] += lun_ecl_str
        jd = jd + 20

    ###--- SOLAR ECLIPSES ---###
    swisseph.set_topo(lon=longitude, lat=latitude, alt=0.0)  #Set location
    jd = jd_start
    while 1:
        next_ecl_sol = swisseph.sol_eclipse_when_loc(julday=jd,
                                                     lon=longitude,
                                                     lat=latitude)
        jd = next_ecl_sol[1][0] + (tz_off / 24.0)
        jd_ecl_sol_start = next_ecl_sol[1][1] + (tz_off / 24.0)
        jd_ecl_sol_end = next_ecl_sol[1][4] + (tz_off / 24.0)
        ecl_y = swisseph.revjul(
            jd - 1
        )[0]  # -1 is to not miss an eclipse that occurs after sunset on 31-Dec!
        if ecl_y != start_year:
            break
        else:
            #print '%%', fday, (jd_ecl_sol_start), (jd_ecl_sol_end), (jd_sunrise[fday])
            #print '%%', swisseph.revjul(jd_ecl_sol_start), swisseph.revjul(jd_ecl_sol_end), swisseph.revjul(jd_sunrise[fday])
            fday = int(math.floor(jd) - math.floor(jd_start) + 1)
            if (jd < (jd_sunrise[fday] + tz_off / 24.0)):
                fday -= 1
            #print '%%', fday, (jd_ecl_sol_start), (jd_ecl_sol_end), (jd_sunrise[fday])
            #print '%%', swisseph.revjul(jd_ecl_sol_start), swisseph.revjul(jd_ecl_sol_end), swisseph.revjul(jd_sunrise[fday])
            ecl_sol_start = swisseph.revjul(jd_ecl_sol_start)[3]
            ecl_sol_end = swisseph.revjul(jd_ecl_sol_end)[3]
            if (jd_ecl_sol_start - (tz_off / 24.0)) == 0.0 or (
                    jd_ecl_sol_end - (tz_off / 24.0)
            ) == 0.0:  # or jd_ecl_end<jd_sunrise[fday] or jd_ecl_start>jd_sunset[fday]:
                jd = jd + 20  #Move towards the next eclipse... at least the next new moon (>=25 days away)
                continue
            if ecl_sol_end < ecl_sol_start:
                ecl_sol_end += 24
            sol_ecl_str = surya_grahanam[script] + '~\\textsf{' + print_time2(
                ecl_sol_start) + '}{\\RIGHTarrow}\\textsf{' + print_time2(
                    ecl_sol_end) + '}'
            if festivals[fday] != '':
                festivals[fday] += '\\\\'
            festivals[fday] += sol_ecl_str
        jd = jd + 20
    ###--- FESTIVAL ADDITIONS COMPLETE ---###

    ###--- PRINT LIST OF FESTIVALS (Page 2) ---###
    if script == 'en':
        cal = Calendar()

    print '\\newpage'
    print '\\centerline {\\LARGE {{%s}}}\\mbox{}\\\\[2cm]' % list_of_festivals[
        script]
    print '\\begin{center}'
    print '\\begin{minipage}[t]{0.3\\linewidth}'
    print '\\begin{center}'
    print '\\begin{tabular}{>{\\sffamily}r>{\\sffamily}r>{\\sffamily}cp{6cm}}'

    mlast = 1
    for d in range(1, 367):
        jd = jd_start - 1 + d
        [y, m, dt, t] = swisseph.revjul(jd)
        weekday = (weekday_start - 1 + d) % 7

        if festivals[d] != '':
            if m != mlast:
                mlast = m
                #print '\\hline\\\\'
                print '\\\\'
                if m == 5 or m == 9:
                    print '\\end{tabular}'
                    print '\\end{center}'
                    print '\\end{minipage}\hspace{1cm}%'
                    print '\\begin{minipage}[t]{0.3\\linewidth}'
                    print '\\begin{center}'
                    print '\\begin{tabular}{>{\\sffamily}r>{\\sffamily}l>{\\sffamily}cp{6cm}}'

            print '%s & %s & %s & {\\raggedright %s} \\\\' % (
                MON[m], dt, WDAY[weekday], festivals[d])

            if script == 'en':
                event = Event()
                event.add('summary', festivals[d])
                event.add('dtstart', datetime(y, m, dt))
                event.add('dtend', datetime(y, m, dt))
                cal.add_component(event)

        if m == 12 and dt == 31:
            break

    print '\\end{tabular}'
    print '\\end{center}'
    print '\\end{minipage}'
    print '\\end{center}'
    print '\\clearpage'

    if script == 'en':
        cal_fname = '%s-%4d.ics' % (city_name, start_year)
        cal_file = open(cal_fname, 'w')
        cal_file.write(cal.as_string())
        cal_file.close()

    #Layout calendar in LATeX format
    #We use a separate loop here, because of festivals like varalakshmi
    #vratam, for which we backtrack to the previous friday from yajur
    #upakarma and change the list of festivals!

    for d in range(1, 367):
        jd = jd_start - 1 + d
        [y, m, dt, t] = swisseph.revjul(jd)
        weekday = (weekday_start - 1 + d) % 7

        if dt == 1:
            if m > 1:
                if weekday != 0:  #Space till Sunday
                    for i in range(weekday, 6):
                        print "{}  &"
                    print "\\\\ \hline"
                print '\end{tabular}'
                print '\n\n'

            #Begin tabular
            print '\\begin{tabular}{|c|c|c|c|c|c|c|}'
            print '\multicolumn{7}{c}{\Large \\bfseries \sffamily %s %s}\\\\[3mm]' % (
                month[m], y)
            print '\hline'
            print '\\textbf{\\textsf{SUN}} & \\textbf{\\textsf{MON}} & \\textbf{\\textsf{TUE}} & \\textbf{\\textsf{WED}} & \\textbf{\\textsf{THU}} & \\textbf{\\textsf{FRI}} & \\textbf{\\textsf{SAT}} \\\\ \hline'
            #print '\\textbf{भानु} & \\textbf{इन्दु} & \\textbf{भौम} & \\textbf{बुध} & \\textbf{गुरु} & \\textbf{भृगु} & \\textbf{स्थिर} \\\\ \hline'

            #Blanks for previous weekdays
            for i in range(0, weekday):
                print "{}  &"

        print '\caldata{\\textcolor{%s}{%s}}{%s{%s}}{\\sundata{%s}{%s}{%s}}{\\tnyk{%s}{%s}{%s}{%s}}{\\rahuyama{%s}{%s}}{%s} ' % (
            daycol[weekday], dt, month_data[d],
            get_chandra_masa(moon_month[d], chandra_masa_names, script),
            sunrise[d], sunset[d], madhya[d], tithi_data_string[d],
            nakshatram_data_string[d], yogam_data_string[d],
            karanam_data_string[d], rahu[d], yama[d], festivals[d])

        if weekday == 6:
            print "\\\\ \hline"
        else:
            print "&"

        if m == 12 and dt == 31:
            break

        # For debugging specific dates
        #if m==4 and dt==10:
        #  break

    for i in range(weekday + 1, 6):
        print "{}  &"
    if weekday != 6:
        print "\\\\ \hline"
    print '\end{tabular}'
    print '\n\n'

    print template_lines[-2][:-1]
    print template_lines[-1][:-1]