skyfielders / python-skyfield

Elegant astronomy for Python
MIT License
1.41k stars 211 forks source link

ts.utc(...) != ts.now() when utc set to now. #344

Closed jakewilliami closed 4 years ago

jakewilliami commented 4 years ago

Hi there, I love your work! This is an excellent python package. I have also found ephem and pyephem to be useful, though I'm not sure I understand the difference between them all. They all work well.

I am running the following:

from skyfield.api import load
import datetime, time, re

planets = load('de421.bsp')
earth, mercury = planets['earth'], planets['mercury']

ts = load.timescale()

t1 = datetime.datetime.now()
precise_second_t1 = float(t1.strftime("%-S.%f"))

t_now = ts.now()
t_utc_now = ts.utc(t1.year, t1.month, t1.day, t1.hour, t1.minute, precise_second_t1)

astrometric1 = earth.at(t_now).observe(mercury)
astrometric2 = earth.at(t_utc_now).observe(mercury)

ra1, dec1, distance1 = astrometric1.radec()
ra2, dec2, distance2 = astrometric2.radec()

print('RA for ts.now():\t', ra1)
print('RA for ts.utc(...):\t', ra2)

These should print the same, but they are not. I am wondering if you know why this might be?

Thank you again for such an amazing package!

Ever yours, Jake Ireland.

brandon-rhodes commented 4 years ago

Thanks for the encouraging statements about Skyfield! Could you should an example output that the script prints for you? Thanks!

jakewilliami commented 4 years ago

Thanks for your speedy response!

Absolutely:

>>> print('RA for ts.now():\t', ra1)
RA for ts.now():     22h 27m 40.62s
>>> print('RA for ts.utc(...):\t', ra2)
RA for ts.utc(...):  22h 25m 30.32s
>>>
brandon-rhodes commented 4 years ago

If you try printing the two times out, you'll find they differ by the number of hours in your timezone. The routine utc() expects Universal Time (roughly, Greenwich Time), but you are giving it hours/minutes/seconds in your local timezone. Try datetime.utcnow() and see if the result improves!

jakewilliami commented 4 years ago

Thanks for your response @brandon-rhodes. I'm sorry, but I'm not quite sure where to insert datetime.utcnow. If I replace ts.utc with ts.datetime.utcnow it returns "AttributeError: 'Timescale' object has no attribute 'datetime'".
Thanks again for your help here.

brandon-rhodes commented 4 years ago

Try replacing:

t1 = datetime.datetime.now()

with:

t1 = datetime.datetime.utcnow()

and see if the output improves.

jakewilliami commented 4 years ago

Ahh, I see. That does indeed work, thank you! So to clarify before we close the “issue”, datetime.datetime.now() lacks time zone information that datetime.datetime.utcnow()? Sorry to open an issue that wasn’t actually an issue. Hopefully this will help someone as naïve as myself in the future...

brandon-rhodes commented 4 years ago

Correct! The now() routine does not attach a timezone. I'm glad you have the date working correctly now in your script, and, yes, hopefully if anyone else is confused that datetime.now() does not return UTC, they will find this issue in a web search and learn about the difference.