时间和日期 (astropy.time#

介绍#

这个 astropy.time Package提供了操作时间和日期的功能。特别强调支持天文学中使用的时间标度(例如,UTC、TAI、UT1、TDB)和时间表示法(例如,JD、MJD、ISO 8601),这些时间标度和时间表示法需要计算恒星时和重心改正。这个 astropy.time 基于快速和内存效率的封装 PyERFA 用包装纸包裹着 ERFA 时间和日历例程。

所有的时间操作和算术运算都在内部使用两个64位浮点来表示时间。浮点算法来自 [1] 是为了使 Time 这个物体在宇宙年龄段内保持亚纳秒级的精度。

入门#

常用的使用方法 astropy.time is to create a Time object by supplying one or more input time values as well as the time formattime scale 这些价值观。输入时间可以是单个标量,例如 "2010-01-01 00:00:00" 或者是一个列表或者一个 numpy 如下所示的值数组。通常,任何输出值都具有与输入相同的形状(标量或数组)。

实例#

创建一个 Time 对象:

>>> import numpy as np
>>> from astropy.time import Time
>>> times = ['1999-01-01T00:00:00.123456789', '2010-01-01T00:00:00']
>>> t = Time(times, format='isot', scale='utc')
>>> t
<Time object: scale='utc' format='isot' value=['1999-01-01T00:00:00.123' '2010-01-01T00:00:00.000']>
>>> t[1]
<Time object: scale='utc' format='isot' value=2010-01-01T00:00:00.000>

这个 format 参数指定如何解释输入值(例如,ISO、JD或Unix时间)。默认情况下,将使用相同的格式表示输出时间。您可以稍后根据需要更改此格式,但因为这仅用于表示,所以不会影响内部表示(始终是两个64位值, jd1jd2 属性),也不对该对象进行任何计算。

这个 scale 参数指定 time scale 值(例如,UTC、TT或UT1)。这个 scale 参数是可选的,默认为UTC,除非 Time from Epoch Formats 。可以将其更改(例如,从UTC更改为TDB),这将导致相应地调整内部值。

我们可以把上面写为:

>>> t = Time(times, format='isot')

当可以明确地确定输入的格式时 format 不需要参数,因此我们可以进一步简化:

>>> t = Time(times)

现在我们可以通过请求相应的 Time 属性::

>>> t.jd  
array([2451179.50000143, 2455197.5       ])
>>> t.mjd  
array([51179.00000143, 55197.        ])

可通过表示输出的全部功率 to_value method which also allows controlling the subformat . 例如,使用 numpy.longdouble 作为更高精度的输出类型:

>>> t.to_value('mjd', 'long')  
array([51179.00000143, 55197.        ], dtype=float128)

可以通过设置 format 属性:

>>> t.format = 'fits'
>>> t
<Time object: scale='utc' format='fits' value=['1999-01-01T00:00:00.123'
                                               '2010-01-01T00:00:00.000']>
>>> t.format = 'isot'

我们也可以转换成不同的时间尺度,例如从UTC到TT。它使用与上面相同的属性机制,但现在返回一个新的 Time 对象:

>>> t2 = t.tt
>>> t2
<Time object: scale='tt' format='isot' value=['1999-01-01T00:01:04.307' '2010-01-01T00:01:06.184']>
>>> t2.jd  
array([2451179.5007443 , 2455197.50076602])

注意ISO(ISOT)和JD表示 t2 不同于 t 因为它们是相对于TT时间尺度来表达的。当然,从数字或字符串来看,你无法分辨出是这样的:

>>> print(t2.fits)
['1999-01-01T00:01:04.307' '2010-01-01T00:01:06.184']

您可以使用 numpy 数组设置项语法::

>>> t2 = t.tt.copy()  # Copy required if transformed Time will be modified
>>> t2[1] = '2014-12-25'
>>> print(t2)
['1999-01-01T00:01:04.307' '2014-12-25T00:00:00.000']

这个 Time 对象还支持缺少值,这对于 表操作 如连接和堆放:

>>> t2[0] = np.ma.masked  # Declare that first time is missing or invalid
>>> print(t2)
[                      ——— '2014-12-25T00:00:00.000']

最后,还有一些可能的例子。有关详细信息,请参阅下面的API文档。

>>> dt = t[1] - t[0]
>>> dt  
<TimeDelta object: scale='tai' format='jd' value=4018.00002172>

这里,注意时间刻度到TAI的转换。时间差只能有一天等于86400秒的刻度。

>>> import numpy as np
>>> t[0] + dt * np.linspace(0., 1., 12)
<Time object: scale='utc' format='isot' value=['1999-01-01T00:00:00.123' '2000-01-01T06:32:43.930'
 '2000-12-31T13:05:27.737' '2001-12-31T19:38:11.544'
 '2003-01-01T02:10:55.351' '2004-01-01T08:43:39.158'
 '2004-12-31T15:16:22.965' '2005-12-31T21:49:06.772'
 '2007-01-01T04:21:49.579' '2008-01-01T10:54:33.386'
 '2008-12-31T17:27:17.193' '2010-01-01T00:00:00.000']>
>>> t.sidereal_time('apparent', 'greenwich')  
<Longitude [6.68050179, 6.70281947] hourangle>

您还可以使用基于时间的 Quantity 对于时间算术:

>>> import astropy.units as u
>>> Time("2020-01-01") + 5 * u.day
<Time object: scale='utc' format='iso' value=2020-01-06 00:00:00.000>

从5.1版开始, Time 对象也可以直接传递给 numpy.linspace 创建偶采样时间数组,包括对非标量的支持 start 和/或 stop 点-给出兼容的形状。

>>> stop = ['1999-01-05T00:00:00.123456789', '2010-05-01T00:00:00']
>>> tstp = Time(stop, format='isot', scale='utc')
>>> np.linspace(t, tstp, 4, endpoint=False)
<Time object: scale='utc' format='isot' value=[['1999-01-01T00:00:00.123' '2010-01-01T00:00:00.000']
 ['1999-01-02T00:00:00.123' '2010-01-31T00:00:00.000']
 ['1999-01-03T00:00:00.123' '2010-03-02T00:00:00.000']
 ['1999-01-04T00:00:00.123' '2010-04-01T00:00:00.000']]>

使用 astropy.time#

时间对象基础#

astropy.time 以时间为单位表示的时间与时间的关系。在“日期”和“时间”之间没有区别,因为这两个概念(在一般用法中的松散定义)只是时间上某个时刻的不同表示。

时间格式#

时间格式指定如何表示时间的某一瞬间。可在中找到当前可用的格式 Time.FORMATS 下表列出了dict和。这些格式中的每一种都是作为一个从基派生的类来实现的 TimeFormat 班级。对于中未提供的专用时间格式,用户可以调整和扩展此类结构 astropy.time .

格式

等级

示例参数

拜耳

TimeBesselianEpoch

1950.0

byear_str

TimeBesselianEpochString

'B1950.0'

cxcsec公司

TimeCxcSec

63072064.184

日期时间

TimeDatetime

日期2,时间

十进制年

TimeDecimalYear

2000.45

适合

TimeFITS

‘2000-01-01T00:00:00.000’

全球定位系统

TimeGPS

630720013.0

国际标准化组织

TimeISO

'2000-01-01 00:00:00.000'

isot公司

TimeISOT

‘2000-01-01T00:00:00.000’

法学博士

TimeJD

2451544.5

jyear公司

TimeJulianEpoch

2000.0

jyear_str

TimeJulianEpochString

'J2000.0'

美赞臣

TimeMJD

51544.0

plot_date

TimePlotDate

730120.0003703703

UNIX

TimeUnix

946684800.0

unix_tai

TimeUnixTai

946684800.0

白天

TimeYearDayTime

2000:001:00:00:00.000

基督教青年会

TimeYMDHMS

{'year':2010,'月':3,'日':1}

日期时间64

TimeDatetime64

np.日期时间64('2000-01-01T01:01:01')

备注

这个 TimeFITS 格式实现了大部分的FITS标准 [2], 包括对 LOCAL 时间刻度。但是请注意,FITS支持一些不推荐使用的时间刻度名称;这些名称在初始化时被转换为正式名称。此外,任何特定的实现信息,例如 UT(NIST) 仅在时间刻度不变的情况下存储。

更改格式#

可以通过设置 format 属性:

>>> t = Time('2000-01-02')
>>> t.format = 'jd'
>>> t
<Time object: scale='utc' format='jd' value=2451545.5>

请注意,在更改格式时,当前输出子格式(请参阅下面的部分)可能不存在于新格式中。在这种情况下,将不保留子格式::

>>> t = Time('2000-01-02', format='fits', out_subfmt='longdate')
>>> t.value
'+02000-01-02'
>>> t.format = 'iso'
>>> t.out_subfmt
u'*'
>>> t.format = 'fits'
>>> t.value
'2000-01-02T00:00:00.000'
子格式#

许多可用的时间格式类都支持子格式的概念。这允许在输入解析/验证和输出中对格式的基本主题进行变化。

下表说明了字符串格式的可用子格式

isofitsyday 格式:

格式

子格式

输入/输出

iso

date_hms

2001-01-02 03:04:05.678

iso

date_hm

2001-01-02 03:04

iso

日期

2001-01-02

fits

date_hms

2001-01-02T03:04:05.678

fits

longdate_hms

+02001-01-02T03:04:05.678

fits

长枣

+02001-01-02

yday

date_hms

2001:032:03:04:05.678

yday

date_hm

2001:032:03:04

yday

日期

2001:032

数字格式,如 mjdjyearcxcsec 所有支持子格式: 'float''long''decimal''str''bytes' . 在这里, 'long' 使用 numpy.longdouble 以提高精度(增强程度取决于平台),以及 'decimal' 实例 decimal.Decimal 完全精确。对于 'str''bytes' 子格式中,也会选择位数以便精确地表示时间值。

当在输入上使用时,这些格式允许使用单个输入值创建时间,该输入值精确地捕捉到 Time . 相反,使用 Time to_valueTimeDelta to_value 可以具有比标准64位浮点更高的精度:

>>> tm = Time('51544.000000000000001', format='mjd')  # String input
>>> tm.mjd  # float64 output loses last digit but Decimal gets it
51544.0
>>> tm.to_value('mjd', subfmt='decimal')  
Decimal('51544.00000000000000099920072216264')
>>> tm.to_value('mjd', subfmt='str')
'51544.000000000000001'

的子格式选项的完整列表 Time 包含它们的格式是:

格式

子格式

byear

浮点、长、十进制、str、字节

cxcsec

浮点、长、十进制、str、字节

datetime64

日期,日期,日期

decimalyear

浮点、长、十进制、str、字节

fits

日期,日期,日期,日期,日期

gps

浮点、长、十进制、str、字节

iso

日期,日期,日期

isot

日期,日期,日期

jd

浮点、长、十进制、str、字节

jyear

浮点、长、十进制、str、字节

mjd

浮点、长、十进制、str、字节

plot_date

浮点、长、十进制、str、字节

unix

浮点、长、十进制、str、字节

unix_tai

浮点、长、十进制、str、字节

yday

日期,日期,日期

的子格式选项的完整列表 TimeDelta 包含它们的格式是:

格式

子格式

jd

浮点、长、十进制、str、字节

sec

浮点、长、十进制、str、字节

quantity_str

多,你,d,小时,分钟,S

历元格式的时间#

格式 cxcsecgpsunixunix_tai 它们的特殊之处在于它们提供了自特定参考日期以来以秒为单位的已用时间的浮点表示。这些格式有一个内在的时间刻度,用来计算自参考日期以来经过的秒数。

格式

规模

参考日期

cxcsec

TT

1998-01-01 00:00:00

unix

UTC

1970-01-01 00:00:00

unix_tai

TAI

1970-01-01 00:00:08

gps

TAI

1980-01-06 00:00:19

与其他默认为UTC的格式不同,如果不是 scale 初始化时提供 Time 对象,则使用上述内部比例。这样做是为了提高计算效率。

时间尺度#

时间刻度(或 time standard )是“测量时间的规范:时间流逝的速率;或时间点;或两者兼而有之” [3], [4]. ::

>>> Time.SCALES
('tai', 'tcb', 'tcg', 'tdb', 'tt', 'ut1', 'utc', 'local')

规模

描述

国际原子时

tcb公司

重心坐标时间(TCB)

tcg公司

地心坐标时间

tdb公司

质心动力学时间

tt

陆地时间(TT)

ut1型

世界时(UT1)

UTC

协调世界时(UTC)

地方的

本地时间刻度(本地)

备注

这个 local 时间刻度是指自由运行的时钟或模拟时间(即,表示没有适当定义的刻度的时间)。这意味着它不能转换为任何其他时间刻度,并且只有在以下情况下才能进行算术运算 Time 具有规模的实例 local 并且有了 TimeDelta 具有规模的实例 localNone

支持的时间尺度之间的转换系统(即 local )如下图所示。有关详细信息,请参阅 Convert time scale 部分。

../_images/time_scale_conversion.png

标量或数组#

A Time 对象可以保存单个时间值或时间值数组。区别完全是由输入时间的形式决定的。如果 Time 对象包含一个值,则任何格式输出都将是一个标量值,对于数组也是如此。

例子#

像其他数组和列表一样, Time 持有数组的对象是可下标的,根据需要返回标量或数组对象:

>>> from astropy.time import Time
>>> t = Time(100.0, format='mjd')
>>> t.jd
2400100.5
>>> t = Time([100.0, 200.0, 300.], format='mjd')
>>> t.jd  
array([2400100.5, 2400200.5, 2400300.5])
>>> t[:2]  
<Time object: scale='utc' format='mjd' value=[100. 200.]>
>>> t[2]
<Time object: scale='utc' format='mjd' value=300.0>
>>> t = Time(np.arange(50000., 50003.)[:, np.newaxis],
...          np.arange(0., 1., 0.5), format='mjd')
>>> t  
<Time object: scale='utc' format='mjd' value=[[50000.  50000.5]
 [50001.  50001.5]
 [50002.  50002.5]]>
>>> t[0]  
<Time object: scale='utc' format='mjd' value=[50000.  50000.5]>

NumPy方法的类比和适用的NumPy函数#

Time 实例包含数组,许多相同的方法和属性 ndarray 可以使用实例。例如,您可以重塑 Time 实例,并使用 reshape()ravel()flatten()Ttranspose()swapaxes()diagonal()squeeze() ,或 take() 。相应的函数,以及影响形状的其他函数,例如 atleast_1drollaxis ,如预期般工作。(相关功能必须在中明确启用 astropy 源代码;如果一个 numpy 不支持您认为应该起作用的函数。)

实例#

重塑 Time 实例::

>>> t.reshape(2, 3)
<Time object: scale='utc' format='mjd' value=[[50000.  50000.5 50001. ]
 [50001.5 50002.  50002.5]]>
>>> t.T
<Time object: scale='utc' format='mjd' value=[[50000.  50001.  50002. ]
 [50000.5 50001.5 50002.5]]>
>>> np.roll(t, 1, axis=0)
<Time object: scale='utc' format='mjd' value=[[50002.  50002.5]
 [50000.  50000.5]
 [50001.  50001.5]]>

请注意,与 ndarray 方法,除了 flatten() 尝试使用新的数据视图,只有在不可能的情况下才复制数据(如 numpy reshape()

还支持一些算术方法: min()max()ptp()sort()argmin()argmax()argsort() .

应用算术方法 Time 实例::

>>> t.max()
<Time object: scale='utc' format='mjd' value=50002.5>
>>> t.min()
<Time object: scale='utc' format='mjd' value=50000.0>

推断输入格式#

这个 Time 类初始值设定项不接受不明确的输入,但在输入不明确的情况下,它将自动进行推断。当时间作为对象和 ymdhms ,或字符串。在后一种情况下,不需要指定格式,因为可用的字符串格式没有重叠。但是,如果预先知道格式,如果提供格式,则字符串解析将更快。

例子#

要推断输入格式:

>>> from datetime import datetime, timezone
>>> t = Time(datetime(2010, 1, 2, 1, 2, 3))
>>> t.format
'datetime'
>>> t = Time('2010-01-02 01:02:03')
>>> t.format
'iso'

内部代表#

这个 Time 对象将时间的内部表示形式维护为一对表示儒略日的双精度数字。这两个数字之和就是相对于给定时间的儒略日期 time scale . 用户需要在人类时间尺度(约100年)内不超过微秒的精度,可以安全地忽略内部表示细节,并跳过本节。

这种表示是由基础的 ERFA C库实现。ERFA程序始终注意保持双对的整体精度。用户可以自由选择提供Total JD的方式,尽管在内部,一部分包含整数天,另一部分包含一天的小数,因为这确保了所有转换的最佳精度。内部JD对可通过 jd1jd2 属性::

>>> t = Time('2010-01-01 00:00:00', scale='utc')
>>> t.jd1, t.jd2
(2455198.0, -0.5)
>>> t2 = t.tai
>>> t2.jd1, t2.jd2  
(2455198., -0.49960648148148146)

创建时间对象#

允许的 Time 创建时间对象的参数如下所示:

valnumpy ndarray、list、str或number

初始化表的数据。

val2numpy ndarray、list、str或number;可选

初始化表的数据。

format可选的STR

输入值的格式。

scale可选的STR

输入值的时间刻度。

precision0到9之间的整数(包括0和9)

以浮点形式输出秒时的十进制精度。

in_subfmtSTR

Unix glob选择用于分析输入时间的子格式。

out_subfmtSTR

Unix glob为输出时间选择子格式。

位置EarthLocation 或元组,可选地球位置或元组,可选

如果是元组,三 Quantity 具有地心坐标长度单位的项目,或大地坐标的经度、纬度和可选高度的项目。可以是单个位置,也可以是每个输入时间的一个位置。

瓦尔#

这个 val 参数指定一个或多个输入时间,可以是单个字符串或数字,也可以是Python列表或 numpy 字符串数组或数字数组。要初始化 Time 对象,则它将基于指定的时间 must 一定要在场。

在大多数情况下,还需要指定 time scale 通过 scale 争论。这个 Time 同学们永远猜不到 time scale ,所以一个简单的例子是:

>>> t1 = Time(50100.0, scale='tt', format='mjd')
>>> t2 = Time('2010-01-01 00:00:00', scale='utc')

可以创建一个新的 Time 对象来自一个或多个现有时间对象。在这种情况下,除非明确指定,否则将从第一个对象推断格式和比例。:

>>> Time([t1, t2])  
<Time object: scale='tt' format='mjd' value=[50100. 55197.00076602]>

瓦尔2#

这个 val2 参数适用于需要高精度的情况。回想一下时间的内在表征 astropy.time 是两个双精度数字,求和后得到儒略日期。如果提供,则 val2 参数与 val 设置第二个内部时间值。对 val2 由输入格式类确定。忽略所有字符串值格式 val2 所有的数字输入有效地将这两个值相加,以保持最高精度。例如::

>>> t = Time(100.0, 0.000001, format='mjd', scale='tt')
>>> t.jd, t.jd1, t.jd2  
(2400100.500001, 2400101.0, -0.499999)

格式#

这个 format 参数设置时间 time format ,并且如上所述,除非可以根据输入时间明确地确定格式,否则它是必需的。

规模#

The scale argument sets the time scale and is required except for time formats such as plot_date (TimePlotDate) and unix (TimeUnix). These formats represent the duration in SI seconds since a fixed instant in time is independent of time scale. See the Time from Epoch Formats for more details.

精度#

这个 precision 当输出包含秒的值时,设置会影响字符串格式。必须是0到9之间的整数。从字符串输入时间值不起作用。默认精度为3。请注意,9位数的限制是由 ERFA 处理分数秒。实际上,这不应该是一个问题。**

>>> t = Time('B1950.0', precision=3)
>>> t.byear_str
'B1950.000'
>>> t.precision = 0
>>> t.byear_str
'B1950'

in_subfmt#

这个 in_subfmt 参数提供了一种选择一个或多个的机制 subformat 可供输入的可用子格式中的值。可以使用Unix风格的通配符选择多个允许的子格式,尤其是 *? ,如Python中所述 fnmatch 模块。

的默认值 in_subfmt* 匹配任何可用的子格式。这样可以方便地输入具有未知或异构子格式的值:

>>> Time(['2000:001', '2000:002:03:04', '2001:003:04:05:06.789'])
<Time object: scale='utc' format='yday'
 value=['2000:001:00:00:00.000' '2000:002:03:04:00.000' '2001:003:04:05:06.789']>

您可以显式指定 in_subfmt 为了严格要求某个子格式:

>>> t = Time('2000:002:03:04', in_subfmt='date_hm')
>>> t = Time('2000:002', in_subfmt='date_hm')  
Traceback (most recent call last):
  ...
ValueError: Input values did not match any of the formats where the
format keyword is optional ['astropy_time', 'datetime',
'byear_str', 'iso', 'isot', 'jyear_str', 'yday']

out_subfmt#

这个 out_subfmt 参数类似于 in_subfmt 但它适用于输出格式。如果有多个匹配的子格式,则使用第一个匹配的子格式。

>>> Time('2000-01-01 02:03:04', out_subfmt='date').iso
'2000-01-01'
>>> Time('2000-01-01 02:03:04', out_subfmt='date_hms').iso
'2000-01-01 02:03:04.000'
>>> Time('2000-01-01 02:03:04', out_subfmt='date*').iso
'2000-01-01 02:03:04.000'
>>> Time('50814.123456789012345', format='mjd', out_subfmt='str').mjd
'50814.123456789012345'

也见 subformat 部分。

位置#

此可选参数使用 EarthLocation 对象或包含可初始化的任何形式的元组:具有地心坐标(X、Y、Z)的元组,或具有大地坐标(经度、纬度、高度;高度默认为零)的元组。它们用于对观测者位置敏感的时间刻度(目前,只有TDB,它依赖于 PyERFA 例行程序 erfa.dtdb 以确定Tdb和TT之间的时间偏差),以及在没有给出明确经度的情况下的恒星时间。

>>> t = Time('2001-03-22 00:01:44.732327132980', scale='utc',
...          location=('120d', '40d'))
>>> t.sidereal_time('apparent', 'greenwich')  
<Longitude 12. hourangle>
>>> t.sidereal_time('apparent')  
<Longitude 20. hourangle>

备注

在未来的版本中,我们希望增加添加天文台对象和/或名称的可能性。

获取当前时间#

当前时间可以确定为 Time 对象使用 now 类方法:

>>> nt = Time.now()
>>> ut = Time(datetime.now(tz=timezone.utc), scale='utc')

这两个人应该很亲近。

基于C的快速数据串解析器#

基于时间的日期字符串表示形式的时间格式,包括 TimeISOTimeISOTTimeYearDayTime ,使用一个快速的基于C的数据解析器,对于大的时间数组,它可以将速度提高20倍或更多。

C解析器比基于Python的解析器(它依赖于 strptime ). 特别是月份或一年中的某一天之类的字段必须始终具有固定数量的ASCII数字。作为一个例子,Python解析器将接受 2000-1-2T3:04:5.23 而C解析器需要 2000-01-02T03:04:05.23

默认情况下,除非输入子格式 in_subfmt 参数与的默认值不同 '*' . 如果fastc解析器无法解析日期值,则 Time 初始值设定项将自动传递给Python解析器。

在极少数需要显式控制使用哪个解析器的情况下,会有一个配置项 time.conf.use_fast_parser 可以设置。默认值是 'True' ,这意味着要尝试快速解析器,如果需要,可以使用Python解析器。请注意,配置值是字符串,而不是bool对象。

例如,要禁用C解析器,请使用:

>>> from astropy.time import conf
>>> date = '2000-1-2T3:04:5.23'
>>> t = Time(date, format='isot')  # Succeeds by default
>>> with conf.set_temp('use_fast_parser', 'False'):
...     t = Time(date, format='isot')
...     print(t)
2000-01-02T03:04:05.230

要强制C解析器的用户(例如在测试中),请使用:

>>> with conf.set_temp('use_fast_parser', 'force'):
...     try:
...          t = Time(date, format='isot')
...     except ValueError as err:
...          print(err)
Input values did not match the format class isot:
ValueError: fast C time string parser failed: non-digit found where digit (0-9) required

使用时间对象#

可用的操作 Time 对象包括:

获取和设置值#

对于现有的 Time 对象的数组值,可以使用 numpy 获取单个项或项子集的数组项语法。返回值是 Time 具有所有相同属性的对象。

实例#

要获取项目或项目的子集:

>>> t = Time(['2001:020', '2001:040', '2001:060', '2001:080'],
...          out_subfmt='date')
>>> print(t[1])
2001:040
>>> print(t[1:])
['2001:040' '2001:060' '2001:080']
>>> print(t[[2, 0]])
['2001:060' '2001:020']

也可以为值为的数组设置值 Time 对象:

>>> t = Time(['2001:020', '2001:040', '2001:060', '2001:080'],
...          out_subfmt='date')
>>> t[1] = '2010:001'
>>> print(t)
['2001:020' '2010:001' '2001:060' '2001:080']
>>> t[[2, 0]] = '1990:123'
>>> print(t)
['1990:123' '2010:001' '1990:123' '2001:080']

设置时的新值(在右侧)可以是以下三种可能性之一:

  • 标量字符串值或字符串值数组,其中每个值都是有效的时间格式,可以自动分析并用于创建 Time 对象。

  • 值或值数组,其中每个值都具有相同的值 format 作为 Time 正在设置的对象。例如,浮动或 numpy 对象的浮点数组 format='unix' .

  • Time 具有相同的对象 location (但是 scaleformat 不必相同)。右侧值将被转换为时间 scale 比赛。

只要设置了任何项,则内部缓存(请参见 Caching )与 delta_tdb_tt 和/或 delta_ut1_utc 变换偏移(如果已设置)。

如果需要 Time 对象是不可变的,然后设置 writeable 属性到 False. In this case, attempting to set a value will raise a ValueError: Time object is read-only. See the section on Caching 举个例子。

缺少值#

这个 TimeTimeDelta 对象支持将值标记为丢失或无效的功能。这也被称为掩蔽,对 表操作 例如接合和堆叠。

例子#

在创建对象时,可以通过以下两种方式之一将一个或多个项目设置为缺少。首先使用一个数字掩码数组::

>>> dates = np.ma.array(['2001:020', '...', '2001:060'], mask=[False, True, False])
>>> print(Time(dates, out_subfmt="date"))
['2001:020'        ——— '2001:060']

排名第二的是 astropy.utils.masked.Masked 班级:

>>> from astropy.utils.masked import Masked
>>> dates = Masked(['2001:020', '', '2001:060'], mask=[False, True, False])
>>> t = Time(dates, out_subfmt="date")
>>> print(t)
['2001:020'        ——— '2001:060']

您也可以使用特殊的 numpy.ma.masked 将值设置为现有的 Time 对象::

>>> t = Time(["2001:020", "2001:040", "2001:060", "2001:080"], out_subfmt="date")
>>> t[2] = np.ma.masked
>>> print(t)
['2001:020' '2001:040'        ——— '2001:080']

如果要获取未屏蔽的数据,可以通过使用 unmasked 属性,或使用选定的值填充任何掩码数据::

>>> print(t.unmasked)
['2001:020' '2001:040' '2001:060' '2001:080']
>>> t_filled = t.filled('1999:365')
>>> print(t_filled)
['2001:020' '2001:040' '1999:365' '2001:080']

您还可以通过指定另一个特定值来取消设置各个元素上的遮罩, numpy.ma.nomask **

>>> t[2] = np.ma.nomask
>>> print(t)
['2001:020' '2001:040' '2001:060' '2001:080']

这两种方法之间的一个细微区别是,当您通过使用 numpy.ma.nomask ,掩码仍然存在于内部,因此任何输出都将具有掩码。相比之下,使用 unmaskedfilled() 删除所有掩码,因此任何输出都不会被掩码。这个 masked 属性可用于检查内部是否正在使用掩码::

>>> t.masked
True
>>> t.value
MaskedNDArray(['2001:020', '2001:040', '2001:060', '2001:080'],
            dtype='<U8')
>>> t_filled.masked
False
>>> t_filled.value
array(['2001:020', '2001:040', '1999:365', '2001:080'], dtype='<U8')

备注

设置掩码时,保留实际时间数据。但是,当 initializing 使用掩码数组,任何掩码时间输入数据都会在内部被覆盖,时间相当于 2000-01-01 12:00:00 (比例和格式与其他值相同)。这是为了确保掩码隐藏的无效数据不会引发错误或警告。因此,对于使用屏蔽数据的初始化,无法恢复原始屏蔽值:

>>> dates = Masked(['2001:020', '2001:040', '2001:060'],
...                mask=[False, True, False])
>>> tm = Time(dates, out_subfmt="date")
>>> tm[2] = np.ma.masked
>>> print(tm)
['2001:020'        ———        ———]
>>> print(tm.unmasked)
['2001:020' '2000:001' '2001:060']

一旦对象中的一个或多个值被屏蔽,任何操作都会将这些值作为屏蔽传播,并访问格式属性,如 unixvalue 将返回一个 Masked 对象::

>>> t[1:3] = np.ma.masked
>>> t.isot
MaskedNDArray(['2001-01-20',          ———,          ———, '2001-03-21'],
              dtype='<U10')

您可以查看 mask ,但请注意,它是只读的。设置和清除掩码始终是通过将项设置为 maskednomask ,分别为。

>>> t.mask
array([False, True,  True, False])
掩码数组类型的选择#

Time 内部使用Aspy的 Masked 类来表示掩码。可以使用NumPy的数据进行初始化 MaskedArray 类,但默认情况下,所有输出都将使用 Masked 。为了向后兼容,可以设置 masked_array_type 设置为“NumPy”以确保输出使用 MaskedArray 在可能的情况下(除 Quantity )。

自定义格式类和屏蔽值#

对象编写了自定义时间格式的高级用户 TimeFormat 子类,则可能需要修改您的类 if you wish to support masked values ,尤其是如果您早先支持 missing values 通过设置 jd2 属性为 numpy.nan 。对于不需要掩码或缺失值的应用程序,不需要任何更改。

在Astopy 6.0之前,在 TimeFormat 子类对象通过设置 jd2 属性为 numpy.nan (但这从未由用户直接完成)。从Astopy6.0开始, Masked 使用数组,这些数组被写入以正确地传播通过(几乎)所有NumPy和 ERFA 功能。

通常,只需极少的修改即可支持 Masked 数组。通常,在输入时不需要进行任何更改,因为格式将被赋予未屏蔽的值(任何屏蔽的输入值都将替换为默认值,以确保只传入有效值)。不过,在计算输出值时,可能需要注意掩码是否正确传播 jd1jd2value 财产。

获取表示#

时间的瞬间可以用不同的方式表示,例如ISO格式的日期字符串 ('1999-07-23 04:31:00' )或1998年以来的秒数 (49091460.0 )或者改为朱利安日期 (51382.187451574

a的表示 Time 通过获取与格式名对应的object属性,可以使用特定格式的对象。可用格式名的列表在 time format 部分。

>>> t = Time('2010-01-01 00:00:00', format='iso', scale='utc')
>>> t.jd        # JD representation of time in current scale (UTC)
2455197.5
>>> t.iso       # ISO representation of time in current scale (UTC)
'2010-01-01 00:00:00.000'
>>> t.unix      # seconds since 1970.0 (UTC)
1262304000.0
>>> t.datetime  # Representation as datetime.datetime object
datetime.datetime(2010, 1, 1, 0, 0)
例子#

得到一个 Time 对象:

>>> import matplotlib.pyplot as plt  
>>> jyear = np.linspace(2000, 2001, 20)  
>>> t = Time(jyear, format='jyear')  
>>> plt.plot_date(t.plot_date, jyear)  
>>> plt.gcf().autofmt_xdate()  # orient date labels at a slant  
>>> plt.draw()  

转换时间刻度#

一个新的 Time 对象,但引用了一个新的 time scale 可以创建获取与时间刻度名称相对应的对象属性。可用时间刻度名称的列表位于 time scale 第节和下图说明了时间尺度变换的网络。

../_images/time_scale_conversion.png
实例#

创建一个 Time 具有新时间刻度的对象::

>>> t = Time('2010-01-01 00:00:00', format='iso', scale='utc')
>>> t.tt        # TT scale
<Time object: scale='tt' format='iso' value=2010-01-01 00:01:06.184>
>>> t.tai
<Time object: scale='tai' format='iso' value=2010-01-01 00:00:34.000>

在这个过程中 format 以及其他对象属性,如 lonlatprecision 也会传播到新对象。

Time Object Basics 剖面图,a Time 对象只能通过显式设置其某些元素来更改。因此,更改时间刻度的过程首先制作原始对象的副本,然后将副本中的内部时间值转换为新的时间刻度。新的 Time 对象由属性access返回。

高速缓存#

将数组转换为不同的格式可能会耗费大量时间。为了避免重复计算,每个 TimeTimeDelta 实例在内部缓存这样的转换:

>>> t = Time(np.arange(1e6), format='unix', scale='utc')

>>> time x = t.tt  
CPU times: user 263 ms, sys: 4.02 ms, total: 267 ms
Wall time: 267 ms

>>> time x = t.tt  
CPU times: user 28 µs, sys: 9 µs, total: 37 µs
Wall time: 32.9 µs

更改输出精度或子格式等操作将清除缓存。要显式清除内部缓存,请执行以下操作:

>>> del t.cache

>>> time x = t.tt  
CPU times: user 263 ms, sys: 4.02 ms, total: 267 ms
Wall time: 267 ms

为了确保转换(和缓存)版本与原始版本之间的一致性,将转换后的对象设置为不可写。例如::

>>> x = t.tt
>>> x[1] = '2000:001'
Traceback (most recent call last):
  ...
ValueError: Time object is read-only. Make a copy() or set "writeable" attribute to True.

如果需要修改对象,请先复制一个对象,例如, x = t.tt.copy() .

转换偏移量#

跨越上图中一个橙色圆的时间比例变换需要一个额外的偏移时间值,该值取决于模型或观测。看见 SOFA Time Scale and Calendar Tools 了解更多细节。

这两个属性 delta_ut1_utcdelta_tdb_tt 提供一种显式设置这些偏移时间的方法。它们分别表示时间刻度偏移UT1-UTC和TDB-TT。例如:

>>> t = Time('2010-01-01 00:00:00', format='iso', scale='utc')
>>> t.delta_ut1_utc = 0.334  # Explicitly set one part of the transformation
>>> t.ut1.iso    # ISO representation of time in UT1 scale
'2010-01-01 00:00:00.334'

对于UT1到UTC偏移量,您必须插值由 International Earth Rotation and Reference Systems (IERS) Service . astropy 将自动下载并使用IER的值,这些值涵盖从1973年1月1日到未来一年的时间。此外 astropy 从1962年到1962年的数据包,与一个数据包捆绑在一起 astropy 释放。

delta_ut1_utc 属性未显式设置,将使用IERS值(第一次开始下载几个Mb的文件)。有关如何在中使用IER值的详细信息 astropy 时间和坐标,以及要了解如何控制自动下载,请参阅 IERS数据访问 (astropy.utils.iers ) . 下面的示例说明如何转换为 UT1 随着自动下载功能的扩展:

>>> t = Time('2016:001')
>>> t.ut1  
Downloading https://maia.usno.navy.mil/ser7/finals2000A.all
|==================================================================| 3.0M/3.0M (100.00%)         6s
<Time object: scale='ut1' format='yday' value=2016:001:00:00:00.082>

备注

这个 IERS_Auto 类包含一些机制,用于根据需要自动下载最新版本来确保IERS表保持最新。这意味着IERS表可以保证拥有最先进的地球自转确定性和预测值。作为一个用户 你的责任 了解IER预测的准确性,如果你的科学依赖于此。如果你要求 UT1-UTC 对于超出IERS表数据范围的时间,将提供最接近的可用值。

在TDB到TT偏移量的情况下,大多数用户只需提供 lonlat 值时创建 Time 对象。如果 delta_tdb_tt 属性,则 PyERFA 例行程序 erfa.dtdb 将用于计算TDB到TT的偏移量。请注意,如果 lonlat 未显式初始化,则将使用这两个值的0.0度。

例子#

下面的代码复制了 SOFA Time Scale and Calendar Tools 文件。它执行从UTC到所有支持的时间尺度(TAI、TCB、TCG、TDB、TT、UT1、UTC)的转换。这需要观察者的位置(这里是纬度和经度)。**

>>> import astropy.units as u
>>> t = Time('2006-01-15 21:24:37.5', format='iso', scale='utc',
...          location=(-155.933222*u.deg, 19.48125*u.deg))
>>> t.utc.iso
'2006-01-15 21:24:37.500'
>>> t.ut1.iso  
'2006-01-15 21:24:37.834'
>>> t.tai.iso
'2006-01-15 21:25:10.500'
>>> t.tt.iso
'2006-01-15 21:25:42.684'
>>> t.tcg.iso
'2006-01-15 21:25:43.323'
>>> t.tdb.iso
'2006-01-15 21:25:42.684'
>>> t.tcb.iso
'2006-01-15 21:25:56.894'

散列#

用户可以为标量(0维)生成唯一的哈希键 TimeTimeDelta 物体。密钥基于的元组 jd1jd2scalelocation (如果存在, None 否则)。

注意两个 Time 具有不同 scale 可以相等地比较,但仍然具有不同的哈希键。这是一个由性能决定的实际考虑,但在大多数情况下代表了一种理想的行为。

打印时间数组#

如果你 times 数组包含很多元素 value 参数将显示 Time 对象 t 当它被调用或打印时。要控制要显示的元素数,请设置 threshold 争论与 np.printoptions 如下:

>>> many_times = np.arange(1000)
>>> t = Time(many_times, format='cxcsec')
>>> with np.printoptions(threshold=10):
...     print(repr(t))
...     print(t.iso)
<Time object: scale='tt' format='cxcsec' value=[  0.   1.   2. ... 997. 998. 999.]>
['1998-01-01 00:00:00.000' '1998-01-01 00:00:01.000'
 '1998-01-01 00:00:02.000' ... '1998-01-01 00:16:37.000'
 '1998-01-01 00:16:38.000' '1998-01-01 00:16:39.000']

恒星时与地球自转角#

表观或平均恒星时间可以用以下公式计算 sidereal_time() 。该方法返回一个 Longitude 以小时角为单位,默认情况下为与 Time 对象已初始化。就像比例变换一样, ERFA C库例程在幕后使用,它支持遵循不同IAU分辨率的计算。

同样,人们可以用以下公式计算地球自转角度 earth_rotation_angle() 。与恒星时间不同的是,恒星时间是指春分,是UT1和地球时间的复杂函数,而地球自转角是指中间天体原点(CIO),是UT1的线性函数。

对于最近的国际天文学联合会的进动模型以及地球自转角,结果包括了TIO定位器(S‘),该定位器将地球中间原点定位在中间天极的赤道上,并经过了严格的极移校正。

例子#

计算恒星时间:

>>> t = Time('2006-01-15 21:24:37.5', scale='utc', location=('120d', '45d'))
>>> t.sidereal_time('mean')  
<Longitude 13.08952187 hourangle>
>>> t.sidereal_time('apparent')  
<Longitude 13.08950368 hourangle>
>>> t.earth_rotation_angle()  
<Longitude 13.08436206 hourangle>
>>> t.sidereal_time('apparent', 'greenwich')  
<Longitude 5.08950368 hourangle>
>>> t.sidereal_time('apparent', '-90d')  
<Longitude 23.08950368 hourangle>
>>> t.sidereal_time('apparent', '-90d', 'IAU1994')  
<Longitude 23.08950365 hourangle>

时间三角洲#

使用支持时间算术 TimeDelta 班级。以下操作可用:

这个 TimeDelta 类派生自 Time 类并共享其许多属性。一个不同的是,时间刻度必须是一天正好是86400秒。因此,刻度不能是UTC。

Quantity 带有时间单位的对象也可以用来代替 TimeDelta

可用的时间格式有:

格式

等级

TimeDeltaSec

法学博士

TimeDeltaJD

日期时间

TimeDeltaDatetime

quantity_str

TimeDeltaQuantityString

实例#

使用 TimeDelta 对象在以下几个示例中进行了说明:

>>> t1 = Time('2010-01-01 00:00:00')
>>> t2 = Time('2010-02-01 00:00:00')
>>> dt = t2 - t1  # Difference between two Times
>>> dt
<TimeDelta object: scale='tai' format='jd' value=31.0>
>>> dt.sec
2678400.0

>>> from astropy.time import TimeDelta
>>> dt2 = TimeDelta(50.0, format='sec')
>>> t3 = t2 + dt2  # Add a TimeDelta to a Time
>>> t3.iso
'2010-02-01 00:00:50.000'

>>> t2 - dt2  # Subtract a TimeDelta from a Time
<Time object: scale='utc' format='iso' value=2010-01-31 23:59:10.000>

>>> dt + dt2  
<TimeDelta object: scale='tai' format='jd' value=31.0005787037>

>>> import numpy as np
>>> t1 + dt * np.linspace(0, 1, 5)
<Time object: scale='utc' format='iso' value=['2010-01-01 00:00:00.000'
'2010-01-08 18:00:00.000' '2010-01-16 12:00:00.000' '2010-01-24 06:00:00.000'
'2010-02-01 00:00:00.000']>

>>> import astropy.units as u
>>> t1 + 1 * u.hour
<Time object: scale='utc' format='iso' value=2010-01-01 01:00:00.000>

用于表示时间增量的字符串的人类可读的多尺度格式可通过 quantity_str 格式化。请参阅 TimeDeltaQuantityString 有关更多详细信息的类文档字符串::

>>> TimeDelta(40.1 * u.hr).quantity_str
'1d 16hr 6min'
>>> t4 = TimeDelta("-1yr 2d 23hr 10min 5.6s")
>>> print(t4)
-368d 5hr 10min 5.6s
>>> t4.to_value(subfmt="d")
'-368.215d'

现已弃用的默认设置假定数字输入为天数:

>>> t1 + 5.0  
<Time object: scale='utc' format='iso' value=2010-01-06 00:00:00.000>
TimeDeltaMissingUnitWarning: Numerical value without unit or explicit format passed to TimeDelta, assuming days

这个 TimeDelta 有一个 to_value method which supports controlling the type of the output representation by providing either a format name and optional subformat 或者有效的 astropy 单位:

>>> dt.to_value(u.hr)
744.0
>>> dt.to_value('jd', 'str')
'31.0'

时间三角洲的时间尺度#

我们已经在上面显示了两个UTC时间的差是 TimeDelta 泰式的。这是因为除非用户知道两个时间差(由于闰秒,一天并不总是有86400秒),否则无法唯一定义UTC时间差。对于所有其他时间尺度 TimeDelta 继承第一个的比例 Time 对象。

实例#

为了得到一个 TimeDelta 对象:

>>> t1 = Time('2010-01-01 00:00:00', scale='tcg')
>>> t2 = Time('2011-01-01 00:00:00', scale='tcg')
>>> dt = t2 - t1
>>> dt
<TimeDelta object: scale='tcg' format='jd' value=365.0>

什么时候? TimeDelta 从中添加或减去对象 Time 对象,比例被适当地转换,最终的比例是 Time 对象:

>>> t2 + dt
<Time object: scale='tcg' format='iso' value=2012-01-01 00:00:00.000>
>>> t2.tai
<Time object: scale='tai' format='iso' value=2010-12-31 23:59:27.068>
>>> t2.tai + dt
<Time object: scale='tai' format='iso' value=2011-12-31 23:59:27.046>

TimeDelta 我不需要把时间转换成不同的比例尺

>>> dt.tt  
<TimeDelta object: scale='tt' format='jd' value=364.999999746>
>>> dt.tdb  
Traceback (most recent call last):
  ...
ScaleValueError: Cannot convert TimeDelta with scale 'tcg' to scale 'tdb'

TimeDelta 对象也可以具有未定义的比例,在这种情况下,假定它们的比例与其他对象的比例匹配 TimeTimeDelta 对象(如果是UTC时间,则为TAI):

>>> t2.tai + TimeDelta(365., format='jd', scale=None)
<Time object: scale='tai' format='iso' value=2011-12-31 23:59:27.068>

备注

从内部 Time 使用浮点数时,舍入误差会导致两次不严格相等,即使在数学上应该是相等的。特别是在UTC中,这可能会导致令人惊讶的行为,因为当您添加 TimeDelta ,它不能有UTC刻度,UTC时间首先转换为TAI,然后完成加法,最后将时间转换回UTC。因此,可能会产生舍入误差,这意味着即使预期的等式也可能不成立:

>>> t = Time(2450000., 1e-6, format='jd')
>>> t + TimeDelta(0, format='jd') == t
False

重心和日心光旅行时间修正#

光子到达天文台的时间对于精确的计时工作(例如双星或系外行星的日食/凌日计时)并不特别有用。这是因为天文台位置的变化导致光子早晚到达。解决方案是计算光子到达标准位置的时间;太阳系的重心或日心。

例子#

假设您从格林威治观察到了dwarf-nova-IP-Peg,并且有一个以MJD形式,以UTC时间刻度表示的时间列表。然后创建适当的 TimeSkyCoord 对象并计算到达重心的光行程时间,如下所示:

>>> from astropy import time, coordinates as coord, units as u
>>> ip_peg = coord.SkyCoord("23:23:08.55", "+18:24:59.3",
...                         unit=(u.hourangle, u.deg), frame='icrs')
>>> greenwich = coord.EarthLocation.of_site('greenwich')  
>>> times = time.Time([56325.95833333, 56325.978254], format='mjd',
...                   scale='utc', location=greenwich)  
>>> ltt_bary = times.light_travel_time(ip_peg)  
>>> ltt_bary 
<TimeDelta object: scale='tdb' format='jd' value=[-0.0037715  -0.00377286]>

如果你想要光到达太阳中心的时间,那么使用:

>>> ltt_helio = times.light_travel_time(ip_peg, 'heliocentric') 
>>> ltt_helio 
<TimeDelta object: scale='tdb' format='jd' value=[-0.00376576 -0.00376712]>

该方法返回一个 TimeDelta 对象,可以将其添加到时间中,以给出光子到达重心或太阳中心的时间。在这里,您应该小心使用的时间刻度;有关时间刻度的更多详细信息,请参阅 时间尺度 .

日心不是一个固定的点,因此重力在日心处不断变化。因此,使用像TDB这样的相对论时间标度并不特别合适,而且,历史上,校正到太阳中心的时间是在UTC时间刻度中给出的:

>>> times_heliocentre = times.utc + ltt_helio  

对重心的修正比日心更精确,因为重心是重力恒定的固定点。为了获得最大的准确度,你希望你的重心校正时间在一个时间刻度上,总是以一个统一的速率打勾,理想情况下,它的滴答频率与时钟在重心上的滴答频率有关。因此,重心校正时间通常使用TDB时间刻度:

>>> time_barycentre = times.tdb + ltt_bary  

默认情况下,使用地球和太阳的位置和速度计算光波传播时间 ERFA 例程,但您也可以使用JPL星历(从动力学模型派生)来获得更精确的计算。使用喷气推进实验室星历的一个例子是:

>>> ltt_bary_jpl = times.light_travel_time(ip_peg, ephemeris='jpl') 
>>> ltt_bary_jpl 
<TimeDelta object: scale='tdb' format='jd' value=[-0.0037715  -0.00377286]>
>>> (ltt_bary_jpl - ltt_bary).to(u.ms) 
<Quantity [-0.00132325, -0.00132861] ms>

内置星历和JPL星历的差别通常是1/100毫秒,因此内置星历应该适合大多数用途。有关可用星历的更多详细信息,包括使用JPL星历的要求,请参阅 太阳系星历 .

与类时量的相互作用#

可能的话, Quantity 具有时间单位的对象被视为 TimeDelta 具有未定义比例的对象(尽管精度必须较低)。它们也可以用作构造的输入 TimeTimeDelta 对象,以及 TimeDelta 对象可以转换为 Quantity 任意时间单位的对象。

实例#

使用 Quantity 具有时间单位的对象:

>>> import astropy.units as u
>>> Time(10.*u.yr, format='gps')   # time-valued quantities can be used for
...                                # for formats requiring a time offset
<Time object: scale='tai' format='gps' value=315576000.0>
>>> Time(10.*u.yr, 1.*u.s, format='gps')
<Time object: scale='tai' format='gps' value=315576001.0>
>>> Time(2000.*u.yr, format='jyear')
<Time object: scale='tt' format='jyear' value=2000.0>
>>> Time(2000.*u.yr, format='byear')
...                                # but not for Besselian year, which implies
...                                # a different time scale
...
Traceback (most recent call last):
  ...
ValueError: Input values did not match the format class byear:
ValueError: cannot use Quantities for 'byear' format, as the unit of year is defined as 365.25 days, while the length of year is variable in this format. Use float instead.

>>> TimeDelta(10.*u.yr)            # With a quantity, no format is required
<TimeDelta object: scale='None' format='jd' value=3652.5>

>>> dt = TimeDelta([10., 20., 30.], format='jd')
>>> dt.to(u.hr)                    # can convert TimeDelta to a quantity  
<Quantity [240., 480., 720.] h>
>>> dt > 400. * u.hr               # and compare to quantities with units of time
array([False,  True,  True]...)
>>> dt + 1.*u.hr                   # can also add/subtract such quantities  
<TimeDelta object: scale='None' format='jd' value=[10.04166667 20.04166667 30.04166667]>
>>> Time(50000., format='mjd', scale='utc') + 1.*u.hr  
<Time object: scale='utc' format='mjd' value=50000.0416667>
>>> dt * 10.*u.km/u.s              # for multiplication and division with a
...                                # Quantity, TimeDelta is converted  
<Quantity [100., 200., 300.] d km / s>
>>> dt * 10.*u.Unit(1)             # unless the Quantity is dimensionless  
<TimeDelta object: scale='None' format='jd' value=[100. 200. 300.]>

编写自定义格式#

某些应用程序可能需要自定义 Time 格式,此功能可通过 TimeFormat 班级。当在代码中定义这样的子类时,格式类和相应的名称将自动注册到可用的时间格式集中。

实例#

新格式类的关键元素通过检查 jd 格式(这是最简单的格式之一):

class TimeJD(TimeFormat):
    """
    Julian Date time format.
    """
    name = 'jd'  # Unique format name

    def set_jds(self, val1, val2):
        """
        Set the internal jd1 and jd2 values from the input val1, val2.
        The input values are expected to conform to this format, as
        validated by self._check_val_type(val1, val2) during __init__.
        """
        self._check_scale(self._scale)  # Validate scale.
        self.jd1, self.jd2 = day_frac(val1, val2)

    @property
    def value(self):
        """
        Return format ``value`` property from internal jd1, jd2
        """
        return self.jd1 + self.jd2

如上所述 _check_val_type(self, val1, val2) 方法可能需要重写,以验证输入是否符合格式规范。默认情况下,它检查有效的float、float数组或 Quantity 输入。相比之下 iso format类确保输入符合字符串的ISO格式规范。

一个比较常见且更易于实现的特殊情况是对日期格式进行了小更改的格式。例如,可以插入 Tyday 使用以下格式 TimeYearDayTimeCustom 班级。注意 subfmts 定义在标准基础上稍作修改 TimeISO 它继承的类:

>>> from astropy.time import TimeISO
>>> class TimeYearDayTimeCustom(TimeISO):
...    """
...    Year, day-of-year and time as "<YYYY>-<DOY>T<HH>:<MM>:<SS.sss...>".
...    The day-of-year (DOY) goes from 001 to 365 (366 in leap years).
...    For example, 2000-001T00:00:00.000 is midnight on January 1, 2000.
...    The allowed subformats are:
...    - 'date_hms': date + hours, mins, secs (and optional fractional secs)
...    - 'date_hm': date + hours, mins
...    - 'date': date
...    """
...    name = 'yday_custom'  # Unique format name
...    subfmts = (('date_hms',
...                '%Y-%jT%H:%M:%S',
...                '{year:d}-{yday:03d}T{hour:02d}:{min:02d}:{sec:02d}'),
...               ('date_hm',
...                '%Y-%jT%H:%M',
...                '{year:d}-{yday:03d}T{hour:02d}:{min:02d}'),
...               ('date',
...                '%Y-%j',
...                '{year:d}-{yday:03d}'))


>>> t = Time('2000-01-01')
>>> t.yday_custom
'2000-001T00:00:00.000'
>>> t2 = Time('2016-001T00:00:00')
>>> t2.iso
'2016-01-01 00:00:00.000'

另一个比较常见的特殊情况是一种表示自特定纪元以来的时间的格式。典型的例子是Unix时间,它是自1970-01-01 00:00:00 UTC以来的秒数,不包括闰秒。如果我们想要这个价值,但是 do 想数一数闰秒。这可以通过使用TAI刻度代替UTC刻度来实现。在这种情况下,我们继承了 TimeFromEpoch 类并定义一些类属性:

>>> from astropy.time.formats import erfa, TimeFromEpoch
>>> class TimeUnixLeap(TimeFromEpoch):
...    """
...    Seconds from 1970-01-01 00:00:00 TAI.  Similar to Unix time
...    but this includes leap seconds.
...    """
...    name = 'unix_leap'
...    unit = 1.0 / erfa.DAYSEC  # in days (1 day == 86400 seconds)
...    epoch_val = '1970-01-01 00:00:00'
...    epoch_val2 = None
...    epoch_scale = 'tai'  # Scale for epoch_val class attribute
...    epoch_format = 'iso'  # Format for epoch_val class attribute

>>> t = Time('2000-01-01')
>>> t.unix_leap
946684832.0
>>> t.unix_leap - t.unix
32.0

超过这一点可能需要查看 astropy 代码可以获得更多的指导,但是如果你被卡住了 astropy 开发商非常乐意提供帮助。如果你写了一个格式类,这是非常有用的,我们可能会想把它包括在核心!

时区#

当A Time 对象是从时区感知构造的 datetime ,没有时区信息保存在 Time 对象。然而, Time 对象可以转换为时区感知的datetime对象。

例子#

Time 对象到可识别时区的datetime对象::

>>> from datetime import datetime
>>> from astropy.time import Time, TimezoneInfo
>>> import astropy.units as u
>>> utc_plus_one_hour = TimezoneInfo(utc_offset=1*u.hour)
>>> dt_aware = datetime(2000, 1, 1, 0, 0, 0, tzinfo=utc_plus_one_hour)
>>> t = Time(dt_aware)  # Loses timezone info, converts to UTC
>>> print(t)            # will return UTC
1999-12-31 23:00:00
>>> print(t.to_datetime(timezone=utc_plus_one_hour)) # to timezone-aware datetime
2000-01-01 00:00:00+01:00

时区数据库包,比如 pytz 例如,可以更方便地使用来创建 tzinfo 对象用于指定时区而不是 TimezoneInfo 对象。

例子#

使用 dateutil 包中,您可以解析各种受支持格式的时间,以生成 datetime.datetime 对象,然后可以使用该对象初始化 Time 对象::

>>> from dateutil.parser import parse  
>>> dtime = parse('2020-10-29T08:20:46.950+1100')  
>>> Time(dtime)  
<Time object: scale='utc' format='datetime' value=2020-10-28 21:20:46.950000>

自定义字符串格式 strftimestrptime#

这个 Time 对象支持使用在Python标准库中定义的格式规范语言来表示输出字符串 time.strftime . 可以使用 strftime 方法。

实例#

使用 strftime 方法:

>>> from astropy.time import Time
>>> t = Time('2018-01-01T10:12:58')
>>> t.strftime('%H:%M:%S %d %b %Y')
'10:12:58 01 Jan 2018'

相反,创建一个 Time 对象从可以使用Python标准库解析的自定义日期字符串 time.strptime (使用上面链接的相同格式语言),使用 strptime 类方法:

>>> from astropy.time import Time
>>> t = Time.strptime('23:59:60 30 June 2015', '%H:%M:%S %d %B %Y')
>>> t
<Time object: scale='utc' format='isot' value=2015-06-30T23:59:60.000>

参考/API#

确认和许可#

此程序包利用 PyERFA 的包装器 ERFA ANSI C库。本网站的版权 ERFA 软件属于NumFOCUS基金会。该库是在“BSD-3条款”许可证的条款下提供的。

这个 ERFA 经允许,类库源自国际天文学联合会的《基础天文学标准》( SOFA )库,可从http://www.iausofa.org.获得