UTC和经度的本地太阳时功能

时间:2012-11-09 19:27:17

标签: python astronomy

我想知道是否有一个python函数/模块在给定UTC时间和经度的情况下计算午夜(或当地太阳时)之后的本地时间?它不需要考虑夏令时。

提前致谢。

5 个答案:

答案 0 :(得分:9)

使用ephem的{​​{1}}方法:

sidereal_time()

注意: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 是一个浮点数,表示以弧度表示的角度,并以字符串形式转换为“hh:mm:ss.ff”。

为了比较,这里是“utc +经度”公式:

ephem.hours

实施例

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

答案 1 :(得分:6)

或者如果你想更短,你可以使用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 :(得分:2)

我看了一下Jean Meeus'天文算法。我想你可能会要求当地小时角度,可以用时间(0-24小时),度数(0-360)或弧度(0-2pi)表示。

我猜你可以用ephem做到这一点。但仅仅是为了它,这里有一些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 <= 2:
        yr -= 1
        mon += 12
    a = yr / 100
    b = 2 - a + a / 4
    jd = int(365.25 * (yr + 4716)) + int(30.6 * (mon + 1)) + day + b - 1524.5

    # get sidereal time at greenwich (AA ch12)
    t = (jd - 2451545.0) / 36525

    # Calculate mean equinox of date (degrees)
    l = 280.46646 + 36000.76983 * t + 0.0003032 * t**2
    while (l > 360):
        l -= 360
    while (l < 0):
        l += 360

    # Calculate mean anomoly of sun (degrees)
    m = 357.52911 + 35999.05029 * t - 0.0001537 * t**2

    # Calculate eccentricity of Earth's orbit
    e = 0.016708634 - 0.000042037 * t - 0.0000001267 * t**2

    # Calculate sun's equation of center (degrees)
    c = (1.914602 - 0.004817 * t - .000014 * t**2) * sin(m * DEG_TO_RAD) \
        + (0.019993 - .000101 * t) * sin(2 * m * DEG_TO_RAD) \
        + 0.000289 * sin(3 * m * DEG_TO_RAD)

    # Calculate the sun's radius vector (AU)
    o = l + c # sun's true longitude (degrees)
    v = m + c # sun's true anomoly (degrees)

    r = (1.000001018 * (1 - e**2)) / (1 + e * cos(v * DEG_TO_RAD))

    # Calculate right ascension & declination
    seconds = 21.448 - t * (46.8150 + t * (0.00059 - t * 0.001813))
    e0 = 23 + (26 + (seconds / 60)) / 60

    ra = atan2(cos(e0 * DEG_TO_RAD) * sin(o * DEG_TO_RAD), cos(o * DEG_TO_RAD)) # (radians)
    decl = asin(sin(e0 * DEG_TO_RAD) * sin(o * DEG_TO_RAD)) # (radians)

    return ra, decl

def hour_angle(dt, longit):
    # @input UTC time (datetime)
    # @input longitude (float, negative west of Greenwich)
    # @output hour angle, in degrees (float)

    # get gregorian time including fractional day
    y = dt.year
    m = dt.month
    d = dt.day + ((dt.second / 60.0 + dt.minute) / 60 + dt.hour) / 24.0 

    # get right ascention
    ra, _ = coords(y, m, d)

    # get julian day (AA ch7)
    if m <= 2:
        y -= 1
        m += 12
    a = y / 100
    b = 2 - a + a / 4
    jd = int(365.25 * (y + 4716)) + int(30.6 * (m + 1)) + d + b - 1524.5

    # get sidereal time at greenwich (AA ch12)
    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 / DEG_TO_RAD) % 360

    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])
    ha = hour_angle(dt, longit)
    # 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()

答案 3 :(得分:1)

使用ephem再次尝试。我将纬度和高程作为参数包括在内,但当然不需要它们。您可以为他们打电话给他们0

#!/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()

答案 4 :(得分:0)

一个非常简单的功能&amp;非常接近当地时间: 时间变化从-12h到+ 12h,经度从-180到180.然后:


import datetime as dt

def localTimeApprox(myDateTime, longitude):
   """Returns local hour approximation"""
   return myDateTime+dt.timedelta(hours=(longitude*12/180))

示例通话:localTimeApprox(dt.datetime(2014, 7, 9, 20, 00, 00), -75)

返回:datetime.datetime(2014, 7, 9, 15, 0)