Skill Tracer
Skills › Scientific Agent Skills › astropy › time.md

time.md

429 lines · skills/astropy/references/time.md at 5f2bc03

Open on GitHub
1# Time Handling (astropy.time)
2
3The `astropy.time` module provides robust tools for manipulating times and dates with support for various time scales and formats.
4

Time Handling (astropy.time)

The astropy.time module provides robust tools for manipulating times and dates with support for various time scales and formats.

Raw lines 1 to 4
5## Creating Time Objects
6

Creating Time Objects

Raw lines 5 to 6
7### Basic Creation
8
9```python
10from astropy.time import Time
11import astropy.units as u
13# ISO format (automatically detected)
14t = Time('2023-01-15 12:30:45')
15t = Time('2023-01-15T12:30:45')
17# Specify format explicitly
18t = Time('2023-01-15 12:30:45', format='iso', scale='utc')
20# Julian Date
21t = Time(2460000.0, format='jd')
23# Modified Julian Date
24t = Time(59945.0, format='mjd')
26# Unix time (seconds since 1970-01-01)
27t = Time(1673785845.0, format='unix')
28```

Basic Creation

from astropy.time import Time
import astropy.units as u

# ISO format (automatically detected)
t = Time('2023-01-15 12:30:45')
t = Time('2023-01-15T12:30:45')

# Specify format explicitly
t = Time('2023-01-15 12:30:45', format='iso', scale='utc')

# Julian Date
t = Time(2460000.0, format='jd')

# Modified Julian Date
t = Time(59945.0, format='mjd')

# Unix time (seconds since 1970-01-01)
t = Time(1673785845.0, format='unix')
Raw lines 7 to 29
30### Array of Times
32```python
33# Multiple times
34times = Time(['2023-01-01', '2023-06-01', '2023-12-31'])
36# From arrays
37import numpy as np
38jd_array = np.linspace(2460000, 2460100, 100)
39times = Time(jd_array, format='jd')
40```

Array of Times

# Multiple times
times = Time(['2023-01-01', '2023-06-01', '2023-12-31'])

# From arrays
import numpy as np
jd_array = np.linspace(2460000, 2460100, 100)
times = Time(jd_array, format='jd')
Raw lines 30 to 41
42## Time Formats

Time Formats

Raw lines 42 to 43
44### Supported Formats
46```python
47# ISO 8601
48t = Time('2023-01-15 12:30:45', format='iso')
49t = Time('2023-01-15T12:30:45.123', format='isot')
51# Julian dates
52t = Time(2460000.0, format='jd') # Julian Date
53t = Time(59945.0, format='mjd') # Modified Julian Date
55# Decimal year
56t = Time(2023.5, format='decimalyear')
57t = Time(2023.5, format='jyear') # Julian year
58t = Time(2023.5, format='byear') # Besselian year
60# Year and day-of-year
61t = Time('2023:046', format='yday') # 46th day of 2023
63# FITS format
64t = Time('2023-01-15T12:30:45', format='fits')
66# GPS seconds
67t = Time(1000000000.0, format='gps')
69# Unix time
70t = Time(1673785845.0, format='unix')
72# Matplotlib dates
73t = Time(738521.0, format='plot_date')
75# datetime objects
76from datetime import datetime
77dt = datetime(2023, 1, 15, 12, 30, 45)
78t = Time(dt)
79```

Supported Formats

# ISO 8601
t = Time('2023-01-15 12:30:45', format='iso')
t = Time('2023-01-15T12:30:45.123', format='isot')

# Julian dates
t = Time(2460000.0, format='jd')          # Julian Date
t = Time(59945.0, format='mjd')           # Modified Julian Date

# Decimal year
t = Time(2023.5, format='decimalyear')
t = Time(2023.5, format='jyear')          # Julian year
t = Time(2023.5, format='byear')          # Besselian year

# Year and day-of-year
t = Time('2023:046', format='yday')       # 46th day of 2023

# FITS format
t = Time('2023-01-15T12:30:45', format='fits')

# GPS seconds
t = Time(1000000000.0, format='gps')

# Unix time
t = Time(1673785845.0, format='unix')

# Matplotlib dates
t = Time(738521.0, format='plot_date')

# datetime objects
from datetime import datetime
dt = datetime(2023, 1, 15, 12, 30, 45)
t = Time(dt)
Raw lines 44 to 80
81## Time Scales
83### Available Time Scales
85```python
86# UTC - Coordinated Universal Time (default)
87t = Time('2023-01-15 12:00:00', scale='utc')
89# TAI - International Atomic Time
90t = Time('2023-01-15 12:00:00', scale='tai')
92# TT - Terrestrial Time
93t = Time('2023-01-15 12:00:00', scale='tt')
95# TDB - Barycentric Dynamical Time
96t = Time('2023-01-15 12:00:00', scale='tdb')
98# TCG - Geocentric Coordinate Time
99t = Time('2023-01-15 12:00:00', scale='tcg')
101# TCB - Barycentric Coordinate Time
102t = Time('2023-01-15 12:00:00', scale='tcb')
104# UT1 - Universal Time
105t = Time('2023-01-15 12:00:00', scale='ut1')
106```

Available Time Scales

# UTC - Coordinated Universal Time (default)
t = Time('2023-01-15 12:00:00', scale='utc')

# TAI - International Atomic Time
t = Time('2023-01-15 12:00:00', scale='tai')

# TT - Terrestrial Time
t = Time('2023-01-15 12:00:00', scale='tt')

# TDB - Barycentric Dynamical Time
t = Time('2023-01-15 12:00:00', scale='tdb')

# TCG - Geocentric Coordinate Time
t = Time('2023-01-15 12:00:00', scale='tcg')

# TCB - Barycentric Coordinate Time
t = Time('2023-01-15 12:00:00', scale='tcb')

# UT1 - Universal Time
t = Time('2023-01-15 12:00:00', scale='ut1')
Raw lines 83 to 107
108### Converting Time Scales
110```python
111t = Time('2023-01-15 12:00:00', scale='utc')
113# Convert to different scales
114t_tai = t.tai
115t_tt = t.tt
116t_tdb = t.tdb
117t_ut1 = t.ut1
119# These are the same instant, so their elapsed-time difference is zero.
120print((t.tai - t.utc).sec) # 0.0
121print(t.utc.iso, t.tai.iso) # 12:00:00 UTC and 12:00:37 TAI on this date
123# UTC contains leap seconds: this wall-clock interval spans two SI seconds.
124before = Time("2016-12-31 23:59:59", scale="utc")
125after = Time("2017-01-01 00:00:00", scale="utc")
126print((after - before).to_value(u.s)) # approximately 2
127```

Converting Time Scales

t = Time('2023-01-15 12:00:00', scale='utc')

# Convert to different scales
t_tai = t.tai
t_tt = t.tt
t_tdb = t.tdb
t_ut1 = t.ut1

# These are the same instant, so their elapsed-time difference is zero.
print((t.tai - t.utc).sec)  # 0.0
print(t.utc.iso, t.tai.iso)  # 12:00:00 UTC and 12:00:37 TAI on this date

# UTC contains leap seconds: this wall-clock interval spans two SI seconds.
before = Time("2016-12-31 23:59:59", scale="utc")
after = Time("2017-01-01 00:00:00", scale="utc")
print((after - before).to_value(u.s))  # approximately 2
Raw lines 108 to 128
129## Format Conversions

Format Conversions

Raw lines 129 to 130
131### Change Output Format
133```python
134t = Time('2023-01-15 12:30:45')
136# Access in different formats
137print(t.jd) # Julian Date
138print(t.mjd) # Modified Julian Date
139print(t.iso) # ISO format
140print(t.isot) # ISO with 'T'
141print(t.unix) # Unix time
142print(t.decimalyear) # Decimal year
144# Change default format
145t.format = 'mjd'
146print(t) # Displays as MJD
147```

Change Output Format

t = Time('2023-01-15 12:30:45')

# Access in different formats
print(t.jd)           # Julian Date
print(t.mjd)          # Modified Julian Date
print(t.iso)          # ISO format
print(t.isot)         # ISO with 'T'
print(t.unix)         # Unix time
print(t.decimalyear)  # Decimal year

# Change default format
t.format = 'mjd'
print(t)  # Displays as MJD
Raw lines 131 to 148
149### High-Precision Output
151```python
152# Use subfmt for precision control
153t.to_value('mjd', subfmt='float') # Standard float
154t.to_value('mjd', subfmt='long') # Extended precision
155t.to_value('mjd', subfmt='decimal') # Decimal (highest precision)
156t.to_value('mjd', subfmt='str') # String representation
157```

High-Precision Output

# Use subfmt for precision control
t.to_value('mjd', subfmt='float')    # Standard float
t.to_value('mjd', subfmt='long')     # Extended precision
t.to_value('mjd', subfmt='decimal')  # Decimal (highest precision)
t.to_value('mjd', subfmt='str')      # String representation
Raw lines 149 to 158
159## Time Arithmetic

Time Arithmetic

Raw lines 159 to 160
161### TimeDelta Objects
163```python
164from astropy.time import TimeDelta
166# Create time difference
167dt = TimeDelta(1.0, format='jd') # 1 day
168dt = TimeDelta(3600.0, format='sec') # 1 hour
170# Subtract times
171t1 = Time('2023-01-15')
172t2 = Time('2023-02-15')
173dt = t2 - t1
174print(dt.jd) # 31 days
175print(dt.sec) # 2678400 seconds
176```

TimeDelta Objects

from astropy.time import TimeDelta

# Create time difference
dt = TimeDelta(1.0, format='jd')      # 1 day
dt = TimeDelta(3600.0, format='sec')  # 1 hour

# Subtract times
t1 = Time('2023-01-15')
t2 = Time('2023-02-15')
dt = t2 - t1
print(dt.jd)   # 31 days
print(dt.sec)  # 2678400 seconds
Raw lines 161 to 177
178### Adding/Subtracting Time
180```python
181t = Time('2023-01-15 12:00:00')
183# Add TimeDelta
184t_future = t + TimeDelta(7, format='jd') # Add 7 days
186# Add Quantity
187t_future = t + 1*u.hour
188t_future = t + 30*u.day
189t_future = t + 1*u.year
191# Subtract
192t_past = t - 1*u.week
193```
195A `u.day` is 86400 SI seconds and a `u.year` is a Julian year; neither
196guarantees a fixed local wall-clock hour across UTC leap seconds or DST.

Adding/Subtracting Time

t = Time('2023-01-15 12:00:00')

# Add TimeDelta
t_future = t + TimeDelta(7, format='jd')  # Add 7 days

# Add Quantity
t_future = t + 1*u.hour
t_future = t + 30*u.day
t_future = t + 1*u.year

# Subtract
t_past = t - 1*u.week

A u.day is 86400 SI seconds and a u.year is a Julian year; neither guarantees a fixed local wall-clock hour across UTC leap seconds or DST.

Raw lines 178 to 197
198### Time Ranges
200```python
201# Create range of times
202start = Time('2023-01-01', scale='utc')
203end = Time('2023-12-31', scale='utc')
204times = start + np.linspace(0, 1, 100) * (end - start)
205# This includes both endpoints; 365 days after Jan 1 would reach Jan 1, 2024.
206```

Time Ranges

# Create range of times
start = Time('2023-01-01', scale='utc')
end = Time('2023-12-31', scale='utc')
times = start + np.linspace(0, 1, 100) * (end - start)
# This includes both endpoints; 365 days after Jan 1 would reach Jan 1, 2024.
Raw lines 198 to 207
208## Observing-Related Features
210Some high-precision time and coordinate operations use IERS Earth-rotation data. Astropy uses `astropy-iers-data` by default, but may auto-download fresher IERS-A data when required for UT1 or polar-motion values. Disable auto-download for offline or privacy-sensitive runs:
212```python
213from astropy.utils import iers
215iers.conf.auto_download = False
216```

Observing-Related Features

Some high-precision time and coordinate operations use IERS Earth-rotation data. Astropy uses astropy-iers-data by default, but may auto-download fresher IERS-A data when required for UT1 or polar-motion values. Disable auto-download for offline or privacy-sensitive runs:

from astropy.utils import iers

iers.conf.auto_download = False
Raw lines 208 to 217
218### Sidereal Time
220```python
221from astropy.coordinates import EarthLocation
223# Define observer location
224location = EarthLocation(lat=40*u.deg, lon=-120*u.deg, height=1000*u.m)
226# Create time with location
227t = Time('2023-06-15 23:00:00', location=location)
229# Calculate sidereal time
230lst_apparent = t.sidereal_time('apparent')
231lst_mean = t.sidereal_time('mean')
233print(f"Local Sidereal Time: {lst_apparent}")
234```

Sidereal Time

from astropy.coordinates import EarthLocation

# Define observer location
location = EarthLocation(lat=40*u.deg, lon=-120*u.deg, height=1000*u.m)

# Create time with location
t = Time('2023-06-15 23:00:00', location=location)

# Calculate sidereal time
lst_apparent = t.sidereal_time('apparent')
lst_mean = t.sidereal_time('mean')

print(f"Local Sidereal Time: {lst_apparent}")
Raw lines 218 to 235
236### Light Travel Time Corrections
238```python
239from astropy.coordinates import SkyCoord, EarthLocation
241# Define target and observer
242target = SkyCoord(ra=10*u.deg, dec=20*u.deg)
243# Synthetic site for a self-contained example; use surveyed coordinates in research.
244location = EarthLocation(lat=40*u.deg, lon=-120*u.deg, height=1000*u.m)
246# Observation times
247times = Time(['2023-01-01', '2023-06-01', '2023-12-31'],
248 location=location, scale='utc')
250# Calculate light travel time to solar system barycenter
251ltt_bary = times.light_travel_time(target, kind='barycentric')
252ltt_helio = times.light_travel_time(target, kind='heliocentric')
254# Apply correction
255times_barycentric = times.tdb + ltt_bary
256```

Light Travel Time Corrections

from astropy.coordinates import SkyCoord, EarthLocation

# Define target and observer
target = SkyCoord(ra=10*u.deg, dec=20*u.deg)
# Synthetic site for a self-contained example; use surveyed coordinates in research.
location = EarthLocation(lat=40*u.deg, lon=-120*u.deg, height=1000*u.m)

# Observation times
times = Time(['2023-01-01', '2023-06-01', '2023-12-31'],
             location=location, scale='utc')

# Calculate light travel time to solar system barycenter
ltt_bary = times.light_travel_time(target, kind='barycentric')
ltt_helio = times.light_travel_time(target, kind='heliocentric')

# Apply correction
times_barycentric = times.tdb + ltt_bary
Raw lines 236 to 257
258### Earth Rotation Angle
260```python
261# Earth rotation angle (for celestial to terrestrial transformations)
262era = t.earth_rotation_angle()
263```
265For reproducible barycentric times, record the input scale, site, target frame/epoch
266and ephemeris (`builtin` is the default). BJD_TDB is a barycentric corrected time,
267not just `Time.utc` displayed as JD. External JPL ephemerides may require downloads.
268The RV helper returns an optical-convention correction; for precision optical RVs
269use `rv + correction + rv*correction/c` and document the convention.

Earth Rotation Angle

# Earth rotation angle (for celestial to terrestrial transformations)
era = t.earth_rotation_angle()

For reproducible barycentric times, record the input scale, site, target frame/epoch and ephemeris (builtin is the default). BJD_TDB is a barycentric corrected time, not just Time.utc displayed as JD. External JPL ephemerides may require downloads. The RV helper returns an optical-convention correction; for precision optical RVs use rv + correction + rv*correction/c and document the convention.

Raw lines 258 to 270
271## Handling Missing or Invalid Times

Handling Missing or Invalid Times

Raw lines 271 to 272
273### Masked Times
275```python
276import numpy as np
278# Create times with missing values
279times = Time(['2023-01-01', '2023-06-01', '2023-12-31'])
280times[1] = np.ma.masked # Mark as missing
282# Check for masks
283print(times.mask) # [False True False]
285# Drop missing rows; .unmasked merely removes the mask and exposes stored values.
286times_clean = times[~times.mask]
288# Fill masked values
289times_filled = times.filled(Time('2000-01-01'))
290```

Masked Times

import numpy as np

# Create times with missing values
times = Time(['2023-01-01', '2023-06-01', '2023-12-31'])
times[1] = np.ma.masked  # Mark as missing

# Check for masks
print(times.mask)  # [False True False]

# Drop missing rows; .unmasked merely removes the mask and exposes stored values.
times_clean = times[~times.mask]

# Fill masked values
times_filled = times.filled(Time('2000-01-01'))
Raw lines 273 to 291
292## Time Precision and Representation

Time Precision and Representation

Raw lines 292 to 293
294### Internal Representation
296Time objects use two 64-bit floats (jd1, jd2) for high precision:
298```python
299t = Time('2023-01-15 12:30:45.123456789', format='iso', scale='utc')
301# Access internal representation
302print(t.jd1, t.jd2) # Integer and fractional parts
304# Two-part representation preserves precision; accuracy still depends on inputs.
305```

Internal Representation

Time objects use two 64-bit floats (jd1, jd2) for high precision:

t = Time('2023-01-15 12:30:45.123456789', format='iso', scale='utc')

# Access internal representation
print(t.jd1, t.jd2)  # Integer and fractional parts

# Two-part representation preserves precision; accuracy still depends on inputs.
Raw lines 294 to 306
307### Precision
309```python
310# High precision for long time intervals
311t1 = Time('1900-01-01')
312t2 = Time('2100-01-01')
313dt = t2 - t1
314print(f"Time span: {dt.sec / (365.25 * 86400)} years")
315# Maintains precision throughout
316```

Precision

# High precision for long time intervals
t1 = Time('1900-01-01')
t2 = Time('2100-01-01')
dt = t2 - t1
print(f"Time span: {dt.sec / (365.25 * 86400)} years")
# Maintains precision throughout
Raw lines 307 to 317
318## Time Formatting

Time Formatting

Raw lines 318 to 319
320### Custom String Format
322```python
323t = Time('2023-01-15 12:30:45')
325# Strftime-style formatting
326t.strftime('%Y-%m-%d %H:%M:%S') # '2023-01-15 12:30:45'
327t.strftime('%B %d, %Y') # 'January 15, 2023'
329# ISO format subformats
330t.iso # '2023-01-15 12:30:45.000'
331t.isot # '2023-01-15T12:30:45.000'
332t.to_value('iso', subfmt='date_hms') # '2023-01-15 12:30:45.000'
333```

Custom String Format

t = Time('2023-01-15 12:30:45')

# Strftime-style formatting
t.strftime('%Y-%m-%d %H:%M:%S')  # '2023-01-15 12:30:45'
t.strftime('%B %d, %Y')          # 'January 15, 2023'

# ISO format subformats
t.iso                    # '2023-01-15 12:30:45.000'
t.isot                   # '2023-01-15T12:30:45.000'
t.to_value('iso', subfmt='date_hms')  # '2023-01-15 12:30:45.000'
Raw lines 320 to 334
335## Common Use Cases

Common Use Cases

Raw lines 335 to 336
337### Converting Between Formats
339```python
340# MJD to ISO
341t_mjd = Time(59945.0, format='mjd')
342iso_string = t_mjd.iso
344# ISO to JD
345t_iso = Time('2023-01-15 12:00:00')
346jd_value = t_iso.jd
348# Unix to ISO
349t_unix = Time(1673785845.0, format='unix')
350iso_string = t_unix.iso
351```

Converting Between Formats

# MJD to ISO
t_mjd = Time(59945.0, format='mjd')
iso_string = t_mjd.iso

# ISO to JD
t_iso = Time('2023-01-15 12:00:00')
jd_value = t_iso.jd

# Unix to ISO
t_unix = Time(1673785845.0, format='unix')
iso_string = t_unix.iso
Raw lines 337 to 352
353### Time Differences in Various Units
355```python
356t1 = Time('2023-01-01')
357t2 = Time('2023-12-31')
359dt = t2 - t1
360print(f"Days: {dt.to(u.day)}")
361print(f"Hours: {dt.to(u.hour)}")
362print(f"Seconds: {dt.sec}")
363print(f"Years: {dt.to(u.year)}")
364```

Time Differences in Various Units

t1 = Time('2023-01-01')
t2 = Time('2023-12-31')

dt = t2 - t1
print(f"Days: {dt.to(u.day)}")
print(f"Hours: {dt.to(u.hour)}")
print(f"Seconds: {dt.sec}")
print(f"Years: {dt.to(u.year)}")
Raw lines 353 to 365
366### Creating Regular Time Series
368```python
369# Daily observations for a year
370start = Time('2023-01-01')
371times = start + np.arange(365) * u.day
373# Hourly observations for a day
374start = Time('2023-01-15 00:00:00')
375times = start + np.arange(24) * u.hour
377# Observations every 30 seconds
378start = Time('2023-01-15 12:00:00')
379times = start + np.arange(1000) * 30 * u.second
380```

Creating Regular Time Series

# Daily observations for a year
start = Time('2023-01-01')
times = start + np.arange(365) * u.day

# Hourly observations for a day
start = Time('2023-01-15 00:00:00')
times = start + np.arange(24) * u.hour

# Observations every 30 seconds
start = Time('2023-01-15 12:00:00')
times = start + np.arange(1000) * 30 * u.second
Raw lines 366 to 381
382### Time Zone Handling
384```python
385# UTC to local time (requires datetime)
386t = Time('2023-01-15 12:00:00', scale='utc')
387dt_utc = t.to_datetime()
389# Standard-library timezone conversion; datetime cannot represent leap seconds.
390from datetime import timezone
391from zoneinfo import ZoneInfo
392dt_eastern = t.to_datetime(timezone=timezone.utc).astimezone(ZoneInfo("America/New_York"))
393```

Time Zone Handling

# UTC to local time (requires datetime)
t = Time('2023-01-15 12:00:00', scale='utc')
dt_utc = t.to_datetime()

# Standard-library timezone conversion; datetime cannot represent leap seconds.
from datetime import timezone
from zoneinfo import ZoneInfo
dt_eastern = t.to_datetime(timezone=timezone.utc).astimezone(ZoneInfo("America/New_York"))
Raw lines 382 to 394
395### Barycentric Correction Example
397```python
398from astropy.coordinates import SkyCoord, EarthLocation
400# Target coordinates
401target = SkyCoord(ra='23h23m08.55s', dec='+18d24m59.3s')
403# Observatory location
404# Synthetic site for a self-contained example; use surveyed coordinates in research.
405location = EarthLocation(lat=40*u.deg, lon=-120*u.deg, height=1000*u.m)
407# Observation times (must include location)
408times = Time(['2023-01-15 08:30:00', '2023-01-16 08:30:00'],
409 location=location, scale='utc')
411# Calculate barycentric correction
412ltt_bary = times.light_travel_time(target, kind='barycentric')
414# Apply correction to get barycentric times
415times_bary = times.tdb + ltt_bary
417# For radial velocity work, use the coordinate helper instead
418# times already carries the observer location: do not supply it a second time.
419rv_correction = target.radial_velocity_correction(obstime=times)
420```

Barycentric Correction Example

from astropy.coordinates import SkyCoord, EarthLocation

# Target coordinates
target = SkyCoord(ra='23h23m08.55s', dec='+18d24m59.3s')

# Observatory location
# Synthetic site for a self-contained example; use surveyed coordinates in research.
location = EarthLocation(lat=40*u.deg, lon=-120*u.deg, height=1000*u.m)

# Observation times (must include location)
times = Time(['2023-01-15 08:30:00', '2023-01-16 08:30:00'],
             location=location, scale='utc')

# Calculate barycentric correction
ltt_bary = times.light_travel_time(target, kind='barycentric')

# Apply correction to get barycentric times
times_bary = times.tdb + ltt_bary

# For radial velocity work, use the coordinate helper instead
# times already carries the observer location: do not supply it a second time.
rv_correction = target.radial_velocity_correction(obstime=times)
Raw lines 395 to 421
422## Performance Considerations
4241. **Array operations are fast**: Process multiple times as arrays
4252. **Format conversions are cached**: Repeated access is efficient
4263. **Scale conversions may require IERS data**: Update `astropy-iers-data` before offline runs, or set `iers.conf.auto_download = False` to prevent network access
4274. **Precision is not accuracy**: Input timestamps, leap seconds, IERS, ephemerides
428 and observatory/target coordinates bound physical accuracy. Preserve `jd1`,
429 `jd2`, scale and location when serializing precise times; a single float JD loses precision.

Performance Considerations

  1. Array operations are fast: Process multiple times as arrays
  2. Format conversions are cached: Repeated access is efficient
  3. Scale conversions may require IERS data: Update astropy-iers-data before offline runs, or set iers.conf.auto_download = False to prevent network access
  4. Precision is not accuracy: Input timestamps, leap seconds, IERS, ephemerides and observatory/target coordinates bound physical accuracy. Preserve jd1, jd2, scale and location when serializing precise times; a single float JD loses precision.
Raw lines 422 to 429