# Fix astropy Time scale, format, and leap-second mistakes

Troubleshoot astropy.time by checking scale and format first: default UTC scale vs intrinsic epoch-format scales (unix/gps/cxcsec), TimeDelta's missing 'utc' scale (differences come back TAI), leap-second handling in to_datetime() via leap_second_strict, jd1/jd2 precision vs single-float .jd, and format inference failures.

Exact reference: {"kind":"skill_version","skill_id":"skl_IWER2iiBANUm3j-GxGO3oQ","version_id":"skv_cDlaQq7uhQirrWsqonaQ3A"}

Applicability: [{"constraint":">=4.0","technology":"astropy","version_scheme":"semver"}]

# Fix astropy Time scale, format, and leap-second mistakes

Use this when a `Time` object holds the wrong instant, construction raises
`ValueError`, `to_datetime()` explodes, or UTC-vs-TAI arithmetic gives
answers off by tens of seconds. Most `Time` bugs come from the scale being
wrong, and the scale is usually wrong because it was never stated.

## 1. Print scale and format before anything else

```python
from astropy.time import Time

t = Time('2026-09-17 12:00:00')
print(t.scale, t.format)   # utc iso
```

Two defaults cause most of the trouble:

- **Default scale is UTC** — except for the epoch formats, which carry an
  intrinsic scale: `unix` → UTC (ref 1970-01-01), `unix_tai` → TAI,
  `gps` → TAI (ref 1980-01-06 00:00:19), `cxcsec` → TT (ref 1998-01-01).
  The same number fed as `format='unix'` vs `format='unix_tai'` names two
  different instants.
- **Format is guessed from the string** — `Time('2010-01-02 01:02:03')`
  becomes `iso`; unambiguous inputs are fine, but if the guess is wrong you
  get a `ValueError` listing the candidate formats. Then pass `format=`
  explicitly (and `in_subfmt`/`out_subfmt` wildcards for format variants).

If the instant looks wrong, check whether you fed TAI/GPS/TT numbers into a
UTC-default constructor — that is the bug nine times out of ten.

## 2. Convert scales with attribute access; state the scale at construction

```python
t = Time('2026-09-17 12:00:00', scale='utc')
t.tai   # new Time object, same instant, TAI scale
t.tt    # Terrestrial Time
t.tdb   # Barycentric Dynamical Time
```

Attribute access (`.utc`, `.tai`, `.tt`, `.tdb`, `.ut1`, ...) converts and
returns a *new* object; the original is unchanged. For sidereal time:

```python
t.sidereal_time('apparent', 'greenwich')   # Longitude in hourangle
```

`kind` is `'mean'` or `'apparent'`; the longitude can be a string like
`'greenwich'`, an `EarthLocation`, or a longitude. Apparent sidereal time
goes through UT1, so it needs the IERS Earth-rotation table — auto-downloaded
on first use, with bundled data as the offline fallback.

## 3. TimeDelta has no 'utc' scale — that is the fix, not the bug

Subtracting two UTC times does not give a UTC delta:

```python
dt = t2 - t1
print(dt.scale)   # 'tai' -- a UTC day is not always 86400 s, so deltas cannot be UTC
```

Valid `TimeDelta` scales are the geocentric (`tai`, `tt`, `tcg`),
barycentric (`tcb`, `tdb`), rotational (`ut1`), and `local` scales —
`'utc'` raises `ScaleValueError`. If you need uniform SI-second intervals
(durations, rates, ephemeris math), do the arithmetic in TAI:

```python
from astropy.time import TimeDelta

dt = TimeDelta(3600.0, format='sec', scale='tai')
t2 = t.tai + dt          # Time + TimeDelta: scales are reconciled automatically
```

`Time + TimeDelta` works across compatible scales (a TAI delta added to a
UTC time is fine), and plain quantities work too:
`Time("2020-01-01") + 5 * u.day`.

## 4. Leap seconds: representable in Time, not in datetime

astropy can hold the leap second itself —
`Time('2016-12-31 23:59:60', scale='utc')` is valid — but Python `datetime`
cannot. Converting out needs a policy:

```python
t.to_datetime()                            # raises on times inside a leap second
t.to_datetime(leap_second_strict='warn')    # 'raise', 'warn', or 'silent'
```

The leap-second table also goes stale: astropy refreshes IERS data
automatically (`from astropy.time import update_leap_seconds` forces it), so
a machine that has been offline can warn about expired leap-second data.
`Time.now()` gives the current instant from the system clock on the UTC
scale.

## 5. Precision: trust jd1/jd2, not .jd

Internally every `Time` is two float64s (`jd1`, `jd2`) holding
sub-nanosecond precision over the age of the universe. A single `.jd`
float64 keeps only ~microsecond precision over human timescales. When you
need the digits — file round-trips, ephemerides — use the high-precision
outputs:

```python
t.to_value('mjd', 'long')      # numpy.longdouble
t.to_value('mjd', 'decimal')   # decimal.Decimal, full precision
t.to_value('mjd', 'str')       # exact string round-trip
```

And on input, `val2` exists for the same reason:
`Time(100.0, 0.000001, format='mjd', scale='tt')` keeps both doubles.
String output precision is `t.precision` (integer 0–9, default 3).

## 6. Checklist

1. Print `t.scale` and `t.format`; confirm the scale is the one you meant.
2. Wrong instant → you probably fed TAI/GPS/TT numbers to a UTC-default
   constructor; state `scale=` explicitly.
3. `TimeDelta(..., scale='utc')` raises → use `'tai'`; differences of UTC
   times come back TAI by design.
4. `to_datetime()` fails → the time is inside a leap second; set
   `leap_second_strict='warn'` or `'silent'`.
5. Digits lost → read `jd1`/`jd2` or `to_value(..., 'decimal'/'str')`,
   never a single `.jd` float.
6. Format guess wrong → pass `format=` explicitly (plus
   `in_subfmt`/`out_subfmt` wildcards for variants).


## Supporting basis and limitations

Built from the astropy Time and Dates documentation (default scales, epoch-format intrinsic scales table, TimeDelta scale restrictions, leap seconds, jd1/jd2 internal representation, in_subfmt/out_subfmt) and the astropy.time API reference (SCALES, TIME_DELTA_SCALES, sidereal_time, to_datetime leap_second_strict).

## Change and rationale

New skill: fix astropy Time scale, format, and leap-second mistakes.

Time-scale mixups (feeding TAI numbers to a UTC-default constructor, assuming deltas can be UTC, datetime conversion inside leap seconds) are recurring astropy support questions with tens-of-seconds consequences. This skill makes 'print t.scale first' the diagnostic reflex and maps each symptom to the documented behavior.
