Python: Weird behavior with signs of pytz timezones - python

I'm in Argentina, my time is GMT-3 (http://wwp.greenwichmeantime.com/time-zone/south-america/argentina/)
I was playing with Pytz and noticed something weird, take a look:
from pytz import timezone
bsas = timezone('America/Argentina/Buenos_Aires')
gmt_plus_3 = timezone('Etc/GMT+3')
gmt_min_3 = timezone('Etc/GMT-3')
# Date and time at this momement: 2012-07-26 10:23:01
fmt = '%Y-%m-%dT%H:%M:%S'
datetime.now(bs).strftime(fmt) #'2012-07-26T10:23:01' <-- GOOD!
datetime.now(gmt_min_3).strftime(fmt) #'2012-07-26T16:25:21' <-- WRONG!
datetime.now(gmt_plus_3).strftime(fmt) #'2012-07-26T10:23:01' <-- GOOD! WTF!
I'd expect:
GMT-3 should be 10:23:01 and gives me 16:23:01
GMT+3 should be 16:23:01 and gives me 10:23:01
Is this a bug? Am i doing it wrong??

It is not a bug, it is a feature (Wikipedia: Tz_database):
The special area of Etc is used for some administrative zones, particularly for "Etc/UTC" which represents Coordinated Universal Time. In order to conform with the POSIX style, those zone names beginning with "Etc/GMT" have their sign reversed from what most people expect. In this style, zones west of GMT have a positive sign and those east have a negative sign in their name (e.g "Etc/GMT-14" is 14 hours ahead/east of GMT.)

Related

Pyephem RA & DEC to GHA & DEC [duplicate]

I have been using python3 and pyephem to study celestial navigation
mostly working through some calculations that would have to be done by
hand in any case.
For the sight reduction part I am trying to have pyephem output data
comparable to the nautical almanac, mostly greenwich hour angle and declination.
To get the hour angle of the first point of aries, I tried adding a body using
ephem.readdb at 0.0 RA and 0.0 dec. But after reading the doc further I think
this is working.
#!/bin/python3
import math , ephem
# zero longitude
gmt_long = '0:0:0' # deg, min, sec
myloc_date = ( '2012/12/02 22:00:00' )
# observer for greenwich gst
utcz = ephem.Observer()
utcz.date = myloc_date
utcz.long = gmt_long
print ( utcz.date )
print (" gst hours", utcz.sidereal_time() )
print (" gst deg", ephem.degrees( utcz.sidereal_time() ) )
Compare the last line of output with the aries column in the nautical almanac
for the date
online version of nautical almanac www.tecepe.com.br
Yes, this does look to be the correct approach; each of your steps makes sense, and so the agreement between your result and the Almanac is meaningful. Here, for anyone else who wants to make the comparison, is the particular page from the Almanac that you reference:
http://www.tecepe.com.br/scripts/AlmanacPagesISAPI.dll/pages?date=12%2F02%2F2012

Pyephem elevation seems to be wrong

I'm trying to compute satellite positions using pyephem.
For most cases it seems to provide valid data. But for ~10% space-track's TLEs its results are wrong. For example:
tlelines = [
'0 SCOUT X-4 DEB',
'1 00722U 63053C 18107.73853716 .10519988 29718+0 80827-1 0 9998',
'2 00722 78.3737 228.3264 0048420 261.5483 98.0279 15.81271626581437'
]
sat = ephem.readtle(*tlelines)
now = ephem.now() # 43314.17601851852
sat.compute(now)
print sat.elevation # computed altitude, according to documentation
Result is 9.793773380577526e+18 which is definitely wrong. According to space-track apogee and perigee are 359 and 294 km.
What's wrong and how can I fix this computation?
PS. Python v.2, pyephem v.3.7.6.0
The problem appears to be that your coordinates are too old; satellite coordinates are generally only accurate for a couple of weeks to either side of the moment they're released. In this case:
print(sat._epoch)
the coordinates were 4 months old when you tried them out:
2018/4/17 17:43:30
If you try a value like now = '2018-04-18' I think you'll get a more reasonable number.

How to trim spaces within timestamps using 'm/d/yy' format

I have a Python script that generates .csv files from other data sources.
Currently, an error happens when the user manually adds a space to a date by accident. Instead of inputting the date as "1/13/17", a space may be added at the front (" 1/13/17") so that there's a space in front of the month.
I've included the relevant part of my Python script below:
def processDateStamp(sourceStamp):
matchObj = re.match(r'^(\d+)/(\d+)/(\d+)\s', sourceStamp)
(month, day, year) = (matchObj.group(1), matchObj.group(2), matchObj.group(3))
return "%s/%s/%s" % (month, day, year)
How do I trim the space issue in front of month and possibly on other components of the date (the day and year) as well for the future?
Thanks in advance.
Since you're dealing with dates, it might be more appropriate to use datetime.strptime than regex here. There are two advantages of this approach:
It makes it slightly clearer to anyone reading that you're trying to parse dates.
Your code will be more prone to throw exceptions when trying to parse data that doesn't represent dates, or represent dates in an incorrect format - this is good because it helps you catch and address issues that might otherwise go unnoticed.
Here's the code:
from datetime import datetime
def processDateStamp(sourceStamp):
date = datetime.strptime(sourceStamp.replace(' ', ''), '%M/%d/%y')
return '{}/{}/{}'.format(date.month, date.day, date.year)
if __name__ == '__main__':
print(processDateStamp('1/13/17')) # 1/13/17
print(processDateStamp(' 1/13/17')) # 1/13/17
print(processDateStamp(' 1 /13 /17')) # 1/13/17
You also can use parser from python-dateutil library. The main benefit you will get - it can recognize the datetime format for you (sometimes it may be useful):
from dateutil import parser
from datetime import datetime
def processDateTimeStamp(sourceStamp):
dt = parser.parse(sourceStamp)
return dt.strftime("%m/%d/%y")
processDateTimeStamp(" 1 /13 / 17") # returns 01/13/17
processDateTimeStamp(" jan / 13 / 17")
processDateTimeStamp(" 1 - 13 - 17")
processDateTimeStamp(" 1 .13 .17")
Once again, a perfect opportunity to use split, strip, and join:
def remove_spaces(date_string):
date_list = date_string.split('/')
result = '/'.join(x.strip() for x in date_list)
return result
Examples
In [7]: remove_spaces('1/13/17')
Out[7]: '1/13/17'
In [8]: remove_spaces(' 1/13/17')
Out[8]: '1/13/17'
In [9]: remove_spaces(' 1/ 13/17')
Out[9]: '1/13/17'

phephem: iss predictions not matching nasa website

I have been reading previous posts here but I still have a question. I am just making a very simple script to tell me when satellites are passing over my city.
I am using this blog post as a guide: http://libjoe.blogspot.com.au/2009/10/where-is-my-satellite-in-python.html
For testing, I am checking whether the output for the ISS station matches the predicted output on the nasa site but it doesn't match: http://spotthestation.nasa.gov/sightings/view.cfm?country=Australia&region=Victoria&city=Melbourne#.VLr7I82UdhE
I have my lat&long set for Melbourne, and I am using ephem.localtime when printing out the rise & set times. However, the times never match the nasa site.
Any advice would be greatly appreciated, thank you!
import datetime
import ephem
import math
import os
import sys
import time
import urllib2
observer = ephem.Observer()
observer.long = '-37.799423'
observer.lat = '144.999979'
observer.date = datetime.datetime.now()
tles = urllib2.urlopen('http://www.amsat.org/amsat/ftp/keps/current/nasabare.txt').readlines()
tles = [item.strip() for item in tles]
tles = [(tles[i],tles[i+1],tles[i+2]) for i in xrange(0,len(tles)-2,3)]
for tle in tles:
try:
sat = ephem.readtle(tle[0], tle[1], tle[2])
rt, ra, tt, ta, st, sa = observer.next_pass(sat)
if rt is not None and st is not None:
#observer.date = rt
sat.compute(observer)
print tle[0]
print 'rise time: ', ephem.localtime(rt)
print 'set time: ', ephem.localtime(st)
print
except ValueError as e:
print e
Here is the output of my script run now at "15:10" in Melbourne on 18th Jan 2015, where the ISS station is listed in the output as:
rise time: 2015-01-19 02:27:09
set time: 2015-01-19 02:37:37
However, the NASA site (spotthestation.nasa.gov/sightings/…) states the following predictions for Jan 19th:
Mon Jan 19, 9:23 PM and
Mon Jan 19, 10:59 PM
Typically, longitude is a “big number” between ±180° while latitude is a small number in the more limited range ±90° — is it possible that you have reversed the latitude and longitude here?
For people who end up here with the same problem. This is what resolved mine:
Read the documentation. Especially related to the timezones. Keep in mind that the default setting is UTC time and may be different than yours
Library is optimistic on the sighting predictions, therefore it may deviate from JSatTrak and online resources. In my case, library predicted a sighting for a pass fairly close to the observer, but yet on the boundary of the visibility. JSatTrak and online resources ignored it.
To see if that's the case in your sitauation, set the observer time at the end-time of the original prediction + 1 minute. The next pass will likely be the same as the online prediction. (I have a feeling that it might be related to the observer elevation, but I didn't do my homework on the source code or the calculations.)

Moon / Lunar Phase Algorithm

Does anyone know an algorithm to either calculate the moon phase or age on a given date or find the dates for new/full moons in a given year?
Googling tells me the answer is in some Astronomy book, but I don't really want to buy a whole book when I only need a single page.
Update:
I should have qualified my statement about googling a little better. I did find solutions that only worked over some subset of time (like the 1900's); and the trig based solutions that would be more computationally expensive than I'd like.
S Lott in his Python book has several algorithms for calculating Easter on a given year, most are less than ten lines of code and some work for all days in the Gregorian calendar. Finding the full moon in March is a key piece of finding Easter so I figured there should be an algorithm that doesn't require trig and works for all dates in the Gregorian calendar.
If you're like me, you try to be a careful programmer. So it makes you nervous when you see random code scattered across the internet that purports to solve a complex astronomical problem, but doesn't explain why the solution is correct.
You believe that there must be authoritative sources such as books which contain careful, and complete, solutions. For instance:
Meeus, Jean. Astronomical Algorithms. Richmond: Willmann-Bell, 1991. ISBN 0-943396-35-2.
Duffett-Smith, Peter. Practical Astronomy With Your Calculator. 3rd ed. Cambridge:
Cambridge University Press, 1981. ISBN 0-521-28411-2.
You place your trust in widely-used, well-tested, open source libraries which can have their errors corrected (unlike static web pages). Here then, is a Python solution to your question based on the PyEphem library, using the Phases of the Moon interface.
#!/usr/bin/python
import datetime
import ephem
from typing import List, Tuple
def get_phase_on_day(year: int, month: int, day: int):
"""Returns a floating-point number from 0-1. where 0=new, 0.5=full, 1=new"""
#Ephem stores its date numbers as floating points, which the following uses
#to conveniently extract the percent time between one new moon and the next
#This corresponds (somewhat roughly) to the phase of the moon.
#Use Year, Month, Day as arguments
date = ephem.Date(datetime.date(year,month,day))
nnm = ephem.next_new_moon(date)
pnm = ephem.previous_new_moon(date)
lunation = (date-pnm)/(nnm-pnm)
#Note that there is a ephem.Moon().phase() command, but this returns the
#percentage of the moon which is illuminated. This is not really what we want.
return lunation
def get_moons_in_year(year: int) -> List[Tuple[ephem.Date, str]]:
"""Returns a list of the full and new moons in a year. The list contains tuples
of either the form (DATE,'full') or the form (DATE,'new')"""
moons=[]
date=ephem.Date(datetime.date(year,1,1))
while date.datetime().year==year:
date=ephem.next_full_moon(date)
moons.append( (date,'full') )
date=ephem.Date(datetime.date(year,1,1))
while date.datetime().year==year:
date=ephem.next_new_moon(date)
moons.append( (date,'new') )
#Note that previous_first_quarter_moon() and previous_last_quarter_moon()
#are also methods
moons.sort(key=lambda x: x[0])
return moons
print(get_phase_on_day(2013,1,1))
print(get_moons_in_year(2013))
This returns
0.632652265318
[(2013/1/11 19:43:37, 'new'), (2013/1/27 04:38:22, 'full'), (2013/2/10 07:20:06, 'new'), (2013/2/25 20:26:03, 'full'), (2013/3/11 19:51:00, 'new'), (2013/3/27 09:27:18, 'full'), (2013/4/10 09:35:17, 'new'), (2013/4/25 19:57:06, 'full'), (2013/5/10 00:28:22, 'new'), (2013/5/25 04:24:55, 'full'), (2013/6/8 15:56:19, 'new'), (2013/6/23 11:32:15, 'full'), (2013/7/8 07:14:16, 'new'), (2013/7/22 18:15:31, 'full'), (2013/8/6 21:50:40, 'new'), (2013/8/21 01:44:35, 'full'), (2013/9/5 11:36:07, 'new'), (2013/9/19 11:12:49, 'full'), (2013/10/5 00:34:31, 'new'), (2013/10/18 23:37:39, 'full'), (2013/11/3 12:49:57, 'new'), (2013/11/17 15:15:44, 'full'), (2013/12/3 00:22:22, 'new'), (2013/12/17 09:28:05, 'full'), (2014/1/1 11:14:10, 'new'), (2014/1/16 04:52:10, 'full')]
I ported some code to Python for this a while back. I was going to just link to it, but it turns out that it fell off the web in the meantime, so I had to go dust it off and upload it again. See moon.py which is derived from John Walker's moontool.
I can't find a reference for this for what time spans it's accurate for either, but seems like the authors were pretty rigorous. Which means yes, it does use trig, but I can't imagine what the heck you would be using this for that would make it computationally prohibitive. Python function call overhead is probably more than the cost of the trig operations. Computers are pretty fast at computing.
The algorithms used in the code are drawn from the following sources:
Meeus, Jean. Astronomical Algorithms. Richmond: Willmann-Bell, 1991. ISBN 0-943396-35-2.
A must-have; if you only buy one book, make sure it's this one. Algorithms are presented mathematically, not as computer programs, but source code implementing many of the algorithms in the book can be ordered separately from the publisher in either QuickBasic, Turbo Pascal, or C. Meeus provides many worked examples of calculations which are essential to debugging your code, and frequently presents several algorithms with different tradeoffs among accuracy, speed, complexity, and long-term (century and millennia) validity.
Duffett-Smith, Peter. Practical Astronomy With Your Calculator. 3rd ed. Cambridge: Cambridge University Press, 1981. ISBN 0-521-28411-2.
Despite the word Calculator in the title; this is a valuable reference if you're interested in developing software which calculates planetary positions, orbits, eclipses, and the like. More background information is given than in Meeus, which helps those not already versed in astronomy learn the often-confusing terminology. The algorithms given are simpler and less accurate than those provided by Meeus, but are suitable for most practical work.
I think you searched on wrong google:
http://home.att.net/~srschmitt/zenosamples/zs_lunarphasecalc.html
http://www.voidware.com/moon_phase.htm
http://www.ben-daglish.net/moon.shtml
http://www.faqs.org/faqs/astronomy/faq/part3/section-15.html
Also, pyephem — scientific-grade astronomy routines [PyPI], which is a Python package but has the computational guts in C, and that does say
Precision < 0.05" from -1369 to +2950.
Uses table lookup techniques to limit calls to trigonometric functions.
PyEphem is now deprecating - they recommend preferring Skyfield astronomy library over PyEphem for new projects. Its modern design encourages better Python code, and uses NumPy to accelerate its calculations.
The phase of the Moon is defined as the angle between the Moon and the
Sun along the ecliptic. This angle is computed as the difference in
the ecliptic longitude of the Moon and of the Sun.
The result is an angle that is 0° for the New Moon, 90° at the First Quarter, 180° at the Full Moon, and 270° at the Last Quarter.
Code taken from here
from skyfield.api import load
from skyfield.framelib import ecliptic_frame
ts = load.timescale()
t = ts.utc(2019, 12, 9, 15, 36)
eph = load('de421.bsp')
sun, moon, earth = eph['sun'], eph['moon'], eph['earth']
e = earth.at(t)
_, slon, _ = e.observe(sun).apparent().frame_latlon(ecliptic_frame)
_, mlon, _ = e.observe(moon).apparent().frame_latlon(ecliptic_frame)
phase = (mlon.degrees - slon.degrees) % 360.0
print('{0:.1f}'.format(phase))
Output
149.4
Pyephem by default uses coordinated universal (UTC) time. I wanted a program that would generate a list of full moons that would be accurate in the pacific time zone. The code below will calculate the full moons for a given year and then adjust that using the ephem.localtime() method to calibrate to the desired time zone. It also appears to properly account for daylight savings time as well. Thank you to Richard, this code is similar to what he had written.
#!/usr/bin/python
import datetime
import ephem
import os
import time
# Set time zone to pacific
os.environ['TZ'] = 'US/Pacific'
time.tzset()
print("Time zone calibrated to", os.environ['TZ'])
def get_full_moons_in_year(year):
"""
Generate a list of full moons for a given year calibrated to the local time zone
:param year: year to determine the list of full moons
:return: list of dates as strings in the format YYYY-mm-dd
"""
moons = []
date = ephem.Date(datetime.date(year - 1, 12, 31))
end_date = ephem.Date(datetime.date(year + 1, 1, 1))
while date <= end_date:
date = ephem.next_full_moon(date)
# Convert the moon dates to the local time zone, add to list if moon date still falls in desired year
local_date = ephem.localtime(date)
if local_date.year == year:
# Append the date as a string to the list for easier comparison later
moons.append(local_date.strftime("%Y-%m-%d"))
return moons
moons = get_full_moons_in_year(2015)
print(moons)
The code above will return:
Time zone calibrated to US/Pacific
['2015-01-04', '2015-02-03', '2015-03-05', '2015-04-04', '2015-05-03', '2015-06-02', '2015-07-01', '2015-07-31', '2015-08-29', '2015-09-27', '2015-10-27', '2015-11-25', '2015-12-25']
I know that you're looking for Python but if you can understand C# there's an open source project out there called Chronos XP which does this very well.
If you don't need high accuracy, you can always (ab)use a lunar (or lunisolar) calendar class (e.g., HijriCalendar or ChineseLunisolarCalendar in Microsoft .NET) to calculate the (approximate) moon phase of any date, as the calendar's "day-of-month" property, being a lunar (or lunisolar) calendar day, always corresponds to the moon phase (e.g., day 1 is the new moon, day 15 is the full moon, etc.)

Categories