python:SunMoonTimeCalculator

# encoding: utf-8
# 版权所有 2024 ©涂聚文有限公司
# 许可信息查看:
# 描述: https://github.com/Broham/suncalcPy
# Author    : geovindu,Geovin Du 涂聚文.
# IDE       : PyCharm 2023.1 python 3.11
# Datetime  : 2024/5/14 21:59
# User      : geovindu
# Product   : PyCharm
# Project   : EssentialAlgorithms
# File      : sunCalc.py
# explain   : 学习

import math
from datetime import datetime, timedelta
import time
import calendar

class SunMoonTimeCalculator(object):
    """
    日出日落,月升月落计算类

    """


    def __init__(self):
        """

        """
        self.PI = 3.141592653589793  # math.pi
        """
        派
        """
        self.sin = math.sin
        """
        sin 函数
        """
        self.cos = math.cos
        """
        函数
        """
        self.tan = math.tan
        """
        函数
        """
        self.asin = math.asin
        """
        函数
        """
        self.atan = math.atan2
        """
        函数
        """
        self.acos = math.acos
        """
        函数
        """
        self.rad = self.PI / 180.0
        self.e = self.rad * 23.4397  # obliquity of the Earth

        self.dayMs = 1000 * 60 * 60 * 24
        self.J1970 = 2440588
        self.J2000 = 2451545
        self.J0 = 0.0009

        self.times = [
            [-0.833, 'sunrise', 'sunset'],
            [-0.3, 'sunriseEnd', 'sunsetStart'],
            [-6, 'dawn', 'dusk'],
            [-12, 'nauticalDawn', 'nauticalDusk'],
            [-18, 'nightEnd', 'night'],
            [6, 'goldenHourEnd', 'goldenHour']
        ]


    def rightAscension(self,l, b):
        """

        :param l:
        :param b:
        :return:
        """
        return self.atan(self.sin(l) * self.cos(self.e) - self.tan(b) * self.sin(self.e), self.cos(l))


    def declination(self,l, b):
        """

        :param l:
        :param b:
        :return:
        """
        return self.asin(self.sin(b) * self.cos(self.e) + self.cos(b) * self.sin(self.e) * self.sin(l))


    def azimuth(self,H, phi, dec):
        """

        :param H:
        :param phi:
        :param dec:
        :return:
        """
        return self.atan(self.sin(H), self.cos(H) * self.sin(phi) - self.tan(dec) * self.cos(phi))


    def altitude(self,H, phi, dec):
        """

        :param H:
        :param phi:
        :param dec:
        :return:
        """
        return self.asin(self.sin(phi) * self.sin(dec) + self.cos(phi) * self.cos(dec) * self.cos(H))


    def siderealTime(self,d, lw):
        """

        :param d:
        :param lw:
        :return:
        """
        return self.rad * (280.16 + 360.9856235 * d) - lw


    def toJulian(self,date):
        """

        :param date:
        :return:
        """
        return (time.mktime(date.timetuple()) * 1000) / self.dayMs - 0.5 + self.J1970


    def fromJulian(self,j):
        """

        :param j:
        :return:
        """
        return datetime.fromtimestamp(((j + 0.5 - self.J1970) * self.dayMs) / 1000.0)


    def toDays(self,date):
        """

        :param date:
        :return:
        """
        return self.toJulian(date) - self.J2000


    def julianCycle(self,d, lw):
        """

        :param d:
        :param lw:
        :return:
        """
        return round(d - self.J0 - lw / (2 * self.PI))


    def approxTransit(self,Ht, lw, n):
        """

        :param Ht:
        :param lw:
        :param n:
        :return:
        """
        return self.J0 + (Ht + lw) / (2 * self.PI) + n


    def solarTransitJ(self,ds, M, L):
        """

        :param ds:
        :param M:
        :param L:
        :return:
        """
        return self.J2000 + ds + 0.0053 * self.sin(M) - 0.0069 * self.sin(2 * L)


    def hourAngle(self,h, phi, d):
        """

        :param h:
        :param phi:
        :param d:
        :return:
        """
        try:
            ret = self.acos((self.sin(h) - self.sin(phi) * self.sin(d)) / (self.cos(phi) * self.cos(d)))
            return ret
        except ValueError as e:
            print(h, phi, d, "=>", e)


    def observerAngle(self,height):
        """

        :param height:
        :return:
        """
        return -2.076 * math.sqrt(height) / 60


    def solarMeanAnomaly(self,d):
        """

        :param d:
        :return:
        """
        return self.rad * (357.5291 + 0.98560028 * d)


    def eclipticLongitude(self,M):
        """

        :param M:
        :return:
        """
        C = self.rad * (1.9148 * self.sin(M) + 0.02 * self.sin(2 * M) + 0.0003 * self.sin(3 * M))  # equation of center
        P = self.rad * 102.9372  # perihelion of the Earth
        return M + C + P + self.PI


    def sunCoords(self,d):
        """

        :param d:
        :return:
        """
        M = self.solarMeanAnomaly(d)
        L = self.eclipticLongitude(M)
        return dict(
            dec=self.declination(L, 0),
            ra=self.rightAscension(L, 0)
        )


    def getSetJ(self,h, lw, phi, dec, n, M, L):
        """

        :param h:
        :param lw:
        :param phi:
        :param dec:
        :param n:
        :param M:
        :param L:
        :return:
        """
        w = self.hourAngle(h, phi, dec)
        a = self.approxTransit(w, lw, n)
        return self.solarTransitJ(a, M, L)



    def moonCoords(self,d):
        """
        geocentric ecliptic coordinates of the moon
        :param d:
        :return:
        """
        L = self.rad * (218.316 + 13.176396 * d)
        M = self.rad * (134.963 + 13.064993 * d)
        F = self.rad * (93.272 + 13.229350 * d)

        l = L + self.rad * 6.289 * self.sin(M)
        b = self.rad * 5.128 * self.sin(F)
        dt = 385001 - 20905 * self.cos(M)

        return dict(
            ra=self.rightAscension(l, b),
            dec=self.declination(l, b),
            dist=dt
        )


    def getMoonIllumination(self,date):
        """
        Gets illumination properties of the moon for the given time.
        :param date:
        :return:
        """
        d = self.toDays(date)
        s = self.sunCoords(d)
        m = self.moonCoords(d)

        # distance from Earth to Sun in km
        sdist = 149598000
        phi = self.acos(self.sin(s["dec"]) * self.sin(m["dec"]) + self.cos(s["dec"]) * self.cos(m["dec"]) * self.cos(s["ra"] - m["ra"]))
        inc = self.atan(sdist * self.sin(phi), m["dist"] - sdist * self.cos(phi))
        angle = self.atan(self.cos(s["dec"]) * self.sin(s["ra"] - m["ra"]),
                     self.sin(s["dec"]) * self.cos(m["dec"]) - self.cos(s["dec"]) * self.sin(m["dec"]) * self.cos(s["ra"] - m["ra"]))

        return dict(
            fraction=(1 + self.cos(inc)) / 2,
            phase=0.5 + 0.5 * inc * (-1 if angle < 0 else 1) / self.PI,
            angle=angle
        )


    def getSunrise(self,date, lat, lng):
        """

        :param lat:
        :param lng:
        :return:
        """
        ret = self.getTimes(date, lat, lng)
        return ret["sunrise"]


    def getTimes(self,date, lat, lng, height=0):
        """
        Gets sun rise/set properties for the given time, location and height.
        :param date:
        :param lat:
        :param lng:
        :param height:
        :return:
        """
        lw = self.rad * -lng
        phi = self.rad * lat

        dh = self.observerAngle(height)

        d = self.toDays(date)
        n = self.julianCycle(d, lw)
        ds = self.approxTransit(0, lw, n)

        M = self.solarMeanAnomaly(ds)
        L = self.eclipticLongitude(M)
        dec = self.declination(L, 0)

        Jnoon = self.solarTransitJ(ds, M, L)

        result = dict(
            solarNoon=self.fromJulian(Jnoon).strftime('%Y-%m-%d %H:%M:%S'),
            nadir=self.fromJulian(Jnoon - 0.5).strftime('%Y-%m-%d %H:%M:%S')
        )

        for i in range(0, len(self.times)):
            time = self.times[i]
            h0 = (time[0] + dh) * self.rad

            Jset = self.getSetJ(h0, lw, phi, dec, n, M, L)
            Jrise = Jnoon - (Jset - Jnoon)
            result[time[1]] = self.fromJulian(Jrise).strftime('%Y-%m-%d %H:%M:%S')
            result[time[2]] = self.fromJulian(Jset).strftime('%Y-%m-%d %H:%M:%S')

        return result


    def hoursLater(self,date, h):
        """

        :param date:
        :param h:
        :return:
        """
        return date + timedelta(hours=h)


    def getMoonTimes(self,date, lat, lng):
        """

        :param date:
        :param lat:
        :param lng:
        :return:
        """
        """Gets moon rise/set properties for the given time and location."""

        t = date.replace(hour=0, minute=0, second=0)

        hc = 0.133 * self.rad
        h0 = self.getMoonPosition(t, lat, lng)["altitude"] - hc
        rise = 0
        sett = 0

        # go in 2-hour chunks, each time seeing if a 3-point quadratic curve crosses zero (which means rise or set)
        for i in range(1, 25, 2):
            h1 = self.getMoonPosition(self.hoursLater(t, i), lat, lng)["altitude"] - hc
            h2 = self.getMoonPosition(self.hoursLater(t, i + 1), lat, lng)["altitude"] - hc

            a = (h0 + h2) / 2 - h1
            b = (h2 - h0) / 2
            xe = -b / (2 * a)
            ye = (a * xe + b) * xe + h1
            d = b * b - 4 * a * h1
            roots = 0

            if d >= 0:
                dx = math.sqrt(d) / (abs(a) * 2)
                x1 = xe - dx
                x2 = xe + dx
                if abs(x1) <= 1:
                    roots += 1
                if abs(x2) <= 1:
                    roots += 1
                if x1 < -1:
                    x1 = x2

            if roots == 1:
                if h0 < 0:
                    rise = i + x1
                else:
                    sett = i + x1

            elif roots == 2:
                rise = i + (x2 if ye < 0 else x1)
                sett = i + (x1 if ye < 0 else x2)

            if (rise and sett):
                break

            h0 = h2

        result = dict()

        if (rise):
            result["rise"] = self.hoursLater(t, rise)
        if (sett):
            result["set"] = self.hoursLater(t, sett)

        if (not rise and not sett):
            value = 'alwaysUp' if ye > 0 else 'alwaysDown'
            result[value] = True

        return result


    def getMoonPosition(self,date, lat, lng):
        """
        Gets positional attributes of the moon for the given time and location.
        :param date:
        :param lat:
        :param lng:
        :return:
        """

        lw = self.rad * -lng
        phi = self.rad * lat
        d = self.toDays(date)

        c = self.moonCoords(d)
        H = self.siderealTime(d, lw) - c["ra"]
        h = self.altitude(H, phi, c["dec"])

        # altitude correction for refraction
        h = h + self.rad * 0.017 / self.tan(h + self.rad * 10.26 / (h + self.rad * 5.10))
        pa = self.atan(self.sin(H), self.tan(phi) * self.cos(c["dec"]) - self.sin(c["dec"]) * self.cos(H))

        return dict(
            azimuth=self.azimuth(H, phi, c["dec"]),
            altitude=h,
            distance=c["dist"],
            parallacticAngle=pa
        )


    def getPosition(self,date, lat, lng):
        """
        Returns positional attributes of the sun for the given time and location.
        :param date:
        :param lat:
        :param lng:
        :return:
        """
        lw = self.rad * -lng
        phi = self.rad * lat
        d = self.toDays(date)

        c = self.sunCoords(d)
        H = self.siderealTime(d, lw) - c["ra"]
        # print("d", d, "c",c,"H",H,"phi", phi)
        return dict(
            azimuth=self.azimuth(H, phi, c["dec"]),
            altitude=self.altitude(H, phi, c["dec"])
        )

调用:

#日出日落 深圳
sun=Common.sunCalc.SunMoonTimeCalculator()
lat= 22.5445741
lng= 114.0545429
print(sun.getTimes(datetime.now(),  lat, lng))
print(sun.getMoonIllumination(datetime.now()))
#月升月落
print(sun.getMoonTimes(datetime.now(), lat, lng))

输出:

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/629628.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

通过 AWS Glue 同步 MaxCompute 数据到 S3

1. 下载驱动 下载 3.3.6 版本的 driver wget https://github.com/aliyun/aliyun-odps-jdbc/releases/download/v3.3.6/odps-jdbc-3.3.6-jar-with-dependencies.jar将下载的jar包上传到 S3 指定目录下。(版本会影响方案的成功&#xff0c;4.x 以上版本验证是不可行的) 2. 在 …

二手手机行业商家如何利用二手机店erp进行破局?

在数字化和AI发展越发先进的的今天&#xff0c;二手手机市场正迎来前所未有的变革。途渡科技精心打造的超机购ERP管理软件&#xff0c;凭借其独特的智能化、高效化特点&#xff0c;正在引领这场变革&#xff0c;为二手手机商家提供全面、深度的数字化管理解决方案。二手手机商家…

谷歌广告账号被暂停是因为什么?防封点大全背好!

跨境出海业务少不了需要做Google Ads推广业务&#xff1b;其中让投手们闻风丧胆的消息就是帐户被暂停。当 Google 检测到任何违反其政策且可能损害用户在线体验的行为时&#xff0c;就会发生这种情况。那么如何在做广告推广的同时&#xff0c;保证账号不被封禁呢&#xff1f;看…

如何管理测试用例?测试用例有什么管理工具?YesDev

3.1 测试用例 测试用例(Test Case) 是指对一项特定的软件产品进行测试任务的描述&#xff0c;体现测试方案、方法、技术和策略。其内容包括测试目标、测试环境、输入数据、测试步骤、预期结果等。简单地认为&#xff0c;测试用例是为某个特殊目标而编制的一组测试输入、执行条…

Postman基础功能-前置脚本与接口关联

大家好&#xff0c;今天给大家分享一下关于 Postman 工具中的前置脚本与接口关联的使用&#xff0c;本文中汇大量用到关于变量的知识&#xff0c;前段时间给大家除了一篇文章分享&#xff0c;可以参考&#xff1a; Postman基础功能-变量设置与使用 一、前置脚本 介绍&#xf…

AI 写 SQL 真的靠谱吗?腾讯游戏在 AI+ 湖仓一体的实践

作者&#xff1a;腾讯游戏数据技术负责人 刘岩 导读 腾讯游戏是全球领先的游戏开发和运营商&#xff0c;其数据团队拥有十余年、700 款大型游戏的数据工作沉淀。复杂的业务环境下&#xff0c;腾讯游戏数据团队每年需要处理超过 3 万个数据提取需求&#xff0c;SQL 编写需要耗费…

.NET 4.8和.NET 8.0的区别和联系、以及查看本地计算机的.NET版本

文章目录 .NET 4.8和.NET 8.0的区别查看本地计算机的.NET版本 .NET 4.8和.NET 8.0的区别 .NET 8.0 和 .NET 4.8 之间的区别主要体现在它们的发展背景、目标平台、架构设计和功能特性上。下面是它们之间的一些主要区别&#xff1a; 发展背景&#xff1a; .NET 4.8 是.NET Fram…

单位内部防泄密策略与技术实践

在信息时代&#xff0c;企业内部数据安全至关重要&#xff0c;尤其是涉及核心竞争力的重要文件&#xff0c;员工的不当操作或恶意泄露都可能给企业带来重大损失。本文将从制度建设、技术防护、以及日常管理三个方面入手&#xff0c;探讨如何构建一套行之有效的内部防泄密体系&a…

20232803 2023-2024-2 《网络攻防实践》实践九报告

目录 1.实践内容2.实践过程2.1 手工修改可执行文件&#xff0c;改变程序执行流程&#xff0c;直接跳转到getShell函数2.2 利用foo函数的Bof漏洞&#xff0c;构造一个攻击输入字符串&#xff0c;覆盖返回地址&#xff0c;触发getShell函数2.3 注入一个自己制作的shellcode并运行…

微信小程序快速开发-基础内容(内容真的又多又干货)

目录 实现横向布局效果 实现滚动效果 实现轮播图效果 实现文本长按选中复制效果 渲染 HTML 标签 按钮组件的使用效果 图片组件的使用效果 Mustache 语法 动态绑定内容&#xff08;定义变量&#xff0c;渲染变量&#xff09; 动态绑定属性&#xff08;将属性定义为变量…

代码随想录算法训练营第二十九天 | 39. 组合总和、40.组合总和II、131.分割回文串

39. 组合总和 题目链接/文章讲解&#xff1a; 代码随想录 视频讲解&#xff1a;带你学透回溯算法-组合总和&#xff08;对应「leetcode」力扣题目&#xff1a;39.组合总和&#xff09;| 回溯法精讲&#xff01;_哔哩哔哩_bilibili 解题思路 这里和组合不同的是元素可以重复选取…

高质量新闻数据集OpenNewsArchive:880万篇主流新闻报道,国产大模型开源数据又添猛料

在构建国产大语言模型的道路上&#xff0c;高质量新闻是不可或缺的重要语料之一。这类语料集准确性、逻辑性、时效性于一体&#xff0c;同时包含丰富的事实知识&#xff0c;可以大幅提升模型的文本生成质量、词汇表达能力、事件理解分析能力以及时序内容的适应性和预测能力&…

[牛客网]——C语言刷题day3

答案&#xff1a;A 解析&#xff1a; A.表示将数组a的首地址赋值给指针变量p B.将一个int型变量直接赋值给一个int型的指针是不行的 C.道理同B D.j2是一个右值&#xff0c;右值是不能进行取地址操作的 #include <iostream> using namespace std;#define N 7 int fun…

Kafka应用Demo: 抽取消费者公共处理代码并利用redis实现多消费者实例负载分担

问题描述 在项目中使用消息中间件&#xff0c;主要为实现两个目的&#xff1a; 任务排队&#xff1a;当请求过多时&#xff0c;消费端无法同时处理&#xff0c;需要排队等待。这一点kafka采用的是"拉取消息"的模式&#xff0c;自然支持。负载分担: 这里的负载负担不…

网络安全|隐藏IP地址的5种不同方法

隐藏计算机的IP地址在互联网在线活动种可以保护个人隐私&#xff0c;这是在线活动的一种常见做法&#xff0c;包括隐私问题、安全性和访问限制内容等场景。那么如何做到呢?有很5种方法分享。每种方法都有自己的优点和缺点。 1. 虚拟网络 当您连接到虚拟服务器时&#xff0c;您…

Spring MVC(四) 数据校验

在开发过程中有一环必不可少的部分就是数据校验&#xff0c;用户在页面中填写的数据通过表单提交时&#xff0c;前端的JS可以做一些是否合法性的验证&#xff0c;比如是否为空、两次密码是否一致、格式是否正确等等验证。当数据到了后台控制器&#xff0c;为了确保程序的健壮性…

STM32--HC-SR501 热释电人体红外感应模块

实物引脚图&#xff1a; 模块工作特性&#xff1a; 当人进入感应范围之后输出引脚输出高电平&#xff0c;人离开感应范围自动延时输出低电平 热释电效应&#xff1a; 热释电传感器&#xff0c;也称为人体红外传感器&#xff0c;其工作原理基于热释电效应。这种传感器由几个关…

IDC:2023年中国IT安全软件市场同比增长4.7%

IDC最新发布的《中国IT安全软件市场跟踪报告&#xff0c;2023H2》显示&#xff0c;2023年下半年中国IT安全软件市场厂商整体收入约为169.8亿人民币&#xff08;约合23.5亿元美元&#xff09;&#xff0c;同比上升2.7%。结合全年数据&#xff0c;2023全年中国IT安全软件市场规模…

三路输出小功率开关电源【MATLAB/simulink】

拟选用一种DC-DC变换器拓扑使用1700 V SiC MOSFET或IGBT设计三相功率系 统的高频开关直流辅助电源&#xff0c;它可用于太阳能逆变器、工业开关电源、电动汽车充电器、 电机驱动装置等领域。&#xff08;建议采用单端反激式电路拓扑&#xff0c;开关频率为80kHz) 电路基本参数&…

项目管理—需求管理规程(软件研发过程标准,管理标准,标书技术编写,资质评审,安全管理体系,项目交付,实施运维,各类建设方案)

软件资料清单列表部分文档清单&#xff1a;工作安排任务书&#xff0c;可行性分析报告&#xff0c;立项申请审批表&#xff0c;产品需求规格说明书&#xff0c;需求调研计划&#xff0c;用户需求调查单&#xff0c;用户需求说明书&#xff0c;概要设计说明书&#xff0c;技术解…