Ephem的Python包* localtime()*函数的奇怪行为

时间:2013-05-05 16:59:27

标签: windows-7 python-3.x

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

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

  在win32上的Python 3.3.1(v3.3.1:d9893d13c628,2013年4月6日,20:30:21)[MSC v.1600 64位(AMD64)]   输入“copyright”,“credits”或“license()”以获取更多信息。

     

>>> 导入ephem

     

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

     

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

     

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

     

追踪(最近一次呼叫最后一次):

     

文件“”,第1行,in        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

     

>>>

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

2 个答案:

答案 0 :(得分:2)

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

the documentation for Ephem's date method来判断,这不应该发生;似乎使用了一个不同的内部时间表示,其时间段是1899-12-31 12:00:00,虽然我不太确定在什么时区。然而,Ephem localtime方法returns a Python datetime object; Python's own documentation for the datetime moduledatetime描述为支持年份介于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()))

在检查the Python documentation for the calendar module时,我们发现:

  

calendar.timegm(元组)

     

一个不相关但很方便的函数,它接受一个时间元组,例如时间模块中的gmtime()函数返回的,并返回相应的Unix时间戳值,假定一个1970年的纪元,并且POSIX编码。事实上,time.gmtime()和timegm()彼此是反向的。

所以有问题:Ephem localtime()试图通过Unix时间戳格式传递它的参数,这种格式不起作用,因为早于Unix纪元的日期必须用负时间戳值表示,并且Unix时间戳是无符号整数。

现在,关于如何解决这个问题,恐怕我可能没那么多帮助,因为我从未使用过Ephem或Python。一般来说,我建议修改Ephem localtime(),以便它不会试图将其参数表示为Unix时间戳;也许你可以使用更广泛的时间表示,或者你可以返工localtime()来操作日期时间模块提供的时间转换功能。

我也想到你可能希望向Ephem开发者报告这个错误;如果他们的软件包打算使用的日期可以追溯到1899年之前,可能之前,那么他们可能会有兴趣知道他们的软件包中至少有一个函数不能在1970年之前处理任何事情。(当然,他们的文档可能会描述localtime()的这种限制;我看的时候没有找到任何关于它的内容,但我的评论并不详尽。)

答案 1 :(得分: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)