docs: def cycles(cls, **kwargs):
          """
          Classmethod for convienence in returning both the sunrise and sunset
          based on a location and date.  Always calculates the sunrise and sunset on the
          given date, no matter the time passed into the function in the datetime object.
  
          Parameters:
              loc = Location4D (object)
                  OR
              point = Shapely point (object)
              time = datetime in UTC (object)
                  OR
              lat = latitude (float)
              lon = longitude (float)
              time = datetime in UTC (object)
  
          Returns:
              { 'sunrise': datetime in UTC, 'sunset': datetime in UTC }
  
  
          Sources:
              http://williams.best.vwh.net/sunrise_sunset_example.htm
          """
          if "loc" not in kwargs:
              if "point" not in kwargs:
                  if "lat" not in kwargs or "lon" not in kwargs:
                      raise ValueError("You must supply some form of lat/lon coordinates")
                  else:
                      lat = kwargs.get("lat")
                      lon = kwargs.get("lon")
              else:
                  lat = kwargs.get("point").y
                  lon = kwargs.get("point").x
              if "time" not in kwargs:
                  raise ValueError("You must supply a datetime object")
              else:
                  time = kwargs.get("time")
          else:
              lat = kwargs.get("loc").latitude
              lon = kwargs.get("loc").longitude
              time = kwargs.get("loc").time
  
          # Convert time to UTC.  Save passed in timezone to return later.
          if time.tzinfo is None:
              time = time.replace(tzinfo=pytz.utc)
              original_zone = pytz.utc
          else:
              original_zone = time.tzinfo
  
          local_jd = time.timetuple().tm_yday
          utc_jd = time.astimezone(pytz.utc).timetuple().tm_yday
  
          # We ALWAYS want to return the sunrise/sunset for the day that was passed
          # in (with timezone accounted for), regardless of what the UTC day is.  Modify
          # the UTC julian day here if need be.
          comp = cmp(utc_jd, local_jd)
          if comp == 1:
              utc_jd -= 1
          elif comp == -1:
              utc_jd += 1
  
          time = time.replace(hour=0, minute=0, second=0, microsecond=0)
  
          rising_h, rising_m = cls._calc(jd=utc_jd, lat=lat, lon=lon, stage=cls.RISING)
          setting_h, setting_m = cls._calc(jd=utc_jd, lat=lat, lon=lon, stage=cls.SETTING)
  
          # _calc returns UTC hours and minutes, so assume time is in UTC for a few lines...
          rising = time.replace(tzinfo=pytz.utc) + timedelta(hours=rising_h, minutes=rising_m)
          setting = time.replace(tzinfo=pytz.utc) + timedelta(hours=setting_h, minutes=setting_m)
          # LOOK: We may be adding 24 hours to the setting time.  Why?
          if setting < rising:
              setting = setting + timedelta(hours=24)
  
          rising = rising.astimezone(original_zone)
          setting = setting.astimezone(original_zone)
  
          return { cls.RISING : rising, cls.SETTING : setting}