Local solar time function from UTC and longitude

匿名 (未验证) 提交于 2019-12-03 01:02:01

问题:

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.

回答1:

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() 


回答2:

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) 

Example

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'))) 

Output

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 


回答3:

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() 


回答4:

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() 


回答5:

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)



标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!