I'm wondering if there is a python function/module that calculates the local time after midnight (or local solar time) given the UTC time and longitude? It doesn't need to take into account daylight saving time.
Thanks in advance.
I'm wondering if there is a python function/module that calculates the local time after midnight (or local solar time) given the UTC time and longitude? It doesn't need to take into account daylight saving time.
Thanks in advance.
Or if you want to go even shorter, you could use NOAA's low-accuracy equations:
#!/usr/local/bin/python import sys from datetime import datetime, time, timedelta from math import pi, cos, sin def solar_time(dt, longit): return ha def main(): if len(sys.argv) != 4: print 'Usage: hour_angle.py [YYYY/MM/DD] [HH:MM:SS] [longitude]' sys.exit() else: dt = datetime.strptime(sys.argv[1] + ' ' + sys.argv[2], '%Y/%m/%d %H:%M:%S') longit = float(sys.argv[3]) gamma = 2 * pi / 365 * (dt.timetuple().tm_yday - 1 + float(dt.hour - 12) / 24) eqtime = 229.18 * (0.000075 + 0.001868 * cos(gamma) - 0.032077 * sin(gamma) \ - 0.014615 * cos(2 * gamma) - 0.040849 * sin(2 * gamma)) decl = 0.006918 - 0.399912 * cos(gamma) + 0.070257 * sin(gamma) \ - 0.006758 * cos(2 * gamma) + 0.000907 * sin(2 * gamma) \ - 0.002697 * cos(3 * gamma) + 0.00148 * sin(3 * gamma) time_offset = eqtime + 4 * longit tst = dt.hour * 60 + dt.minute + dt.second / 60 + time_offset solar_time = datetime.combine(dt.date(), time(0)) + timedelta(minutes=tst) print solar_time if __name__ == '__main__': main()
Using ephem
's sidereal_time()
method:
import ephem # pip install pyephem (on Python 2) # pip install ephem (on Python 3) def solartime(observer, sun=ephem.Sun()): sun.compute(observer) # sidereal time == ra (right ascension) is the highest point (noon) hour_angle = observer.sidereal_time() - sun.ra return ephem.hours(hour_angle + ephem.hours('12:00')).norm # norm for 24h
Note: ephem.hours
is a float number that represents an angle in radians and converts to/from a string as "hh:mm:ss.ff".
For comparison, here's the "utc + longitude" formula:
import math from datetime import timedelta def ul_time(observer): utc_dt = observer.date.datetime() longitude = observer.long return utc_dt + timedelta(hours=longitude / math.pi * 12)
from datetime import datetime # "solar time" for some other cities for name in ['Los Angeles', 'New York', 'London', 'Paris', 'Moscow', 'Beijing', 'Tokyo']: city = ephem.city(name) print("%-11s %11s %s" % (name, solartime(city), ul_time(city).strftime('%T'))) # set date, longitude manually o = ephem.Observer() o.date = datetime(2012, 4, 15, 1, 0, 2) # some utc time o.long = '00:00:00.0' # longitude (you could also use a float (radians) here) print("%s %s" % (solartime(o), ul_time(o).strftime('%T')))
Los Angeles 14:59:34.11 14:44:30 New York 17:56:31.27 17:41:27 London 22:52:02.04 22:36:58 Paris 23:01:56.56 22:46:53 Moscow 1:23:00.33 01:07:57 Beijing 6:38:09.53 06:23:06 Tokyo 8:11:17.81 07:56:15 1:00:00.10 01:00:01
I took a look at Jean Meeus' Astronomical Algorithms. I think you might be asking for local hour angle, which can be expressed in time (0-24hr), degrees (0-360) or radians (0-2pi).
I'm guessing you can do this with ephem. But just for the heck of it, here's some python:
#!/usr/local/bin/python import sys from datetime import datetime, time, timedelta from math import pi, sin, cos, atan2, asin # helpful constant DEG_TO_RAD = pi / 180 # hardcode difference between Dynamical Time and Universal Time # delta_T = TD - UT # This comes from IERS Bulletin A # ftp://maia.usno.navy.mil/ser7/ser7.dat DELTA = 35.0 def coords(yr, mon, day): # @input year (int) # @input month (int) # @input day (float) # @output right ascention, in radians (float) # @output declination, in radians (float) # get julian day (AA ch7) day += DELTA / 60 / 60 / 24 # use dynamical time if mon 360): l -= 360 while (l 0.5: days -= 0.5 td = timedelta(days=days) # make solar time solar_time = datetime.combine(dt.date(), time(12)) + td print solar_time if __name__ == '__main__': main()
Trying again, with ephem. I included latitude and elevation as arguments, but they are not needed of course. You can just call them 0
for your purposes.
#!/usr/local/bin/python import sys from datetime import datetime, time, timedelta import ephem def hour_angle(dt, longit, latit, elev): obs = ephem.Observer() obs.date = dt.strftime('%Y/%m/%d %H:%M:%S') obs.lon = longit obs.lat = latit obs.elevation = elev sun = ephem.Sun() sun.compute(obs) # get right ascention ra = ephem.degrees(sun.g_ra) - 2 * ephem.pi # get sidereal time at greenwich (AA ch12) jd = ephem.julian_date(dt) t = (jd - 2451545.0) / 36525 theta = 280.46061837 + 360.98564736629 * (jd - 2451545) \ + .000387933 * t**2 - t**3 / 38710000 # hour angle (AA ch13) ha = (theta + longit - ra * 180 / ephem.pi) % 360 return ha def main(): if len(sys.argv) != 6: print 'Usage: hour_angle.py [YYYY/MM/DD] [HH:MM:SS] [longitude] [latitude] [elev]' sys.exit() else: dt = datetime.strptime(sys.argv[1] + ' ' + sys.argv[2], '%Y/%m/%d %H:%M:%S') longit = float(sys.argv[3]) latit = float(sys.argv[4]) elev = float(sys.argv[5]) # get hour angle ha = hour_angle(dt, longit, latit, elev) # convert hour angle to timedelta from noon days = ha / 360 if days > 0.5: days -= 0.5 td = timedelta(days=days) # make solar time solar_time = datetime.combine(dt.date(), time(12)) + td print solar_time if __name__ == '__main__': main()
For a very simple function & very very approximated local time: Time variation goes from -12h to +12h and longitude goes from -180 to 180. Then:
import datetime as dt def localTimeApprox(myDateTime, longitude): """Returns local hour approximation""" return myDateTime+dt.timedelta(hours=(longitude*12/180))
Sample calling: localTimeApprox(dt.datetime(2014, 7, 9, 20, 00, 00), -75)
Returns: datetime.datetime(2014, 7, 9, 15, 0)