# Path: skyfield/constants.py
# AU_KM = 149597870.700
# 
# DAY_S = 86400.0
# 
# Path: skyfield/errors.py
# class EphemerisRangeError(ValueError):
#     """An ephemeris has been asked about positions outside its time range.
# 
#     Attributes:
# 
#     - `start_time`, `end_time`: the range of times supported by the segment
#     - `time_mask`: Boolean array where ``True`` marks out-of-range times
#     - `segment`: the ephemeris segment that was asked for positions
# 
#     """
#     def __init__(self, message, start_time, end_time, time_mask, segment):
#         self.args = message,
#         self.start_time = start_time
#         self.end_time = end_time
#         self.time_mask = time_mask
#         self.segment = segment
# 
# Path: skyfield/timelib.py
# def compute_calendar_date(jd_integer, julian_before=None):
#     """Convert Julian day ``jd_integer`` into a calendar (year, month, day).
# 
#     Uses the proleptic Gregorian calendar unless ``julian_before`` is
#     set to a specific Julian day, in which case the Julian calendar is
#     used for dates older than that.
# 
#     """
#     use_gregorian = (julian_before is None) or (jd_integer >= julian_before)
# 
#     # See the Explanatory Supplement to the Astronomical Almanac 15.11.
#     f = jd_integer + 1401
#     f += use_gregorian * ((4 * jd_integer + 274277) // 146097 * 3 // 4 - 38)
#     e = 4 * f + 3
#     g = e % 1461 // 4
#     h = 5 * g + 2
#     day = h % 153 // 5 + 1
#     month = (h // 153 + 2) % 12 + 1
#     year = e // 1461 - 4716 + (12 + 2 - month) // 12
#     return year, month, day
# 
# Path: skyfield/vectorlib.py
# class VectorFunction(object):
# class ReversedVector(VectorFunction):
# class VectorSum(VectorFunction):
#     def vector_name(self):
#     def center_name(self):
#     def target_name(self):
#     def __repr__(self):
#     def __str__(self):
#     def arrow_str(self):
#     def __add__(self, other):
#     def __neg__(self):
#     def __sub__(self, other):
#     def at(self, t):
#     def _observe_from_bcrs(self, observer):
#     def geometry_of(self, other):
#     def topos(self, latitude=None, longitude=None, latitude_degrees=None,
#               longitude_degrees=None, elevation_m=0.0, x=0.0, y=0.0):
#     def satellite(self, text):
#     def __init__(self, vector_function):
#     def vector_name(self):
#     def center_name(self):
#     def target_name(self):
#     def __neg__(self):
#     def _at(self, t):
#     def __init__(self, center, target, vector_functions):
#     def __str__(self):
#     def __repr__(self):
#     def _at(self, t):
# def _correct_for_light_travel_time(observer, target):
# def _jpl_name(target):


import os
from collections import defaultdict
from jplephem.exceptions import OutOfRangeError
from jplephem.spk import SPK
from jplephem.names import target_name_pairs
from .constants import AU_KM, DAY_S
from .errors import EphemerisRangeError
from .timelib import compute_calendar_date
from .vectorlib import VectorFunction, VectorSum, _jpl_code_name_dict
        return '{0!r} segment'.format(self.ephemeris.path)

    def time_range(self, ts):
        s = self.spk_segment
        return ts.tdb_jd(s.start_jd), ts.tdb_jd(s.end_jd)

class ChebyshevPosition(SPICESegment):
    def _at(self, t):
        segment = self.spk_segment
        try:
            position, velocity = segment.compute_and_differentiate(
                t.whole, t.tdb_fraction)
        except OutOfRangeError as e:
            start_time = t.ts.tdb(jd=segment.start_jd)
            end_time = t.ts.tdb(jd=segment.end_jd)
            # TODO: switch to calendar dates in TDB to produce round numbers?
            text = ('ephemeris segment only covers dates %s through %s UT'
                    % (start_time.utc_iso(' '), end_time.utc_iso(' ')))
            mask = e.out_of_range_times
            segment = self.spk_segment
            e = EphemerisRangeError(text, start_time, end_time, mask, segment)
            e.__cause__ = None  # avoid exception chaining in Python 3
            raise e

        return position / AU_KM, velocity / AU_KM, None, None


class ChebyshevPositionVelocity(SPICESegment):
    def _at(self, t):
        pv = self.spk_segment.compute(t.whole, t.tdb_fraction)

# Path: skyfield/constants.py
# AU_KM = 149597870.700
# 
# DAY_S = 86400.0
# 
# Path: skyfield/errors.py
# class EphemerisRangeError(ValueError):
#     """An ephemeris has been asked about positions outside its time range.
# 
#     Attributes:
# 
#     - `start_time`, `end_time`: the range of times supported by the segment
#     - `time_mask`: Boolean array where ``True`` marks out-of-range times
#     - `segment`: the ephemeris segment that was asked for positions
# 
#     """
#     def __init__(self, message, start_time, end_time, time_mask, segment):
#         self.args = message,
#         self.start_time = start_time
#         self.end_time = end_time
#         self.time_mask = time_mask
#         self.segment = segment
# 
# Path: skyfield/timelib.py
# def compute_calendar_date(jd_integer, julian_before=None):
#     """Convert Julian day ``jd_integer`` into a calendar (year, month, day).
# 
#     Uses the proleptic Gregorian calendar unless ``julian_before`` is
#     set to a specific Julian day, in which case the Julian calendar is
#     used for dates older than that.
# 
#     """
#     use_gregorian = (julian_before is None) or (jd_integer >= julian_before)
# 
#     # See the Explanatory Supplement to the Astronomical Almanac 15.11.
#     f = jd_integer + 1401
#     f += use_gregorian * ((4 * jd_integer + 274277) // 146097 * 3 // 4 - 38)
#     e = 4 * f + 3
#     g = e % 1461 // 4
#     h = 5 * g + 2
#     day = h % 153 // 5 + 1
#     month = (h // 153 + 2) % 12 + 1
#     year = e // 1461 - 4716 + (12 + 2 - month) // 12
#     return year, month, day
# 
# Path: skyfield/vectorlib.py
# class VectorFunction(object):
# class ReversedVector(VectorFunction):
# class VectorSum(VectorFunction):
#     def vector_name(self):
#     def center_name(self):
#     def target_name(self):
#     def __repr__(self):
#     def __str__(self):
#     def arrow_str(self):
#     def __add__(self, other):
#     def __neg__(self):
#     def __sub__(self, other):
#     def at(self, t):
#     def _observe_from_bcrs(self, observer):
#     def geometry_of(self, other):
#     def topos(self, latitude=None, longitude=None, latitude_degrees=None,
#               longitude_degrees=None, elevation_m=0.0, x=0.0, y=0.0):
#     def satellite(self, text):
#     def __init__(self, vector_function):
#     def vector_name(self):
#     def center_name(self):
#     def target_name(self):
#     def __neg__(self):
#     def _at(self, t):
#     def __init__(self, center, target, vector_functions):
#     def __str__(self):
#     def __repr__(self):
#     def _at(self, t):
# def _correct_for_light_travel_time(observer, target):
# def _jpl_name(target):


# Path: skyfield/jpllib.py
import os
from collections import defaultdict
from jplephem.exceptions import OutOfRangeError
from jplephem.spk import SPK
from jplephem.names import target_name_pairs
from .constants import AU_KM, DAY_S
from .errors import EphemerisRangeError
from .timelib import compute_calendar_date
from .vectorlib import VectorFunction, VectorSum, _jpl_code_name_dict

        return '{0!r} segment'.format(self.ephemeris.path)

    def time_range(self, ts):
        s = self.spk_segment
        return ts.tdb_jd(s.start_jd), ts.tdb_jd(s.end_jd)

class ChebyshevPosition(SPICESegment):
    def _at(self, t):
        segment = self.spk_segment
        try:
            position, velocity = segment.compute_and_differentiate(
                t.whole, t.tdb_fraction)
        except OutOfRangeError as e:
            start_time = t.ts.tdb(jd=segment.start_jd)
            end_time = t.ts.tdb(jd=segment.end_jd)
            # TODO: switch to calendar dates in TDB to produce round numbers?
            text = ('ephemeris segment only covers dates %s through %s UT'
                    % (start_time.utc_iso(' '), end_time.utc_iso(' ')))
            mask = e.out_of_range_times
            segment = self.spk_segment
            e = EphemerisRangeError(text, start_time, end_time, mask, segment)
            e.__cause__ = None  # avoid exception chaining in Python 3
            raise e

        return position / AU_KM, velocity / AU_KM, None, None


class ChebyshevPositionVelocity(SPICESegment):
    def _at(self, t):
        pv = self.spk_segment.compute(t.whole, t.tdb_fraction)

        return pv[:3] / AU_KM, pv[3:] * DAY_S / AU_KM, None, None