<commit_before># -*- coding: utf-8 -*-
import datetime as dt_module
import re
from collections import namedtuple
from datetime import date, datetime
from numpy import (array, concatenate, cos, float_, interp, isnan, nan,
                   ndarray, pi, rollaxis, searchsorted, sin, where)
from time import strftime, struct_time
from .constants import ASEC2RAD, B1950, DAY_S, T0, tau
from .descriptorlib import reify
from .earthlib import sidereal_time, earth_rotation_angle
from .framelib import ICRS_to_J2000 as B
from .functions import (mxm, mxmxm, load_bundled_npy, rot_z,
                        _to_array, _reconcile)
from .nutationlib import (
    build_nutation_matrix, equation_of_the_equinoxes_complimentary_terms,
    iau2000a_radians, mean_obliquity,
)
from .precessionlib import compute_precession

CalendarTuple = namedtuple('CalendarTuple', 'year month day hour minute second')

class CalendarArray(ndarray):
    @property
    def year(self): return self[0]
    @property
    def month(self): return self[1]
    @property
    def day(self): return self[2]
    @property
    def hour(self): return self[3]
    @property
    def minute(self): return self[4]
    @property
    def second(self): return self[5]

if hasattr(dt_module, 'timezone'):
    utc = dt_module.timezone.utc
else:
    class UTC(dt_module.tzinfo):
        'UTC'
        zero = dt_module.timedelta(0)
        def utcoffset(self, dt):
            return self.zero
        def tzname(self, dt):
            return 'UTC'
        def dst(self, dt):
            return self.zero

    utc = UTC()

# Much of the following code is adapted from the USNO's "novas.c".

_time_zero = dt_module.time(tzinfo=utc)
_half_minute = 30.0 / DAY_S
_half_second = 0.5 / DAY_S
_half_microsecond = 0.5e-6 / DAY_S
_months = array(['Month zero', 'Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun',
                 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'])

tt_minus_tai = array(32.184 / DAY_S)

class Timescale(object):
    """The data necessary to express dates in different timescales.

    A `Timescale` loads three data files.  They supply the value of ∆T
    over time and the schedule of UTC leap seconds, which Skyfield uses
    to translate between different time scales.  Most programs create a
    single `Timescale` which they use to build their `Time` objects:

    >>> from skyfield.api import load
    >>> ts = load.timescale()
    >>> t = ts.utc(1980, 3, 1, 9, 30)
    >>> t
    <Time tt=2444299.896425741>

    See :ref:`downloading-timescale-files` if you are interested in
    checking how recent the data is in the files loaded by the
    timescale.

    """
    _utcnow = datetime.utcnow

    def __init__(self, delta_t_recent, leap_dates, leap_offsets):
        self.delta_t_table = build_delta_t_table(delta_t_recent)
        self.leap_dates, self.leap_offsets = leap_dates, leap_offsets
        self._leap_reverse_dates = leap_dates + leap_offsets / DAY_S
        self.J2000 = Time(self, float_(T0))
        self.B1950 = Time(self, float_(B1950))
        #self.julian_calendar_cutoff = None

    def now(self):
        """Return the current date and time as a `Time` object.

        For the return value to be correct, your operating system time
        and timezone settings must be set so that the Python Standard
        Library constructor ``datetime.datetime.utcnow()`` returns a
        correct UTC date and time.

        """
        return self.from_datetime(self._utcnow().replace(tzinfo=utc))

    def from_datetime(self, datetime):
        """Return a `Time` for a Python ``datetime``.

        The ``datetime`` must be “timezone-aware”: it must have a time
        zone object as its ``tzinfo`` attribute instead of ``None``.

        """
        return self._utc(_datetime_to_utc_tuple(datetime))

    def from_datetimes(self, datetime_list):
        """Return a `Time` for a Python ``datetime`` list.

        The ``datetime`` objects must each be “timezone-aware”: they
        must each have a time zone object as their ``tzinfo`` attribute
        instead of ``None``.

        """
        tuples = (_datetime_to_utc_tuple(d) for d in datetime_list)
        return self._utc(array(value) for value in zip(*tuples))

    def utc(self, year, month=1, day=1, hour=0, minute=0, second=0.0):
        """Build a `Time` from a UTC calendar date.

        Specify the date as a numeric year, month, day, hour, minute,
        and second.  Any argument may be an array in which case the
        return value is a ``Time`` representing a whole array of times.

        """
        # TODO: someday deprecate passing datetime objects here, as
        # there are now separate constructors for them.
        if isinstance(year, datetime):
            return self.from_datetime(year)
        if isinstance(year, date):
            return self.from_datetime(datetime.combine(year, _time_zero))
        if hasattr(year, '__len__') and isinstance(year[0], datetime):
            return self.from_datetimes(year)

        a = _to_array
        tup = a(year), a(month), a(day), a(hour), a(minute), a(second)
        return self._utc(tup)

    def _utc(self, tup):
        year, month, day, hour, minute, second = tup
        j = julian_day(year, month, day) - 0.5
        i = searchsorted(self.leap_dates, j, 'right')
        seconds = self.leap_offsets[i] + second + minute * 60.0 + hour * 3600.0
        j, seconds = _reconcile(j, seconds)
        fraction = seconds / DAY_S
        t = Time(self, j, fraction + tt_minus_tai)
        t.tai_fraction = fraction
        return t

    def _cal(self, year, month, day, hour, minute, second):
        a = _to_array
        whole = julian_day(a(year), a(month), a(day)) - 0.5
        fraction = (a(second) + a(minute) * 60.0 + a(hour) * 3600.0) / DAY_S
        return _reconcile(whole, fraction)

    def tai(self, year=None, month=1, day=1, hour=0, minute=0, second=0.0,
            jd=None):
        """Build a `Time` from a TAI proleptic Gregorian date.

        Supply the International Atomic Time (TAI) as a proleptic
        Gregorian calendar date:

        >>> t = ts.tai(2014, 1, 18, 1, 35, 37.5)
        >>> t.tai
        2456675.56640625
        >>> t.tai_calendar()
        (2014, 1, 18, 1, 35, 37.5)

        """
        if jd is not None:
            return self.tai_jd(jd)  # deprecate someday
        whole, fraction = self._cal(year, month, day, hour, minute, second)
        t = Time(self, whole, fraction + tt_minus_tai)
        t.tai_fraction = fraction
        return t

    def tai_jd(self, jd, fraction=0.0):
        """Build a `Time` from a TAI Julian date."""
        whole, fraction2 = divmod(_to_array(jd), 1.0)
        fraction2 += fraction
        t = Time(self, whole, fraction2 + tt_minus_tai)
        t.tai_fraction = fraction2
        return t

    def tt(self, year=None, month=1, day=1, hour=0, minute=0, second=0.0,
           jd=None):
        """Build a `Time` from a TT calendar date.

        Supply the Terrestrial Time (TT) as a proleptic Gregorian
        calendar date:

        >>> t = ts.tt(2014, 1, 18, 1, 35, 37.5)
        >>> t.tt
        2456675.56640625
        >>> t.tt_calendar()
        (2014, 1, 18, 1, 35, 37.5)

        """
        if jd is not None:
            return self.tt_jd(jd)  # deprecate someday
        whole, fraction = self._cal(year, month, day, hour, minute, second)
        return Time(self, whole, fraction)

    def tt_jd(self, jd, fraction=0.0):
        """Build a `Time` from a TT Julian date."""
        whole, fraction2 = divmod(_to_array(jd), 1.0)
        fraction2 += fraction
        return Time(self, whole, fraction2)

    def J(self, year):
        """Build a `Time` from a TT Julian year or array of years.

        Julian years are convenient uniform periods of exactly 365.25
        days of Terrestrial Time, centered on 2000 January 1 12h TT =
        Julian year 2000.0.

        """
        tt = _to_array(year) * 365.25 + 1721045.0
        return Time(self, tt, 0.0)

    def tdb(self, year=None, month=1, day=1, hour=0, minute=0, second=0.0,
            jd=None):
        """Build a `Time` from a TDB calendar date.

        Supply the Barycentric Dynamical Time (TDB) as a proleptic
        Gregorian calendar date:

        >>> t = ts.tdb(2014, 1, 18, 1, 35, 37.5)
        >>> t.tdb
        2456675.56640625

        """
        if jd is not None:
            return self.tdb_jd(jd)  # deprecate someday
        whole, fraction = self._cal(year, month, day, hour, minute, second)
        t = Time(self, whole, fraction - tdb_minus_tt(whole + fraction) / DAY_S)
        t.tdb_fraction = fraction
        return t

    def tdb_jd(self, jd, fraction=0.0):
        """Build `Time` from a Barycentric Dynamical Time (TDB) Julian date."""
        whole, fraction2 = divmod(jd, 1.0)
        fraction2 += fraction
        t = Time(self, whole, fraction2 - tdb_minus_tt(jd, fraction) / DAY_S)
        t.tdb_fraction = fraction2
        return t

    def ut1(self, year=None, month=1, day=1, hour=0, minute=0, second=0.0,
            jd=None):
        """Build a `Time` from a UT1 calendar date.
<commit_msg>Return to old way of building TDB, to fix a test<commit_after># -*- coding: utf-8 -*-
import datetime as dt_module
import re
from collections import namedtuple
from datetime import date, datetime
from numpy import (array, concatenate, cos, float_, interp, isnan, nan,
                   ndarray, pi, rollaxis, searchsorted, sin, where)
from time import strftime, struct_time
from .constants import ASEC2RAD, B1950, DAY_S, T0, tau
from .descriptorlib import reify
from .earthlib import sidereal_time, earth_rotation_angle
from .framelib import ICRS_to_J2000 as B
from .functions import (mxm, mxmxm, load_bundled_npy, rot_z,
                        _to_array, _reconcile)
from .nutationlib import (
    build_nutation_matrix, equation_of_the_equinoxes_complimentary_terms,
    iau2000a_radians, mean_obliquity,
)
from .precessionlib import compute_precession

CalendarTuple = namedtuple('CalendarTuple', 'year month day hour minute second')

class CalendarArray(ndarray):
    @property
    def year(self): return self[0]
    @property
    def month(self): return self[1]
    @property
    def day(self): return self[2]
    @property
    def hour(self): return self[3]
    @property
    def minute(self): return self[4]
    @property
    def second(self): return self[5]

if hasattr(dt_module, 'timezone'):
    utc = dt_module.timezone.utc
else:
    class UTC(dt_module.tzinfo):
        'UTC'
        zero = dt_module.timedelta(0)
        def utcoffset(self, dt):
            return self.zero
        def tzname(self, dt):
            return 'UTC'
        def dst(self, dt):
            return self.zero

    utc = UTC()

# Much of the following code is adapted from the USNO's "novas.c".

_time_zero = dt_module.time(tzinfo=utc)
_half_minute = 30.0 / DAY_S
_half_second = 0.5 / DAY_S
_half_microsecond = 0.5e-6 / DAY_S
_months = array(['Month zero', 'Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun',
                 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'])

tt_minus_tai = array(32.184 / DAY_S)

class Timescale(object):
    """The data necessary to express dates in different timescales.

    A `Timescale` loads three data files.  They supply the value of ∆T
    over time and the schedule of UTC leap seconds, which Skyfield uses
    to translate between different time scales.  Most programs create a
    single `Timescale` which they use to build their `Time` objects:

    >>> from skyfield.api import load
    >>> ts = load.timescale()
    >>> t = ts.utc(1980, 3, 1, 9, 30)
    >>> t
    <Time tt=2444299.896425741>

    See :ref:`downloading-timescale-files` if you are interested in
    checking how recent the data is in the files loaded by the
    timescale.

    """
    _utcnow = datetime.utcnow

    def __init__(self, delta_t_recent, leap_dates, leap_offsets):
        self.delta_t_table = build_delta_t_table(delta_t_recent)
        self.leap_dates, self.leap_offsets = leap_dates, leap_offsets
        self._leap_reverse_dates = leap_dates + leap_offsets / DAY_S
        self.J2000 = Time(self, float_(T0))
        self.B1950 = Time(self, float_(B1950))
        #self.julian_calendar_cutoff = None

    def now(self):
        """Return the current date and time as a `Time` object.

        For the return value to be correct, your operating system time
        and timezone settings must be set so that the Python Standard
        Library constructor ``datetime.datetime.utcnow()`` returns a
        correct UTC date and time.

        """
        return self.from_datetime(self._utcnow().replace(tzinfo=utc))

    def from_datetime(self, datetime):
        """Return a `Time` for a Python ``datetime``.

        The ``datetime`` must be “timezone-aware”: it must have a time
        zone object as its ``tzinfo`` attribute instead of ``None``.

        """
        return self._utc(_datetime_to_utc_tuple(datetime))

    def from_datetimes(self, datetime_list):
        """Return a `Time` for a Python ``datetime`` list.

        The ``datetime`` objects must each be “timezone-aware”: they
        must each have a time zone object as their ``tzinfo`` attribute
        instead of ``None``.

        """
        tuples = (_datetime_to_utc_tuple(d) for d in datetime_list)
        return self._utc(array(value) for value in zip(*tuples))

    def utc(self, year, month=1, day=1, hour=0, minute=0, second=0.0):
        """Build a `Time` from a UTC calendar date.

        Specify the date as a numeric year, month, day, hour, minute,
        and second.  Any argument may be an array in which case the
        return value is a ``Time`` representing a whole array of times.

        """
        # TODO: someday deprecate passing datetime objects here, as
        # there are now separate constructors for them.
        if isinstance(year, datetime):
            return self.from_datetime(year)
        if isinstance(year, date):
            return self.from_datetime(datetime.combine(year, _time_zero))
        if hasattr(year, '__len__') and isinstance(year[0], datetime):
            return self.from_datetimes(year)

        a = _to_array
        tup = a(year), a(month), a(day), a(hour), a(minute), a(second)
        return self._utc(tup)

    def _utc(self, tup):
        year, month, day, hour, minute, second = tup
        j = julian_day(year, month, day) - 0.5
        i = searchsorted(self.leap_dates, j, 'right')
        seconds = self.leap_offsets[i] + second + minute * 60.0 + hour * 3600.0
        j, seconds = _reconcile(j, seconds)
        fraction = seconds / DAY_S
        t = Time(self, j, fraction + tt_minus_tai)
        t.tai_fraction = fraction
        return t

    def _cal(self, year, month, day, hour, minute, second):
        a = _to_array
        whole = julian_day(a(year), a(month), a(day)) - 0.5
        fraction = (a(second) + a(minute) * 60.0 + a(hour) * 3600.0) / DAY_S
        return _reconcile(whole, fraction)

    def tai(self, year=None, month=1, day=1, hour=0, minute=0, second=0.0,
            jd=None):
        """Build a `Time` from a TAI proleptic Gregorian date.

        Supply the International Atomic Time (TAI) as a proleptic
        Gregorian calendar date:

        >>> t = ts.tai(2014, 1, 18, 1, 35, 37.5)
        >>> t.tai
        2456675.56640625
        >>> t.tai_calendar()
        (2014, 1, 18, 1, 35, 37.5)

        """
        if jd is not None:
            return self.tai_jd(jd)  # deprecate someday
        whole, fraction = self._cal(year, month, day, hour, minute, second)
        t = Time(self, whole, fraction + tt_minus_tai)
        t.tai_fraction = fraction
        return t

    def tai_jd(self, jd, fraction=0.0):
        """Build a `Time` from a TAI Julian date."""
        whole, fraction2 = divmod(_to_array(jd), 1.0)
        fraction2 += fraction
        t = Time(self, whole, fraction2 + tt_minus_tai)
        t.tai_fraction = fraction2
        return t

    def tt(self, year=None, month=1, day=1, hour=0, minute=0, second=0.0,
           jd=None):
        """Build a `Time` from a TT calendar date.

        Supply the Terrestrial Time (TT) as a proleptic Gregorian
        calendar date:

        >>> t = ts.tt(2014, 1, 18, 1, 35, 37.5)
        >>> t.tt
        2456675.56640625
        >>> t.tt_calendar()
        (2014, 1, 18, 1, 35, 37.5)

        """
        if jd is not None:
            return self.tt_jd(jd)  # deprecate someday
        whole, fraction = self._cal(year, month, day, hour, minute, second)
        return Time(self, whole, fraction)

    def tt_jd(self, jd, fraction=0.0):
        """Build a `Time` from a TT Julian date."""
        whole, fraction2 = divmod(_to_array(jd), 1.0)
        fraction2 += fraction
        return Time(self, whole, fraction2)

    def J(self, year):
        """Build a `Time` from a TT Julian year or array of years.

        Julian years are convenient uniform periods of exactly 365.25
        days of Terrestrial Time, centered on 2000 January 1 12h TT =
        Julian year 2000.0.

        """
        tt = _to_array(year) * 365.25 + 1721045.0
        return Time(self, tt, 0.0)

    def tdb(self, year=None, month=1, day=1, hour=0, minute=0, second=0.0,
            jd=None):
        """Build a `Time` from a TDB calendar date.

        Supply the Barycentric Dynamical Time (TDB) as a proleptic
        Gregorian calendar date:

        >>> t = ts.tdb(2014, 1, 18, 1, 35, 37.5)
        >>> t.tdb
        2456675.56640625

        """
        if jd is not None:
            return self.tdb_jd(jd)  # deprecate someday
        whole, fraction = self._cal(year, month, day, hour, minute, second)
        jd = whole + fraction  # TODO: why do tests break if we pass separately
        return Time(self, jd, - tdb_minus_tt(jd) / DAY_S)

    def tdb_jd(self, jd, fraction=0.0):
        """Build `Time` from a Barycentric Dynamical Time (TDB) Julian date."""
        whole, fraction2 = divmod(jd, 1.0)
        fraction2 += fraction
        t = Time(self, whole, fraction2 - tdb_minus_tt(jd, fraction) / DAY_S)
        t.tdb_fraction = fraction2
        return t

    def ut1(self, year=None, month=1, day=1, hour=0, minute=0, second=0.0,
            jd=None):
        """Build a `Time` from a UT1 calendar date.

{'fraction_non_alphanumeric': 0.11012540386616286, 'fraction_numerical': 0.03187120091999343, 'mean_word_length': 2.518011943748796, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 77, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 2, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3994908', 'n_tokens_mistral': 6352, 'n_tokens_neox': 5784, 'n_words': 1886}