Esempio n. 1
0
def night(
    observer: Observer,
    date: Optional[datetime.date] = None,
    tzinfo: datetime.tzinfo = pytz.utc,
) -> Tuple[datetime.datetime, datetime.datetime]:
    """Calculate night start and end times.

    Night is calculated to be between astronomical dusk on the
    date specified and astronomical dawn of the next day.

    Args:
        observer: Observer to calculate night for
        date:     Date to calculate for. Default is today's date for the
                  specified tzinfo.
        tzinfo:   Timezone to return times in. Default is UTC.

    Returns:
        A tuple of the date and time at which night starts and ends.

    Raises:
        ValueError: if dawn does not occur on the specified date or
                    dusk on the following day
    """
    if date is None:
        date = today(tzinfo)

    start = dusk(observer, date, 6, tzinfo)
    tomorrow = date + datetime.timedelta(days=1)
    end = dawn(observer, tomorrow, 6, tzinfo)

    return start, end
Esempio n. 2
0
def sun(
    observer: Observer,
    date: Optional[datetime.date] = None,
    dawn_dusk_depression: Union[float, Depression] = Depression.CIVIL,
    tzinfo: datetime.tzinfo = pytz.utc,
) -> Dict:
    """Calculate all the info for the sun at once.

    Args:
        observer:             Observer for which to calculate the times of the sun
        date:                 Date to calculate for.
                              Default is today's date in the timezone `tzinfo`.
        dawn_dusk_depression: Depression to use to calculate dawn and dusk.
                              Default is for Civil dusk i.e. 6.0
        tzinfo:               Timezone to return times in. Default is UTC.

    Returns:
        Dictionary with keys ``dawn``, ``sunrise``, ``noon``, ``sunset`` and ``dusk``
        whose values are the results of the corresponding functions.

    Raises:
        ValueError: if passed through from any of the functions
    """

    if date is None:
        date = today(tzinfo)

    return {
        "dawn": dawn(observer, date, dawn_dusk_depression, tzinfo),
        "sunrise": sunrise(observer, date, tzinfo),
        "noon": noon(observer, date, tzinfo),
        "sunset": sunset(observer, date, tzinfo),
        "dusk": dusk(observer, date, dawn_dusk_depression, tzinfo),
    }
Esempio n. 3
0
def daylight(
    observer: Observer,
    date: Optional[datetime.date] = None,
    tzinfo: datetime.tzinfo = pytz.utc,
) -> Tuple[datetime.datetime, datetime.datetime]:
    """Calculate daylight start and end times.

    Args:
        observer: Observer to calculate daylight for
        date:     Date to calculate for. Default is today's date in the timezone `tzinfo`.
        tzinfo:   Timezone to return times in. Default is UTC.

    Returns:
        A tuple of the date and time at which daylight starts and ends.

    Raises:
        ValueError: if the sun does not rise or does not set 
    """
    if date is None:
        date = today(tzinfo)

    start = sunrise(observer, date, tzinfo)
    end = sunset(observer, date, tzinfo)

    return start, end
Esempio n. 4
0
def phase(date: Optional[datetime.date] = None) -> float:
    """Calculates the phase of the moon on the specified date.

    Args:
        date: The date to calculate the phase for. Dates are always in the UTC timezone.
              If not specified then today's date is used.

    Returns:
        A number designating the phase.

        ============  ==============
        0 .. 6.99     New moon
        7 .. 13.99    First quarter
        14 .. 20.99   Full moon
        21 .. 27.99   Last quarter
        ============  ==============
    """

    if date is None:
        date = today()

    moon = _phase_asfloat(date)
    if moon >= 28.0:
        moon -= 28.0
    return moon
Esempio n. 5
0
def midnight(
    observer: Observer,
    date: Optional[datetime.date] = None,
    tzinfo: Union[str, datetime.tzinfo] = pytz.utc,
) -> datetime.datetime:
    """Calculate solar midnight time.

    Note:
        This calculates the solar midnight that is closest
        to 00:00:00 of the specified date i.e. it may return a time that is on
        the previous day.

    Args:
        observer: An observer viewing the sun at a specific, latitude, longitude and elevation
        date:     Date to calculate for. Default is today for the specified tzinfo.
        tzinfo:   Timezone to return times in. Default is UTC.

    Returns:
        Date and time at which midnight occurs.
    """
    if isinstance(tzinfo, str):
        tzinfo = pytz.timezone(tzinfo)

    if date is None:
        date = today(tzinfo)

    jd = julianday(date)
    newt = jday_to_jcentury(jd + 0.5 + -observer.longitude / 360.0)

    eqtime = eq_of_time(newt)
    timeUTC = (-observer.longitude * 4.0) - eqtime

    timeUTC = timeUTC / 60.0
    hour = int(timeUTC)
    minute = int((timeUTC - hour) * 60)
    second = int((((timeUTC - hour) * 60) - minute) * 60)

    if second > 59:
        second -= 60
        minute += 1
    elif second < 0:
        second += 60
        minute -= 1

    if minute > 59:
        minute -= 60
        hour += 1
    elif minute < 0:
        minute += 60
        hour -= 1

    if hour < 0:
        hour += 24
        date -= datetime.timedelta(days=1)

    midnight = datetime.datetime(date.year, date.month, date.day, hour, minute,
                                 second)
    return pytz.utc.localize(midnight).astimezone(tzinfo)  # pylint: disable=E1120
Esempio n. 6
0
def noon(
    observer: Observer,
    date: Optional[datetime.date] = None,
    tzinfo: Union[str, datetime.tzinfo] = pytz.utc,
) -> datetime.datetime:
    """Calculate solar noon time when the sun is at its highest point.

    Args:
        observer: An observer viewing the sun at a specific, latitude, longitude and elevation
        date:     Date to calculate for. Default is today for the specified tzinfo.
        tzinfo:   Timezone to return times in. Default is UTC.

    Returns:
        Date and time at which noon occurs.
    """
    if isinstance(tzinfo, str):
        tzinfo = pytz.timezone(tzinfo)

    if date is None:
        date = today(tzinfo)

    jc = jday_to_jcentury(julianday(date))
    eqtime = eq_of_time(jc)
    timeUTC = (720.0 - (4 * observer.longitude) - eqtime) / 60.0

    hour = int(timeUTC)
    minute = int((timeUTC - hour) * 60)
    second = int((((timeUTC - hour) * 60) - minute) * 60)

    if second > 59:
        second -= 60
        minute += 1
    elif second < 0:
        second += 60
        minute -= 1

    if minute > 59:
        minute -= 60
        hour += 1
    elif minute < 0:
        minute += 60
        hour -= 1

    if hour > 23:
        hour -= 24
        date += datetime.timedelta(days=1)
    elif hour < 0:
        hour += 24
        date -= datetime.timedelta(days=1)

    noon = datetime.datetime(date.year, date.month, date.day, hour, minute,
                             second)
    return pytz.utc.localize(noon).astimezone(tzinfo)  # pylint: disable=E1120
Esempio n. 7
0
def page7():
    global lastday
    global sunrise_m
    global sunset_m

    now = time.localtime()
    hh = now.tm_hour
    mm = now.tm_min
    today = now.tm_mday

    ## partial clock setup
    daybegin = 8
    dayend = 23

    daymin = (hh * 60) + mm
    minbegin = daybegin * 60
    minend = dayend * 60
    if ((daymin >= minbegin) and (daymin <= minend)):
        tleft = (minend - daymin) / float(minend - minbegin)
    else:
        tleft = 0

    ## angle for partial clock
    pangle = (180 * (1 - tleft)) - 90

    ## angle for 24h clock
    cangle = 90 + (-360 * (1 - (daymin / float(24 * 60))))

    ## sunrise sunset calculation
    if (lastday != today):
        lastday = today
        mysun = sun(observer, astral.today())
        sunrise = mysun['sunrise'].astimezone(Berlin_tz)
        sunset = mysun['sunset'].astimezone(Berlin_tz)
        sunrise_m = int((sunrise.hour * 60) + sunrise.minute)
        sunset_m = int((sunset.hour * 60) + sunset.minute)

    now_m = (now.tm_hour * 60) + now.tm_min

    if ((now_m < sunrise_m) or (now_m > sunset_m)):
        sunscale = 0
    else:
        sunscale = 1 - ((now_m - sunrise_m) / (sunset_m - sunrise_m))

    sunangle = (180 * sunscale) + 90

    ## draw
    dr.rectangle((0, 0, 128, 64), fill=0)
    dr.arc((-30, 0, 30, 60), pangle, 90, fill=1, width=20)
    dr.arc((34, 0, 94, 60), cangle, 90, fill=1, width=20)
    dr.arc((98, 0, 158, 60), 90, sunangle, fill=1, width=20)
Esempio n. 8
0
def time_at_elevation(
    observer: Observer,
    elevation: float,
    date: Optional[datetime.date] = None,
    direction: SunDirection = SunDirection.RISING,
    tzinfo: Union[str, datetime.tzinfo] = pytz.utc,
) -> datetime.datetime:
    """Calculates the time when the sun is at the specified elevation on the specified date.

    Note:
        This method uses positive elevations for those above the horizon.

        Elevations greater than 90 degrees are converted to a setting sun
        i.e. an elevation of 110 will calculate a setting sun at 70 degrees.

    Args:
        elevation: Elevation of the sun in degrees above the horizon to calculate for.
        observer:  Observer to calculate for
        date:      Date to calculate for. Default is today's date in the timezone `tzinfo`.
        direction: Determines whether the calculated time is for the sun rising or setting.
                   Use ``SunDirection.RISING`` or ``SunDirection.SETTING``. Default is rising.
        tzinfo:    Timezone to return times in. Default is UTC.

    Returns:
        Date and time at which the sun is at the specified elevation.
    """

    if elevation > 90.0:
        elevation = 180.0 - elevation
        direction = SunDirection.SETTING

    if isinstance(tzinfo, str):
        tzinfo = pytz.timezone(tzinfo)

    if date is None:
        date = today(tzinfo)

    zenith = 90 - elevation
    try:
        return time_of_transit(observer, date, zenith,
                               direction).astimezone(tzinfo)
    except ValueError as exc:
        if exc.args[0] == "math domain error":
            raise ValueError(
                f"Sun never reaches an elevation of {elevation} degrees "
                "at this location.") from exc
        else:
            raise
Esempio n. 9
0
def rahukaalam(
    observer: Observer,
    date: Optional[datetime.date] = None,
    daytime: bool = True,
    tzinfo: Union[str, datetime.tzinfo] = pytz.utc,
) -> Tuple[datetime.datetime, datetime.datetime]:
    """Calculate ruhakaalam times.

    Args:
        observer: Observer to calculate rahukaalam for
        date:     Date to calculate for. Default is today's date in the timezone `tzinfo`.
        daytime:  If True calculate for the day time else calculate for the night time.
        tzinfo:   Timezone to return times in. Default is UTC.

    Returns:
        Tuple containing the start and end times for Rahukaalam.

    Raises:
        ValueError: if the sun does not rise or does not set
    """

    if isinstance(tzinfo, str):
        tzinfo = pytz.timezone(tzinfo)

    if date is None:
        date = today(tzinfo)

    if daytime:
        start = sunrise(observer, date, tzinfo)
        end = sunset(observer, date, tzinfo)
    else:
        start = sunset(observer, date, tzinfo)
        oneday = datetime.timedelta(days=1)
        end = sunrise(observer, date + oneday, tzinfo)

    octant_duration = datetime.timedelta(seconds=(end - start).seconds / 8)

    # Mo,Sa,Fr,We,Th,Tu,Su
    octant_index = [1, 6, 4, 5, 3, 2, 7]

    weekday = date.weekday()
    octant = octant_index[weekday]

    start = start + (octant_duration * octant)
    end = start + octant_duration

    return start, end
Esempio n. 10
0
def twilight(
    observer: Observer,
    date: Optional[datetime.date] = None,
    direction: SunDirection = SunDirection.RISING,
    tzinfo: Union[str, datetime.tzinfo] = pytz.utc,
) -> Tuple[datetime.datetime, datetime.datetime]:
    """Returns the start and end times of Twilight
    when the sun is traversing in the specified direction.

    This method defines twilight as being between the time
    when the sun is at -6 degrees and sunrise/sunset.

    Args:
        observer:  Observer to calculate twilight for
        date:      Date for which to calculate the times.
                      Default is today's date in the timezone `tzinfo`.
        direction: Determines whether the time is for the sun rising or setting.
                      Use ``astral.SunDirection.RISING`` or ``astral.SunDirection.SETTING``.
        tzinfo:    Timezone to return times in. Default is UTC.

    Returns:
        A tuple of the date and time at which twilight starts and ends.

    Raises:
        ValueError: if the sun does not rise or does not set
    """

    if isinstance(tzinfo, str):
        tzinfo = pytz.timezone(tzinfo)

    if date is None:
        date = today(tzinfo)

    start = time_of_transit(observer, date, 90 + 6,
                            direction).astimezone(tzinfo)
    if direction == SunDirection.RISING:
        end = sunrise(observer, date, tzinfo).astimezone(tzinfo)
    else:
        end = sunset(observer, date, tzinfo).astimezone(tzinfo)

    if direction == SunDirection.RISING:
        return start, end
    else:
        return end, start
Esempio n. 11
0
def dusk(
    observer: Observer,
    date: Optional[datetime.date] = None,
    depression: Union[float, Depression] = Depression.CIVIL,
    tzinfo: Union[str, datetime.tzinfo] = pytz.utc,
) -> datetime.datetime:
    """Calculate dusk time.

    Args:
        observer:   Observer to calculate dusk for
        date:       Date to calculate for. Default is today's date in the timezone `tzinfo`.
        depression: Number of degrees below the horizon to use to calculate dusk.
                    Default is for Civil dusk i.e. 6.0
        tzinfo:     Timezone to return times in. Default is UTC.

    Returns:
        Date and time at which dusk occurs.

    Raises:
        ValueError: if dusk does not occur on the specified date
    """

    if isinstance(tzinfo, str):
        tzinfo = pytz.timezone(tzinfo)

    if date is None:
        date = today(tzinfo)

    dep: float = 0.0
    if isinstance(depression, Depression):
        dep = depression.value
    else:
        dep = depression

    try:
        return time_of_transit(observer, date, 90.0 + dep,
                               SunDirection.SETTING).astimezone(tzinfo)
    except ValueError as exc:
        if exc.args[0] == "math domain error":
            raise ValueError(
                f"Sun never reaches {dep} degrees below the horizon, at this location."
            ) from exc
        else:
            raise
Esempio n. 12
0
def golden_hour(
    observer: Observer,
    date: Optional[datetime.date] = None,
    direction: SunDirection = SunDirection.RISING,
    tzinfo: Union[str, datetime.tzinfo] = pytz.utc,
) -> Tuple[datetime.datetime, datetime.datetime]:
    """Returns the start and end times of the Golden Hour
    when the sun is traversing in the specified direction.

    This method uses the definition from PhotoPills i.e. the
    golden hour is when the sun is between 4 degrees below the horizon
    and 6 degrees above.

    Args:
        observer:  Observer to calculate the golden hour for
        date:      Date for which to calculate the times.
                      Default is today's date in the timezone `tzinfo`.
        direction: Determines whether the time is for the sun rising or setting.
                      Use ``SunDirection.RISING`` or ``SunDirection.SETTING``.
        tzinfo:    Timezone to return times in. Default is UTC.

    Returns:
        A tuple of the date and time at which the Golden Hour starts and ends.

    Raises:
        ValueError: if the sun does not transit the elevations -4 & +6 degrees
    """

    if isinstance(tzinfo, str):
        tzinfo = pytz.timezone(tzinfo)

    if date is None:
        date = today(tzinfo)

    start = time_of_transit(observer, date, 90 + 4,
                            direction).astimezone(tzinfo)
    end = time_of_transit(observer, date, 90 - 6, direction).astimezone(tzinfo)

    if direction == SunDirection.RISING:
        return start, end
    else:
        return end, start
Esempio n. 13
0
def sunset(
    observer: Observer,
    date: Optional[datetime.date] = None,
    tzinfo: Union[str, datetime.tzinfo] = pytz.utc,
) -> datetime.datetime:
    """Calculate sunset time.

    Args:
        observer: Observer to calculate sunset for
        date:     Date to calculate for. Default is today's date in the timezone `tzinfo`.
        tzinfo:   Timezone to return times in. Default is UTC.

    Returns:
        Date and time at which sunset occurs.

    Raises:
        ValueError: if the sun does not reach the horizon
    """

    if isinstance(tzinfo, str):
        tzinfo = pytz.timezone(tzinfo)

    if date is None:
        date = today(tzinfo)

    try:
        return time_of_transit(
            observer,
            date,
            90.0 + SUN_APPARENT_RADIUS,
            SunDirection.SETTING,
        ).astimezone(tzinfo)
    except ValueError as exc:
        if exc.args[0] == "math domain error":
            z = zenith(observer, noon(observer, date))
            if z > 90.0:
                msg = "Sun is always below the horizon on this day, at this location."
            else:
                msg = "Sun is always above the horizon on this day, at this location."
            raise ValueError(msg) from exc
        else:
            raise
Esempio n. 14
0
 def test_australia(self):
     assert today(timezone("Australia/Melbourne")).day == 2
Esempio n. 15
0
 def test_adak(self):
     assert today(timezone("America/Adak")).day == 1
Esempio n. 16
0
def test_ElevationEqualsTimeAtElevation(elevation, london):
    o = london.observer
    td = today()
    et = sun.time_at_elevation(o, elevation, td)
    assert sun.elevation(o, et) == pytest.approx(elevation, abs=0.05)
Esempio n. 17
0
 def today(self, local: bool = True) -> datetime.date:
     if local:
         return today(self.tzinfo)
     else:
         return today()
Esempio n. 18
0
 def test_default_timezone(self):
     td = today()
     assert td.year == 2020
     assert td.month == 1
     assert td.day == 1