I could finally install the astronomical calculations Efem package in my Windows7 64 bit machine and Python 3.3.1 thanks to the precompiled version distributed by http://www.lfd.uci.edu/%7Egohlke/pythonlibs/.
In learning to use it I have stumbled on the following oddity, for which I can find no explanation:
Python 3.3.1 (v3.3.1:d9893d13c628, Apr 6 2013, 20:30:21) [MSC v.1600 64 bit (AMD64)] on win32 Type "copyright", "credits" or "license()" for more information.
>>> import ephem
>>> ephem.localtime( ephem.Date( '1970' ) )
datetime.datetime(1970, 1, 1, 1, 0, 0, 3)
>>> ephem.localtime( ephem.Date( '1969' ) )
Rastreo (llamadas recientes más última):
File "", line 1, in ephem.localtime( ephem.Date( '1969' ) )
File "C:\Python33\lib\site-packages\ephem__init__.py", line 479, in localtime timetuple = time.localtime(calendar.timegm(date.tuple()))
OSError: [Errno 22] Invalid argument
All arguments smaller than 1970 trigger this same error. As ephem.Date() does not seem to be the culprit,
I can only conclude that the odd behaviour belongs to ephem.localtime(). Is my use of it mistaken or does the code have some bug?
preguntado el 05 de mayo de 13 a las 17:05
I'm not directly familiar with the Ephem package, but the behavior you're seeing strongly suggests that what you're seeing is an epoch problem; the Unix epoch being 1970-01-01 00:00:00 UTC, attempts to convert dates prior to that into a Unix time value (an unsigned 32- or 64-bit int) will have undefined results.
A juzgar por the documentation for Ephem's
date Método, this shouldn't be happening; that appears to use a different internal time representation whose epoch is 1899-12-31 12:00:00, though I'm not quite sure in what time zone. The Ephem
localtime método, sin embargo, returns a Python
datetime objeto; Python's own documentation for the datetime module describe
datetime as supporting years ranging from 1 to 9999, so the behavior you're seeing would seem to suggest that, somewhere between Ephem's internal date representation and Python's
datetime, there's an attempt to convert to a Unix timestamp. Looking at the traceback in your question, we have the following highly suggestive line:
File "C:\Python33\lib\site-packages\ephem__init__.py", line 479, in localtime \ timetuple = time.localtime(calendar.timegm(date.tuple()))
And in checking the Python documentation for the calendar module, encontramos:
An unrelated but handy function that takes a time tuple such as returned by the gmtime() function in the time module, and returns the corresponding Unix timestamp value, assuming an epoch of 1970, and the POSIX encoding. In fact, time.gmtime() and timegm() are each others’ inverse.
So there's the problem: Ephem
localtime() is trying to pass its argument through the Unix timestamp format, which isn't working because dates earlier than the Unix epoch would have to be represented by negative timestamp values, and the Unix timestamp is an unsigned integer.
Now, as for how to go about fixing this, there I'm afraid I may not be of as much help, because I've never used either Ephem or Python. In general, I'd advise modifying Ephem
localtime() so that it doesn't try to represent its argument as a Unix timestamp; perhaps there's some more widely ranging time representation you could use, or perhaps you could rework
localtime() to operate in terms of the time conversion functions provided by the datetime module.
It also occurs to me that you may wish to report this to the Ephem developers as a bug; if their package is intended to work with dates ranging back to 1899 and possibly before, then presumably they would be interested to know at least one of the functions in their package can't handle anything earlier than 1970. (Of course, their documentation may describe this limitation of
localtime(); I didn't find anything about it when I looked, but my review was hardly exhaustive.)
It works on my machine (Ubuntu, Python 3.3.0, ephem 22.214.171.124):
>>> 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)