3

由于http://www.lfd.uci.edu/%7Egohlke/pythonlibs/分发的预编译版本,我终于可以在我的 Windows7 64 位机器和 Python 3.3.1 中安装天文计算Ephem包。

在学习使用它时,我偶然发现了以下奇怪现象,对此我找不到任何解释:

Python 3.3.1 (v3.3.1:d9893d13c628, Apr 6 2013, 20:30:21) [MSC v.1600 64 bit (AMD64)] on win32 键入“copyright”、“credits”或“license()”了解更多信息信息。

>>>导入 ephe

>>> ephem.localtime(ephem.Date('1970'))

datetime.datetime(1970, 1, 1, 1, 0, 0, 3)

>>> ephem.localtime(ephem.Date('1969'))

回溯(最近一次通话最后):

文件“”,第 1 行,在 ephem.localtime(ephem.Date('1969'))

文件“C:\Python33\lib\site-packages\ephem__init__.py”,第 479 行,本地时间 timetuple = time.localtime(calendar.timegm(date.tuple()))

OSError:[Errno 22] 参数无效

>>>

所有小于1970的参数都会触发同样的错误。由于ephem.Date()似乎不是罪魁祸首,

>>> ephem.Date('1969')

25202.5

>>>

我只能得出结论,奇怪的行为属于ehem.localtime()。我的使用是错误的还是代码有一些错误?

4

2 回答 2

2

我并不直接熟悉 Ephem 包,但您所看到的行为强烈表明您所看到的是一个时代问题;Unix 纪元是 1970-01-01 00:00:00 UTC,尝试将在此之前的日期转换为 Unix 时间值(无符号 32 位或 64 位整数)将产生未定义的结果。

Ephemdate方法的文档来看,这不应该发生;这似乎使用了不同的内部时间表示,其纪元是 1899-12-31 12:00:00,尽管我不太确定在哪个时区。localtime然而,Ephem方法返回一个 Pythondatetime对象Python 自己的 datetime 模块文档描述datetime为支持从 1 到 9999 的年份,因此您看到的行为似乎表明,在 Ephem 的内部日期表示和 Python 之间的某个地方,datetime尝试转换为 Unix 时间戳。查看您问题中的回溯,我们有以下高度暗示性的行:

File "C:\Python33\lib\site-packages\ephem__init__.py", line 479, in localtime \
timetuple = time.localtime(calendar.timegm(date.tuple()))

在检查日历模块的 Python 文档时,我们发现:

calendar.timegm(元组)

一个不相关但方便的函数,它采用时间元组,例如由 time 模块中的 gmtime() 函数返回,并返回相应的 Unix 时间戳值,假设纪元为 1970和 POSIX 编码。事实上,time.gmtime() 和 timegm() 是彼此的倒数。

所以问题就来了:Ephemlocaltime()试图通过 Unix 时间戳格式传递它的参数,这不起作用,因为早于 Unix 纪元的日期必须用负时间戳值表示,而 Unix 时间戳是一个无符号整数。

现在,至于如何解决这个问题,恐怕我可能没有太多帮助,因为我从未使用过 Ephem 或 Python。一般来说,我建议修改 Ephemlocaltime()以便它不会尝试将其参数表示为 Unix 时间戳;也许您可以使用一些更广泛的时间表示,或者您可以localtime()根据 datetime 模块提供的时间转换功能重新进行操作。

我还想到您可能希望将此作为错误报告给 Ephem 开发人员;如果他们的包打算使用追溯到 1899 年甚至更早的日期,那么大概他们有兴趣知道他们包中的至少一个函数不能处理早于 1970 年的任何事情。(当然,他们的文档可能描述这个限制localtime();我看的时候没有发现任何关于它的东西,但我的评论几乎没有详尽无遗。)

于 2013-05-05T18:17:53.107 回答
1

它适用于我的机器(Ubuntu,Python 3.3.0,ephem 3.7.5.1):

>>> import ephem
>>> ephem.Date('1969')
25202.5
>>> d = ephem.Date('1969')
>>> d.datetime() # utc
datetime.datetime(1969, 1, 1, 0, 0)
>>> ephem.localtime(d) # local timezone
datetime.datetime(1969, 1, 1, 6, 0, 0, 2)
于 2013-05-05T21:40:46.120 回答