I favor a modified version of approach #2, and agree with Erik's
opinion that it allows for simpler code, simpler documentation (both
for users and developers), and better use of Python and better
potential for abstracting the problem so the Time class is more easily
extensible.
Here's my take on the situation.
Fundamentally there are three things needed for instantiating the
"normal" resolution time representations:
- One or more "values", which are the input time(s). This input could
be one of a number of Python types:
- Float, int, datetime object, string, list of any of the previous,
numpy array of any of the previous.
- A format (one might also call this the "representation" but stick
with "format" for now). This is required in cases where the input
values are ambiguous. For instance a float is always ambiguous but a
datetime is never ambiguous nor is a string that matches one of the
supported string formats (e.g. ISO). Examples for format include:
- JD, MJD, unix, ISO, datetime, Chandra_seconds, Chandra_FITS,
'YYYYDDD:HHMMSS.sss' etc.
- A "system", e.g. UTC, TT, TAI, TDB, TGB, TCB
(
http://tycho.usno.navy.mil/systime.html)
Handling of the different input types for "values" (e.g. array or not)
should be independent of the format and system. This makes it easier
to support more formats. In the latest Time implementation this
handling occurs twice (from_tai and from_jd) and would likely get
repeated more as the class develops. Of course this can be
refactored, but I think this would drive the code toward Erik's #2
anyway.
It should be very cheap to add support for a new format. Notice I
include Chandra_seconds as a format. This is a mission-specific
format, but as an astronomical utility there is no reason we cannot
support mission or observatory specific formats if it is cheap and
unambiguous.
Given the above, why not have one and exactly one way to make a time object:
t = Time(values, format=None, system=None)
t = Time(values, format='iso', system='tt')
This provides a single uniform interface and a single doc string that
needs to be memorized (users) and maintained (developers). The Time
class will have internal methods that convert from any format and
system into the internal representation. The Time class will raise an
exception if the input is ambiguous, for instance a float value is
provided with no value of format. But for formats that are
unambiguous it won't be required to specify the format.
Each time format will have a default "system" which is well
documented, but this can be overridden by the user.
To access different representations, provide two ways:
t.jd # short form which uses the default system for that format
t.get_jd(system=None) # long getter form that allows for a different system
If you are still reading, providing a single point interface like this
has a huge advantage in developing other parts of astropy that rely on
time. For any new method that needs a time you can *always* do:
def my_method(stuff, ..., time_values, time_format=None,
time_system=None, .. kwargs):
time_values = Time(time_values, time_format, time_system)
...
This means that for any astropy routine that needs a time there is
just one line of code to validate and convert anything the user
provides into a well-mannered Time object. And this provides a
uniform interface across all of astropy for how to do this. If Time
uses a blizzard of class methods then the above code gets a lot
uglier.
My 2c,
Tom