docs: def sun_rise_set(latitude, longitude, date, mode='rise', timezone=0,
                   zenith=None):
      """Calculate sunrise or sunset for a specific location.
  
      This function calculates the time sunrise or sunset, or optionally the
      beginning or end of a specified twilight period.
  
      Source::
  
          Almanac for Computers, 1990
          published by Nautical Almanac Office
          United States Naval Observatory
          Washington, DC 20392
  
      Args:
          latitude (float): Location's latitude
          longitude (float): Location's longitude
          date (datetime.date): Calculate rise or set for given date
          mode (str): Which time to calculate
          timezone (int): Offset from UTC in minutes
          zenith (str): Calculate rise/set events, or twilight times
  
      Returns:
          datetime.time or None: The time for the given event in the specified
              timezone, or ``None`` if the event doesn't occur on the given date
  
      Raises:
          ValueError: Unknown value for ``mode``
      """
      if not date:
          date = datetime.date.today()
  
      zenith = ZENITH[zenith]
  
      # First calculate the day of the year
      # Thanks, datetime this would have been ugly without you!!!
      n = (date - datetime.date(date.year - 1, 12, 31)).days
  
      # Convert the longitude to hour value and calculate an approximate time
      lng_hour = longitude / 15
  
      if mode == 'rise':
          t = n + ((6 - lng_hour) / 24)
      elif mode == 'set':
          t = n + ((18 - lng_hour) / 24)
      else:
          raise ValueError('Unknown mode value %r' % mode)
  
      # Calculate the Sun's mean anomaly
      m = (0.9856 * t) - 3.289
  
      # Calculate the Sun's true longitude
      l = m + 1.916 * math.sin(math.radians(m)) + 0.020 \
          * math.sin(2 * math.radians(m)) + 282.634
      l = abs(l) % 360
  
      # Calculate the Sun's right ascension
      ra = math.degrees(math.atan(0.91764 * math.tan(math.radians(l))))
  
      # Right ascension value needs to be in the same quadrant as L
      l_quandrant = (math.floor(l / 90)) * 90
      ra_quandrant = (math.floor(ra / 90)) * 90
      ra = ra + (l_quandrant - ra_quandrant)
  
      # Right ascension value needs to be converted into hours
      ra = ra / 15
  
      # Calculate the Sun's declination
      sin_dec = 0.39782 * math.sin(math.radians(l))
      cos_dec = math.cos(math.asin(sin_dec))
  
      # Calculate the Sun's local hour angle
      cos_h = (math.radians(zenith) -
               (sin_dec * math.sin(math.radians(latitude)))) \
          / (cos_dec * math.cos(math.radians(latitude)))
  
      if cos_h > 1:
          # The sun never rises on this location (on the specified date)
          return None
      elif cos_h < -1:
          # The sun never sets on this location (on the specified date)
          return None
  
      # Finish calculating H and convert into hours
      if mode == 'rise':
          h = 360 - math.degrees(math.acos(cos_h))
      else:
          h = math.degrees(math.acos(cos_h))
      h = h / 15
  
      # Calculate local mean time of rising/setting
      t = h + ra - (0.06571 * t) - 6.622
  
      # Adjust back to UTC
      utc = t - lng_hour
  
      # Convert UT value to local time zone of latitude/longitude
      local_t = utc + timezone / 60
      if local_t < 0:
          local_t += 24
      elif local_t > 23:
          local_t -= 24
  
      hour = int(local_t)
      if hour == 0:
          minute = int(60 * local_t)
      else:
          minute = int(60 * (local_t % hour))
      if minute < 0:
          minute += 60
      return datetime.time(hour, minute)