使用.NET查询日出日落时间

net · 浏览次数 : 0

小编点评

**公式计算日出日落时间** ``` nautical_twilight_begin\": \"4:57:33 AM\", \"nautical_twilight_end\": \"7:49:30 PM\", \"astronomical_twilight_begin\": \"4:28:26 AM\", \"astronomical_twilight_end\": "8:18:37 PM" ``` **步骤:** 1. **获取经度和纬度信息**: - 从公式中,可以推断出: - **经度:100.225** - **纬度:35.3375** 2. **获取IP地址**: - 通过 IP2Location 服务获取地理位置信息,例如:IP地址为 120.236.111.205。 3. **根据IP地址获取城市信息**: - 通过 IP2Location 服务或其他数据库服务获取该 IP 地址的城市名称。 4. **根据城市名称获取经度和纬度**: - 通过 IP2Location 或其他数据库服务获取该城市对应的经度和纬度。 5. **计算日出日落时间**: - 可以使用任何日出日落计算公式,例如: - **当地时间:**2024 年 5 月 7 日下午 19 点 - **东经度:**113.2646 - **日出时间:**约 00:38:14 **注意:** - 以上公式使用的是的是地平经度,可能与实际经度有所不同。 - IP2Location 和 GeoIP2 服务可能需要付费才能获取地理位置信息。

正文

在WPF中,通过资源文件实现主题切换是个常见的功能,有不少文章介绍了如何实现手动切换主题。那如何实现自动切换主题呢?通常有两种机制:一是跟随系统明暗主题切换,二是像手机操作系统那样根据日出日落时间自动切换。本文将以终为始,采用倒推法一步步介绍如何使用.NET免费获取日出日落时间。

获取日出日落时间

日出日落时间会随季节及各地方经度纬度的不同而不同,此外还会受到大气折射等因素的影响。计算日出和日落时间通常需要考虑以下因素:

  • 日期:具体的年、月、日,用于确定太阳相对于地球的位置。
  • 经度:地理位置的经度,影响日出和日落的具体时刻。
  • 纬度:地理位置的纬度,影响日出和日落时间的早晚以及全年日照时间的长短。
  • 海拔:较高的海拔会影响大气折射,从而略微影响日出和日落时间。

获取日出日落时间可以使用在线API或者公式计算。最简单的方法就是付费API,其中有不少API提供免费试用(每天限额请求次数)。公式计算则不受网络限制,但准确度要低一点。

在线API

查询日出日落时间的在线API比较多,这里介绍一个无需注册,无需AccessKey的免费API
sunrise-sunset ,它是一个简单的RESTful API,只需要通过GET请求https://api.sunrise-sunset.org/json即可。最少只用提供经度和纬度参数。详细参数说明如下:

  • lat(float):十进制的纬度,例如22.5559。必要参数
  • lng(float):十进制的经度,例如114.0577。必要参数
  • date(string): YYYY-MM-DD格式的日期,也可以是其他的日期格式或者相对日期格式,默认值是当天。可选参数
  • callback (string):JSONP回调函数名称。可选参数
  • formatted (integer):0 or 1 (默认值是1)。值为0时,API响应结果中时间类型的值将按照 ISO 8601显示,并且昼长(day_length)以秒为单位显示。可选参数
  • tzid (string):时区标识符。例如:UTC,Asia/Shanghai。可用的时区标识符参见支持的时区列表,如果设置了该参数,响应结果中的时间将根据该参数中时区作为基准。默认是国际协调时间UTC。可选参数

以下是获取日出日落时间最基本参数的示例和响应结果:

https://api.sunrise-sunset.org/json?lat=23.1181&lng=113.2539

由于参数只提供了最基本的纬度和经度信息,响应结果默认是当天的日出日落信息,并且数据进行了默认的格式化,所有的时间都是以UTC作为基准且没有进行夏令时调整。

{
  "results": {
    "sunrise": "9:48:35 PM",
    "sunset": "10:58:28 AM",
    "solar_noon": "4:23:32 AM",
    "day_length": "13:09:53",
    "civil_twilight_begin": "9:25:53 PM",
    "civil_twilight_end": "11:21:10 AM",
    "nautical_twilight_begin": "8:57:33 PM",
    "nautical_twilight_end": "11:49:30 AM",
    "astronomical_twilight_begin": "8:28:26 PM",
    "astronomical_twilight_end": "12:18:37 PM"
  },
  "status": "OK",
  "tzid": "UTC"
}

以下是提供了时区参数的请求示例和响应结果:

https://api.sunrise-sunset.org/json?lat=23.1181&lng=113.2539&tzid=Asia/shanghai

响应结果中的时间都是以东八区作为基准:

{
  "results": {
    "sunrise": "5:48:35 AM",
    "sunset": "6:58:28 PM",
    "solar_noon": "12:23:32 PM",
    "day_length": "13:09:53",
    "civil_twilight_begin": "5:25:53 AM",
    "civil_twilight_end": "7:21:10 PM",
    "nautical_twilight_begin": "4:57:33 AM",
    "nautical_twilight_end": "7:49:30 PM",
    "astronomical_twilight_begin": "4:28:26 AM",
    "astronomical_twilight_end": "8:18:37 PM"
  },
  "status": "OK",
  "tzid": "Asia/shanghai"
}

公式计算日出日落时间

除了通过在线API获取日出日落时间,还可以通过天文算法计算,这些算法通常基于地球自转、公转、地球椭圆轨道、黄赤交角以及大气折射等因素。下边这个公式没有涉及大气折射因素,但依旧有较高的精度。

前边通过在线API获取的时间与多个付费API比较结果一致,姑且以在线API作为参照基准,此处公式计算结果偏差有几分钟。

计算机一般采用弧度制,公式为:

日出时间=(180+时区*15-经度-arccos(tan(10547π/81000*cos(2π*(日期+9)/365))*tan(纬度*π/180))*180/π)/15

日落时间=(180+时区*15-经度+arccos(tan(10547π/81000*cos(2π*(日期+9)/365))*tan(纬度*π/180))*180/π)/15

请注意,使用这些公式时应确保:

  • 日期:通常表示为距离当年1月1日的天数。(例如:1月1日表示日期=1,2月15日表示日期=46)
  • 时区:以小时为单位,东时区为正,西时区为负。(例如:我国时区为东八区,时区=8)
  • 经度、纬度:以度为单位,东经、北纬为正,西经、南纬为负。(例如:东经100º13′30″,北纬35º20′15″,则表示经度=100.225,纬度=35.3375;西经25º15′54″,南纬50º45′18″,则表示经度=-25.265,纬度=-50.755)

经度纬度查询

不管是在线API还是公式计算的方式获取日出日落时间,都需要输入经度纬度信息,直接获取经度纬度信息并不容易。但是,我们可以轻松地获取到另一个和地理位置有关的网络信息:IP地址。然后通过IP地址与地理位置的映射(包括经度纬度)得到想要的信息。通常可以通过在线API服务或者离线数据库完成IP地址到经度纬度信息地转换。

在线API服务

除了百度地图,还有许多其他提供IP到经纬度转换的服务,如 MaxMind GeoIP、IPinfo.io、IPGeolocation.io 等。这些服务通常提供免费和付费版本,使用方式类似,通常包括注册、获取API密钥、按照文档指示构造请求URL并解析响应。

使用本地数据库或API库

如果需要在本地处理大量IP到经纬度的转换,或者希望减少对外部API的依赖,可以考虑使用如IP2LocationGeoIP等提供的数据库产品。这些数据库包含了IP地址与地理位置信息的映射,可以直接在本地进行查询,无需每次请求都通过网络发送到第三方服务器。

IP2Location

IP2Location提供了付费的版本IP2Location和免费版本IP2Location Lite,他们的区别在于付费版本数据更多更准确,详细对比参见版本比较。IP2Location Lite提供了CSV和Bin两种格式的数据库,并根据数据丰富性分为多个不同的版本。这里以包含了国家、地区、城市、经度纬度、邮政编码、时区的DB11为例介绍如何使用。

首先,下载IP2LOCATION-LITE-DB11.BIN数据库文件,然后在项目中通过Nuget引用IP2Location.IPGeolocation包。调用代码如下:

Component oIP2Location = new Component();
IPResult oIPResult = new IPResult();
oIP2Location.Open(@"C:\Users\John\Downloads\IP2LOCATION-LITE-DB11.BIN");
oIPResult = oIP2Location.IPQuery("120.236.111.205");
if (oIPResult.Status == "OK")
{
    Console.WriteLine(oIPResult.Latitude); //23.12736
    Console.WriteLine(oIPResult.Longitude); //113.2646
    Console.WriteLine(oIPResult.CountryLong); //"China"
    Console.WriteLine(oIPResult.CountryShort); //"CN"
    Console.WriteLine(oIPResult.Region); //"Guangdong"
    Console.WriteLine(oIPResult.City);  //"Guangzhou"
    Console.WriteLine(oIPResult.TimeZone); //"+08:00"
    Console.WriteLine(oIPResult.ZipCode); //"510140"
}
oIP2Location.Close();

GeoIP

GeoIP也是提供了付费版本GeoIP2和免费版本GeoLite2,付费版本除了数据更多更准确,更新频率也更高一些。GeoLite2也是提供了CSV和mmdb两种格式数据库,并根据内容不同分为GeoLite2 CountryGeoLite2 CityGeoLite2 ASN三个版本,详细信息参见GeoLite2 IP元数据数据库对比。这里以GeoLite2 City.mmdb为例介绍如何使用。

首先,下载GeoLite2-City.mmdb数据库文件,然后在项目中通过Nuget引用MaxMind.GeoIP2包。调用代码如下:

using (var reader = new DatabaseReader(@"C:\Users\John\Downloads\GeoLite2-City.mmdb"))
{
    var city = reader.City("120.236.111.205");
    
    Console.WriteLine(city.Country.IsoCode); // "CN"
    Console.WriteLine(city.Country.Name); // "China"
    Console.WriteLine(city.Country.Names["zh-CN"]); // "中国"

    Console.WriteLine(city.MostSpecificSubdivision.Name); // null
    Console.WriteLine(city.MostSpecificSubdivision.IsoCode); // null

    Console.WriteLine(city.City.Name); // null

    Console.WriteLine(city.Postal.Code); // null

    Console.WriteLine(city.Location.Latitude); // 34.7732
    Console.WriteLine(city.Location.Longitude); // 113.722
}

不太幸运的是,这个IP并没有查询到城市信息,只返回了国家信息,因此结果中的经度纬度信息也不准确。国内所有未查询到城市信息的IP,返回都是这个经度纬度信息(通过百度地图查询到该坐标处于郑州)。但是GeoIP2的在线服务查询到了准确的城市及经度纬度信息。

最新(2024-5-7下载)的GeoLite2数据库中查询到20071个中国的IP网段,其中有11270条是未查询到具体城市信息的记录。

IP2Location Lite和GeoLite2数据库的覆盖情况并没有一个确切的数据,两个数据库结合使用或许能提高查询命中率。

获取公网IP

自己的公网IP非常容易获取,比如使用在线IP查询网站,或者搜索引擎中搜索关键词“IP”,搜索结果中通常会显示自己的公网IP地址。在程序中也可以通过特定API获取公网IP,比如下边这个API:

Get https://ipecho.net/plain

小结

在计算日出日落和经度纬度信息的环节都介绍了在线API服务和离线获取两种方式。在线API服务的优势是结果更准确,离线方式的优势是无需依赖第三方服务,缺点就是结果没那么精准。当然,在根据日出日落时间实现自动切换主题的需求上,准确度要求没那么高,离线计算方式足矣。

与使用.NET查询日出日落时间相似的内容:

使用.NET查询日出日落时间

在WPF中,通过资源文件实现主题切换是个常见的功能,有不少文章介绍了如何实现手动切换主题。那如何实现自动切换主题呢?通常有两种机制:一是跟随系统明暗主题切换,二是像手机操作系统那样根据日出日落时间自动切换。本文将以终为始,采用倒推法一步步介绍如何使用.NET免费获取日出日落时间。 获取日出日落时间

使用 OpenTelemetry 构建 .NET 应用可观测性(1):什么是可观测性

[TOC] # 什么是系统的可观测性(Observability) 对软件行业来说,可观测性(Observability)是一个舶来词,出自控制论(Control Theory)。 **可观测性是系统的一个属性**,它是指系统的状态能否被观测,也就是说,系统的状态能否被监控、收集、分析、查询、可视化

使用 SQL 的方式查询消息队列数据以及踩坑指南

![Pulsar-sql.png](https://s2.loli.net/2023/08/30/3iz9yqfuSCn18xk.png) # 背景 为了让业务团队可以更好的跟踪自己消息的生产和消费状态,需要一个类似于表格视图的消息列表,用户可以直观的看到发送的消息;同时点击详情后也能查到消息的整个

.NET 数据库大数据 方案(插入、更新、删除、查询 、插入或更新)

1、功能介绍 海量数据操作ORM性能瓶颈在实体转换上面,并且不能使用常规的Sql去实现 当列越多转换越慢,SqlSugar将转换性能做到极致,并且采用数据库最佳API 操作数据库达到极限性能,当然你如果不用sqlsugar了解一下原理也可以使用其他ORM实现 BulkCopy BulkCopy是一种

[转帖]图文结合带你搞懂 MySQL 日志之 Slow Query Log(慢查询日志)

https://my.oschina.net/GreatSQL/blog/5719211 GreatSQL 社区原创内容未经授权不得随意使用,转载请联系小编并注明来源。 GreatSQL 是 MySQL 的国产分支版本,使用上与 MySQL 一致。 作者:KAiTO 文章来源:GreatSQL 社区

Linq开发技巧与业务逻辑校验

Linq 是一种基于 .NET Framework 的编程语言,它的出现极大地提高了开发效率。Linq 提供了一种统一的查询语法,使得开发人员可以使用一种语言来查询不同类型的数据源,包括对象、集合、数据库等。这种语言非常直观和简洁,可以大大减少编写代码的时间和工作量。但是,随着业务逻辑的复杂性增加,

使用.NET源生成器(SG)实现一个自动注入的生成器

DI依赖注入对我们后端程序员来说肯定是基础中的基础了,我们经常会使用下面的代码注入相关的service services.AddScoped(); services.AddTransient<

[转帖]windows使用net user add用户并加入管理员,从而支持rdp远程登陆访问

C:\phpstudy_pro\WWW> net user test2 /add 命令成功完成。 C:\phpstudy_pro\WWW> net user test2 Huawei@123 命令成功完成。 C:\phpstudy_pro\WWW> net localgroup administra

Gin 框架是怎么使用 net http 包的(gin.go)

Gin 框架是基于 Go 语言的标准库 net/http 构建的,它使用 net/http 提供的基础功能来构建自己的高性能 Web 应用框架。 具体来说,Gin 使用 net/http 的以下方面: 1,HandlerFunc: Gin 使用 net/http 的 HandlerFunc 类型,这

【译】使用 .NET Aspire 和 Visual Studio 开发云原生应用

我们很高兴地宣布 .NET Aspire 发布,它扩展了 Visual Studio 在云原生应用程序开发方面的能力。.NET Aspire 提供了一个框架和工具,以一种独特的方式,使分布式 .NET 应用程序更容易构建、部署和管理。这种集成旨在使云原生应用程序的开发更加简单和高效。