This blog post was written in a Jupyter notebook. Click here for an interactive version: Binder badge

Transition from datetime to astropy.time#

The SunPy project is very happy to announce that the time handling in SunPy will be transitioned from python datetime module to astropy.time module. The changes for this transition are under review in the pull request #2691. These changes are scheduled for SunPy 1.0.

This comes with numerous benefits:

Support for non-UTC time scales

UTC as well as non-UTC time scales like TAI, TT, UT1 etc. can be used with astropy.time.Time.

[1]:
from astropy.time import Time

t = Time("2012-06-18T02:00:05.453", scale="tai")
t
[1]:
<Time object: scale='tai' format='isot' value=2012-06-18T02:00:05.453>

~astropy.time.Time also provides easy conversion between different scales.

[2]:
t.utc
[2]:
<Time object: scale='utc' format='isot' value=2012-06-18T01:59:31.453>

Support for high precision times.

~astropy.time.Time can provide sub-nanosecond precision for time objects while python datetime was restricted to microseconds.

[3]:
t.precision = 9
t
[3]:
<Time object: scale='tai' format='isot' value=2012-06-18T02:00:05.453000000>

Support for leap seconds

This was one of the bigger motivation for the transition to astropy.time.Time. datetime has no support for leap second while ~astropy.time.Time supports leap seconds. A leap second is a one-second adjustment applied to UTC to keep it close to the mean solar time.

[4]:
import astropy.units as u

Time("2016-12-31T23:59:60"), Time("2016-12-31T23:59:59") + 1 * u.s
[4]:
(<Time object: scale='utc' format='isot' value=2016-12-31T23:59:60.000>,
 <Time object: scale='utc' format='isot' value=2016-12-31T23:59:60.000>)

Support for numerous formats

~astropy.time.Time can parse numerous formats including python datetime.

[5]:
Time.FORMATS
[5]:
OrderedDict([('jd', astropy.time.formats.TimeJD),
             ('mjd', astropy.time.formats.TimeMJD),
             ('decimalyear', astropy.time.formats.TimeDecimalYear),
             ('unix', astropy.time.formats.TimeUnix),
             ('cxcsec', astropy.time.formats.TimeCxcSec),
             ('gps', astropy.time.formats.TimeGPS),
             ('plot_date', astropy.time.formats.TimePlotDate),
             ('datetime', astropy.time.formats.TimeDatetime),
             ('iso', astropy.time.formats.TimeISO),
             ('isot', astropy.time.formats.TimeISOT),
             ('yday', astropy.time.formats.TimeYearDayTime),
             ('datetime64', astropy.time.formats.TimeDatetime64),
             ('fits', astropy.time.formats.TimeFITS),
             ('byear', astropy.time.formats.TimeBesselianEpoch),
             ('jyear', astropy.time.formats.TimeJulianEpoch),
             ('byear_str', astropy.time.formats.TimeBesselianEpochString),
             ('jyear_str', astropy.time.formats.TimeJulianEpochString)])
[6]:
import datetime

Time(datetime.datetime.now(tz=datetime.timezone.utc))
[6]:
<Time object: scale='utc' format='datetime' value=2019-03-20 19:19:05.112429>

Changes to SunPy#

  • All functions which used to return datetime now return ~astropy.time.Time

    • All functions which return datetime.timedelta now return astropy.time.TimeDelta. For example, the properties of sunpy.time.TimeRange which used to return datetime.datetime and datetime.timedelta now return astropy.time.Time and astropy.time.TimeDelta.

  • Changes to sunpy.time.parse_time

    • ~sunpy.time.parse_time has been reduced to a tiny wrapper over~astropy.time.Time. The API of ~sunpy.time.parse_time is mostly similar to that of ~astropy.time.Time. ~sunpy.time.parse_time supports parsing a few more formats than ~astropy.time.Time, which are numpy.datetime64, pandas.Series, pandas.DatetimeIndex, “UTime” and a few other time formats.

The work on the transition from datetime to astropy.time.Time was done as a part of Vishnunarayan’s Google Summer of Code 2018 project. To see more about the project: