一个现成代码的公共类库,复制下来作为一个类文件就可以调用了。一般不需要了解实现过程,各种数学公式太麻烦。

调用方法:

  1. SunTimeResult result = SunTimes.GetSunTime(DateTime.Now, double.Parse(Longitude), double.Parse(Latitude));
  2. MessageBox.Show(string.Format("今天日出时间:{0},日落时间:{1}", result.SunriseTime.ToString("HH:mm:ss"), result.SunsetTime.ToString("HH:mm:ss")));

  

  1. DateTime.Now是现在的时间
  1. Longitude是经度
  1. Latitude是纬度

类库代码如下:

  1. using System;
  2.  
  3. namespace SwitchTime
  4. {
  5. /// <summary>
  6. /// 日出日落时间类
  7. /// </summary>
  8. public static class SunTimes
  9. {
  10. #region 公共方法
  11. /// <summary>
  12. /// 计算日长
  13. /// </summary>
  14. /// <param name="date">日期</param>
  15. /// <param name="longitude">经度</param>
  16. /// <param name="latitude">纬度</param>
  17. /// <returns>日长</returns>
  18. /// <remarks>
  19. /// 注:日期最小为2000.1.1号
  20. /// </remarks>
  21. public static double GetDayLength(DateTime date, double longitude, double latitude)
  22. {
  23. double result = DayLen(date.Year, date.Month, date.Day, longitude, latitude, -35.0 / 60.0, 1);
  24. return result;
  25. }
  26.  
  27. /// <summary>
  28. /// 计算日出日没时间
  29. /// </summary>
  30. /// <param name="date">日期</param>
  31. /// <param name="longitude">经度</param>
  32. /// <param name="latitude">纬度</param>
  33. /// <returns>日落日出时间</returns>
  34. /// <remarks>
  35. /// 注:日期最小为2000.1.1号
  36. /// </remarks>
  37. public static SunTimeResult GetSunTime(DateTime date, double longitude, double latitude)
  38. {
  39. double start = 0;
  40. double end = 0;
  41. SunRiset(date.Year, date.Month, date.Day, longitude, latitude, -35.0 / 60.0, 1, ref start, ref end);
  42. DateTime sunrise = ToLocalTime(date, start);
  43. DateTime sunset = ToLocalTime(date, end);
  44. return new SunTimeResult(sunrise, sunset);
  45. }
  46. #endregion
  47.  
  48. #region 私有方法
  49.  
  50. #region 时间转换
  51. private static DateTime ToLocalTime(DateTime time, double utTime)
  52. {
  53. int hour = Convert.ToInt32(Math.Floor(utTime));
  54. double temp = utTime - hour;
  55. hour += 8;//转换为东8区北京时间
  56. temp = temp * 60;
  57. int minute = Convert.ToInt32(Math.Floor(temp));
  58. try
  59. {
  60. return new DateTime(time.Year, time.Month, time.Day, hour, minute, 0);
  61. }
  62. catch
  63. {
  64. return new DateTime(time.Year, time.Month, time.Day, 0, 0, 0);
  65. }
  66. }
  67. #endregion
  68.  
  69. #region 与日出日落时间相关计算
  70. private static double DayLen(int year, int month, int day, double lon, double lat,
  71. double altit, int upper_limb)
  72. {
  73. double d, /* Days since 2000 Jan 0.0 (negative before) */
  74. obl_ecl, /* Obliquity (inclination) of Earth's axis */
  75. //黄赤交角,在2000.0历元下国际规定为23度26分21.448秒,但有很小的时间演化。
  76.  
  77. sr, /* Solar distance, astronomical units */
  78. slon, /* True solar longitude */
  79. sin_sdecl, /* Sine of Sun's declination */
  80. //太阳赤纬的正弦值。
  81. cos_sdecl, /* Cosine of Sun's declination */
  82. sradius, /* Sun's apparent radius */
  83. t; /* Diurnal arc */
  84.  
  85. /* Compute d of 12h local mean solar time */
  86. d = Days_since_2000_Jan_0(year, month, day) + 0.5 - lon / 360.0;
  87.  
  88. /* Compute obliquity of ecliptic (inclination of Earth's axis) */
  89. obl_ecl = 23.4393 - 3.563E-7 * d;
  90. //这个黄赤交角时变公式来历复杂,很大程度是经验性的,不必追究。
  91.  
  92. /* Compute Sun's position */
  93. slon = 0.0;
  94. sr = 0.0;
  95. Sunpos(d, ref slon, ref sr);
  96.  
  97. /* Compute sine and cosine of Sun's declination */
  98. sin_sdecl = Sind(obl_ecl) * Sind(slon);
  99. cos_sdecl = Math.Sqrt(1.0 - sin_sdecl * sin_sdecl);
  100. //用球面三角学公式计算太阳赤纬。
  101.  
  102. /* Compute the Sun's apparent radius, degrees */
  103. sradius = 0.2666 / sr;
  104. //视半径,同前。
  105.  
  106. /* Do correction to upper limb, if necessary */
  107. if (upper_limb != 0)
  108. altit -= sradius;
  109.  
  110. /* Compute the diurnal arc that the Sun traverses to reach */
  111. /* the specified altitide altit: */
  112. //根据设定的地平高度判据计算周日弧长。
  113. double cost;
  114. cost = (Sind(altit) - Sind(lat) * sin_sdecl) /
  115. (Cosd(lat) * cos_sdecl);
  116. if (cost >= 1.0)
  117. t = 0.0; /* Sun always below altit */
  118. //极夜。
  119. else if (cost <= -1.0)
  120. t = 24.0; /* Sun always above altit */
  121. //极昼。
  122. else t = (2.0 / 15.0) * Acosd(cost); /* The diurnal arc, hours */
  123. //周日弧换算成小时计。
  124. return t;
  125.  
  126. }
  127.  
  128. private static void Sunpos(double d, ref double lon, ref double r)
  129. {
  130. double M,//太阳的平均近点角,从太阳观察到的地球(=从地球看到太阳的)距近日点(近地点)的角度。
  131. w, //近日点的平均黄道经度。
  132. e, //地球椭圆公转轨道离心率。
  133. E, //太阳的偏近点角。计算公式见下面。
  134.  
  135. x, y,
  136. v; //真近点角,太阳在任意时刻的真实近点角。
  137.  
  138. M = Revolution(356.0470 + 0.9856002585 * d);//自变量的组成:2000.0时刻太阳黄经为356.0470度,此后每天约推进一度(360度/365天
  139. w = 282.9404 + 4.70935E-5 * d;//近日点的平均黄经。
  140.  
  141. e = 0.016709 - 1.151E-9 * d;//地球公转椭圆轨道离心率的时间演化。以上公式和黄赤交角公式一样,不必深究。
  142.  
  143. E = M + e * Radge * Sind(M) * (1.0 + e * Cosd(M));
  144. x = Cosd(E) - e;
  145. y = Math.Sqrt(1.0 - e * e) * Sind(E);
  146. r = Math.Sqrt(x * x + y * y);
  147. v = Atan2d(y, x);
  148. lon = v + w;
  149. if (lon >= 360.0)
  150. lon -= 360.0;
  151. }
  152.  
  153. private static void Sun_RA_dec(double d, ref double RA, ref double dec, ref double r)
  154. {
  155. double lon, obl_ecl, x, y, z;
  156. lon = 0.0;
  157.  
  158. Sunpos(d, ref lon, ref r);
  159. //计算太阳的黄道坐标。
  160.  
  161. x = r * Cosd(lon);
  162. y = r * Sind(lon);
  163. //计算太阳的直角坐标。
  164.  
  165. obl_ecl = 23.4393 - 3.563E-7 * d;
  166. //黄赤交角,同前。
  167.  
  168. z = y * Sind(obl_ecl);
  169. y = y * Cosd(obl_ecl);
  170. //把太阳的黄道坐标转换成赤道坐标(暂改用直角坐标)。
  171.  
  172. RA = Atan2d(y, x);
  173. dec = Atan2d(z, Math.Sqrt(x * x + y * y));
  174. //最后转成赤道坐标。显然太阳的位置是由黄道坐标方便地直接确定的,但必须转换到赤
  175. //道坐标里才能结合地球的自转确定我们需要的白昼长度。
  176.  
  177. }
  178. /// <summary>
  179. /// 日出没时刻计算
  180. /// </summary>
  181. /// <param name="year">年</param>
  182. /// <param name="month">月</param>
  183. /// <param name="day">日</param>
  184. /// <param name="lon"></param>
  185. /// <param name="lat"></param>
  186. /// <param name="altit"></param>
  187. /// <param name="upper_limb"></param>
  188. /// <param name="trise">日出时刻</param>
  189. /// <param name="tset">日没时刻</param>
  190. /// <returns>太阳有出没现象,返回0 极昼,返回+1 极夜,返回-1</returns>
  191. private static int SunRiset(int year, int month, int day, double lon, double lat,
  192. double altit, int upper_limb, ref double trise, ref double tset)
  193. {
  194. double d, /* Days since 2000 Jan 0.0 (negative before) */
  195. //以历元2000.0起算的日数。
  196.  
  197. sr, /* Solar distance, astronomical units */
  198. //太阳距离,以天文单位计算(约1.5亿公里)。
  199.  
  200. sRA, /* Sun's Right Ascension */
  201. //同前,太阳赤经。
  202.  
  203. sdec, /* Sun's declination */
  204. //太阳赤纬。
  205.  
  206. sradius, /* Sun's apparent radius */
  207. //太阳视半径,约16分(受日地距离、大气折射等诸多影响)
  208.  
  209. t, /* Diurnal arc */
  210. //周日弧,太阳一天在天上走过的弧长。
  211.  
  212. tsouth, /* Time when Sun is at south */
  213. sidtime; /* Local sidereal time */
  214. //当地恒星时,即地球的真实自转周期。比平均太阳日(日常时间)长3分56秒。
  215.  
  216. int rc = 0; /* Return cde from function - usually 0 */
  217.  
  218. /* Compute d of 12h local mean solar time */
  219. d = Days_since_2000_Jan_0(year, month, day) + 0.5 - lon / 360.0;
  220. //计算观测地当日中午时刻对应2000.0起算的日数。
  221.  
  222. /* Compute local sideral time of this moment */
  223. sidtime = Revolution(GMST0(d) + 180.0 + lon);
  224. //计算同时刻的当地恒星时(以角度为单位)。以格林尼治为基准,用经度差校正。
  225.  
  226. /* Compute Sun's RA + Decl at this moment */
  227. sRA = 0.0;
  228. sdec = 0.0;
  229. sr = 0.0;
  230. Sun_RA_dec(d, ref sRA, ref sdec, ref sr);
  231. //计算同时刻太阳赤经赤纬。
  232.  
  233. /* Compute time when Sun is at south - in hours UT */
  234. tsouth = 12.0 - Rev180(sidtime - sRA) / 15.0;
  235. //计算太阳日的正午时刻,以世界时(格林尼治平太阳时)的小时计。
  236.  
  237. /* Compute the Sun's apparent radius, degrees */
  238. sradius = 0.2666 / sr;
  239. //太阳视半径。0.2666是一天文单位处的太阳视半径(角度)。
  240.  
  241. /* Do correction to upper limb, if necessary */
  242. if (upper_limb != 0)
  243. altit -= sradius;
  244. //如果要用上边缘,就要扣除一个视半径。
  245.  
  246. /* Compute the diurnal arc that the Sun traverses to reach */
  247. //计算周日弧。直接利用球面三角公式。如果碰到极昼极夜问题,同前处理。
  248. /* the specified altitide altit: */
  249.  
  250. double cost;
  251. cost = (Sind(altit) - Sind(lat) * Sind(sdec)) /
  252. (Cosd(lat) * Cosd(sdec));
  253. if (cost >= 1.0)
  254. {
  255. rc = -1;
  256. t = 0.0;
  257. }
  258. else
  259. {
  260. if (cost <= -1.0)
  261. {
  262. rc = +1;
  263. t = 12.0; /* Sun always above altit */
  264. }
  265. else
  266. t = Acosd(cost) / 15.0; /* The diurnal arc, hours */
  267. }
  268.  
  269. /* Store rise and set times - in hours UT */
  270. trise = tsouth - t;
  271. tset = tsouth + t;
  272.  
  273. return rc;
  274. }
  275. #endregion
  276.  
  277. #region 辅助函数
  278. /// <summary>
  279. /// 历元2000.0,即以2000年第一天开端为计日起始(天文学以第一天为0日而非1日)。
  280. /// 它与UT(就是世界时,格林尼治平均太阳时)1999年末重合。
  281. /// </summary>
  282. /// <param name="y"></param>
  283. /// <param name="m"></param>
  284. /// <param name="d"></param>
  285. /// <returns></returns>
  286. private static long Days_since_2000_Jan_0(int y, int m, int d)
  287. {
  288. return (367L * (y) - ((7 * ((y) + (((m) + 9) / 12))) / 4) + ((275 * (m)) / 9) + (d) - 730530L);
  289. }
  290.  
  291. private static double Revolution(double x)
  292. {
  293. return (x - 360.0 * Math.Floor(x * Inv360));
  294. }
  295.  
  296. private static double Rev180(double x)
  297. {
  298. return (x - 360.0 * Math.Floor(x * Inv360 + 0.5));
  299. }
  300.  
  301. private static double GMST0(double d)
  302. {
  303. double sidtim0;
  304. sidtim0 = Revolution((180.0 + 356.0470 + 282.9404) +
  305. (0.9856002585 + 4.70935E-5) * d);
  306. return sidtim0;
  307. }
  308.  
  309. private static double Inv360 = 1.0 / 360.0;
  310. #endregion
  311.  
  312. #region 度与弧度转换系数,为球面三角计算作准备
  313. private static double Sind(double x)
  314. {
  315. return Math.Sin(x * Degrad);
  316. }
  317.  
  318. private static double Cosd(double x)
  319. {
  320. return Math.Cos(x * Degrad);
  321. }
  322.  
  323. private static double Tand(double x)
  324. {
  325. return Math.Tan(x * Degrad);
  326.  
  327. }
  328.  
  329. private static double Atand(double x)
  330. {
  331. return Radge * Math.Atan(x);
  332. }
  333.  
  334. private static double Asind(double x)
  335. {
  336. return Radge * Math.Asin(x);
  337. }
  338.  
  339. private static double Acosd(double x)
  340. {
  341. return Radge * Math.Acos(x);
  342. }
  343.  
  344. private static double Atan2d(double y, double x)
  345. {
  346. return Radge * Math.Atan2(y, x);
  347.  
  348. }
  349.  
  350. private static double Radge = 180.0 / Math.PI;
  351. private static double Degrad = Math.PI / 180.0;
  352.  
  353. #endregion
  354.  
  355. #endregion
  356. }
  357.  
  358. /// <summary>
  359. /// 日出日落时间结果
  360. /// </summary>
  361. public class SunTimeResult
  362. {
  363. #region 构造与析构
  364. /// <summary>
  365. /// 构造函数
  366. /// </summary>
  367. /// <param name="sunrise">日出时间</param>
  368. /// <param name="sunset">日落时间</param>
  369. public SunTimeResult(DateTime sunrise, DateTime sunset)
  370. {
  371. sunriseTime = sunrise;
  372. sunsetTime = sunset;
  373. }
  374. #endregion
  375.  
  376. #region 属性定义
  377. /// <summary>
  378. /// 获取日出时间
  379. /// </summary>
  380. public DateTime SunriseTime
  381. {
  382. get
  383. {
  384. return sunriseTime;
  385. }
  386. }
  387.  
  388. /// <summary>
  389. /// 获取日落时间
  390. /// </summary>
  391. public DateTime SunsetTime
  392. {
  393. get
  394. {
  395. return sunsetTime;
  396. }
  397. }
  398. #endregion
  399.  
  400. #region 私成员
  401. private DateTime sunriseTime;//日出时间
  402. private DateTime sunsetTime;//日落时间
  403. #endregion
  404. }
  405. }

  

C#可用的日出日落时间类的更多相关文章

  1. java时间类简单总结

    java时间类(Data类) 1.Data类(没有考虑到国际化,好多方法已过时java.util.Data包中) 父类(是类不是接口含有直接子类3个):  日期格式为:年月日时分秒(不包含毫秒部分) ...

  2. java最全时间类及用法

    对于时间类,这篇主要说明各种现实情况下如何取值,怎么定向取值,得到自己想要的时间参数.在java中时间类主要有Date.Calendar,暂时只介绍 java.util.*下的时间类,对于java.s ...

  3. java时间类Date、Calendar及用法

    对于时间类,这篇主要说明各种现实情况下如何取值,怎么定向取值,得到自己想要的时间参数.在java中时间类主要有Date.Calendar,暂时只介绍 java.util.*下的时间类,对于java.s ...

  4. Java日期时间API系列3-----Jdk7及以前的日期时间类的不方便使用问题

    使用Java日期时间类,每个人都很熟悉每个项目中必不可少的工具类就是dateutil,包含各种日期计算,格式化等处理,而且常常会遇到找不到可用的处理方法,需要自己新增方法,处理过程很复杂. 1.Dat ...

  5. Java 之 JDK1.8之前日期时间类

    一.JDK1.8之前日期时间类 二. java.lang.System类 System类提供的public static long currentTimeMillis()用来返回当前时间与1970年1 ...

  6. java新时间类

    时间 java8以前使用的时间很多方法都已经废弃了,而且不是线程安全的,java8提供了一系列的时间类,这些时间类都是线程安全的 LocalDate.LocalTime.LocalDateTime 这 ...

  7. Java中六大时间类的使用和区别

    关于java中六个时间类的使用和区别 java.util.Date java.sql.Date  java.sql.Time  java.sql.Timestamp java.text.SimpleD ...

  8. iOS--时间类date详解

    NSDate定义时间的类 NSDate是一个时间类,在编写程序时,我们很少遇到.今天我突然碰到,感觉很生疏. 给大家发个博客,让大家也都温习一下,哈哈! 兄弟用的时候突然发现竟然有一些bug,大家用时 ...

  9. 3 EventTime 事件时间类和TimeNow函数——Live555源码阅读(一)基本组件类

    这是Live555源码阅读的第一部分,包括了时间类,延时队列类,处理程序描述类,哈希表类这四个大类. 这里是时间相关类的第三个部分,也是最后一个部分. EventTime 事件时间类 这个类和Dela ...

随机推荐

  1. Android开发案例 - 自定义虚拟键盘

    所有包含IM功能的App(如微信, 微博, QQ, 支付宝等)都提供了Emoji表情之类的虚拟键盘,  如下图:    本文只着重介绍如何实现输入法键盘和自定义虚拟键盘的流畅切换, 而不介绍如何实现虚 ...

  2. NSURLConnection学习笔记

    虽说现在都用三方库来获取网络数据,再不济也会用苹果官方的NSURLSession,但有些东西还是要先学会才有资格说不好不用,不是么? NSURLConnection发送请求是分为同步和异步两种方式的, ...

  3. js异步加载的3种方式(转载)

    1.defer标签 只支持IE    defer属性的定义和用法: 属性规定是否对脚本执行进行延迟,直到页面加载为止.有的 javascript 脚本 document.write 方法来创建当前的文 ...

  4. Windows环境下的NodeJS+NPM+Bower安装配置

    npm作为一个NodeJS的模块管理,之前我由于没有系统地看资料所以导致安装配置模块的时候走了一大段弯路,所以现在很有必要列出来记录下.我们要先配置npm的全局模块的存放路径以及cache的路径,例如 ...

  5. 异常处理之“The remote certificate is invalid according to the validation praocedure.”

    参考文章:http://brainof-dave.blogspot.com.au/2008/08/remote-certificate-is-invalid-according.html 参考文章:h ...

  6. MYSQL 导入Excel数据到数据库中

    1,先把excel的数据整理整齐,如每列都要保持同样的格式:就一列一列的数据: 2,导出excel的数据为CSV格式,即把excel的数据另存为xxxx.csv;: 3,用EditPlus工具将xxx ...

  7. 理解Docker(3):Docker 使用 Linux namespace 隔离容器的运行环境

    本系列文章将介绍Docker的有关知识: (1)Docker 安装及基本用法 (2)Docker 镜像 (3)Docker 容器的隔离性 - 使用 Linux namespace 隔离容器的运行环境 ...

  8. [No000099]软件版本命名规范

    软件版本阶段说明 Base: 此版本表示该软件仅仅是一个假页面链接,通常包括所有的功能和页面布局,但是页面中的功能都没有做完整的实现,只是做为整体网站的一个基础架构. Alpha: 此版本表示该软件在 ...

  9. Docker初体验

    ## Docker初体验 安装 因为我用的是mac,所以安装很简单,下载dmg下来之后拖拽安装即可完成. 需要注意的就是由于之前的docker是基于linux开发,不支持mac,所以就出现了docke ...

  10. oAuth 2.0 笔记

    OAuth 2.0规范于2012年发布,很多大型互联网公司(比如:微信.微博.支付宝)对外提供的SDK中,授权部分基本上都是按这个规范来实现的. OAuth 2.0提供了4种基本的标准授权流程,最为复 ...