Python Library GEO
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

sun.py 5.2KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182
  1. #!/usr/bin/env python
  2. # -*- coding: utf-8 -*-
  3. #
  4. """
  5. geo.sun (Sun)
  6. =============
  7. **Author:**
  8. * Dirk Alders <sudo-dirk@mount-mockery.de>
  9. * Formula from Dr. Roland Brodbeck, Calsky (http://lexikon.astronomie.info/zeitgleichung/neu.html)
  10. * First implementation by Alexander Klupp 2014-01-14
  11. **Description:**
  12. This module is a submodule of :mod:`geo` and supports functions and classes for sun position.
  13. **Contentlist:**
  14. * :func:`geo.sun.sunset`
  15. * :func:`geo.sun.sunrise`
  16. **Unittest:**
  17. See also the :download:`unittest <../../geo/_testresults_/unittest.pdf>` documentation.
  18. """
  19. import calendar
  20. import math
  21. import time
  22. europe_berlin = {'lat': 52.520008, 'lon': 13.404954}
  23. def JulianischesDatum(Jahr, Monat, Tag, Stunde, Minuten, Sekunden):
  24. if (Monat <= 2):
  25. Monat = Monat + 12
  26. Jahr = Jahr - 1
  27. Gregor = (Jahr / 400) - (Jahr / 100) + (Jahr / 4) # Gregorianischer Kalender
  28. return 2400000.5 + 365 * Jahr - 679004 + Gregor + math.floor(30.6001 * (Monat + 1)) + Tag + Stunde / 24 + Minuten / 1440 + Sekunden / 86400
  29. def InPi(x):
  30. n = int(x / (2 * math.pi))
  31. x = x - n * 2 * math.pi
  32. if (x < 0):
  33. x += 2 * math.pi
  34. return x
  35. def eps(T):
  36. # Neigung der Erdachse
  37. return math.pi / 180 * (23.43929111 + (-46.8150 * T - 0.00059 * T ** 2 + 0.001813 * T ** 3) / 3600)
  38. def BerechneZeitgleichung(T):
  39. RA_Mittel = 18.71506921 + 2400.0513369 * T + (2.5862e-5 - 1.72e-9 * T) * T ** 2
  40. M = InPi(2 * math.pi * (0.993133 + 99.997361 * T))
  41. L = InPi(2 * math.pi * (0.7859453 + M / (2 * math.pi) + (6893 * math.sin(M) + 72 * math.sin(2 * M) + 6191.2 * T) / 1296e3))
  42. e = eps(T)
  43. RA = math.atan(math.tan(L) * math.cos(e))
  44. if (RA < 0):
  45. RA += math.pi
  46. if (L > math.pi):
  47. RA += math.pi
  48. RA = 24 * RA / (2 * math.pi)
  49. DK = math.asin(math.sin(e) * math.sin(L))
  50. # Damit 0 <= RA_Mittel < 24
  51. RA_Mittel = 24.0 * InPi(2 * math.pi * RA_Mittel / 24.0) / (2 * math.pi)
  52. dRA = RA_Mittel - RA
  53. if (dRA < -12.0):
  54. dRA += 24.0
  55. if (dRA > 12.0):
  56. dRA -= 24.0
  57. dRA = dRA * 1.0027379
  58. return dRA, DK
  59. def Sonnenauf_untergang(JD, Zeitzone, coord):
  60. # Zeitzone = 0 #Weltzeit
  61. # Zeitzone = 1 #Winterzeit
  62. # Zeitzone = 2 #Sommerzeit
  63. # JD = JulianischesDatum
  64. B = math.radians(coord.get('lat')) # geographische Breite Erkelenz
  65. GeographischeLaenge = coord.get('lon') # geographische Laenge
  66. JD2000 = 2451545
  67. h = -50.0 / 60.0 * math.pi / 180
  68. T = (JD - JD2000) / 36525
  69. Zeitgleichung, DK = BerechneZeitgleichung(T)
  70. Zeitdifferenz = 12 * math.acos((math.sin(h) - math.sin(B) * math.sin(DK)) / (math.cos(B) * math.cos(DK))) / math.pi
  71. AufgangOrtszeit = 12 - Zeitdifferenz - Zeitgleichung
  72. UntergangOrtszeit = 12 + Zeitdifferenz - Zeitgleichung
  73. AufgangWeltzeit = AufgangOrtszeit - GeographischeLaenge / 15
  74. UntergangWeltzeit = UntergangOrtszeit - GeographischeLaenge / 15
  75. Aufgang = AufgangWeltzeit + Zeitzone
  76. if (Aufgang < 0):
  77. Aufgang += 24
  78. elif (Aufgang >= 24):
  79. Aufgang -= 24
  80. AM = round(Aufgang * 60) / 60 # minutengenau runden
  81. Untergang = UntergangWeltzeit + Zeitzone
  82. if (Untergang < 0):
  83. Untergang += 24
  84. elif (Untergang >= 24):
  85. Untergang -= 24
  86. UM = round(Untergang * 60) / 60 # minutengenau runden
  87. return AM, UM
  88. def sunrise(coord=europe_berlin, date=None):
  89. """
  90. :param coord: Target coordinate or None (default is central europe).
  91. :type coord: geo.gps.coordinate
  92. :param date: The day to calculate with or None (only year, month and day are relevant; default ist today)
  93. :type date: time.struct_time
  94. :return: The date and time information for the sunrise
  95. :rtype: time.struct_time
  96. This Method calculates the time for sunrise for a given date and coordinate.
  97. .. code-block:: python
  98. >>> import geo
  99. >>> ...
  100. """
  101. date = date or time.localtime()
  102. year, month, day = date[0:3]
  103. dst = date[8] # Sommerzeit
  104. AM = Sonnenauf_untergang(JulianischesDatum(year, month, day, 12, 0, 0), dst + 1, coord)[0]
  105. tup_list = list(date)
  106. tup_list[3] = 0
  107. tup_list[4] = 0
  108. tup_list[5] = 0
  109. tm = time.mktime(time.struct_time(tup_list))
  110. return time.localtime(tm + AM * 3600)
  111. def sunset(coord=europe_berlin, date=None):
  112. """
  113. :param coord: Target coordinate or None (default is central europe).
  114. :type coord: geo.gps.coordinate
  115. :param date: The day to calculate with or None (only year, month and day are relevant; default ist today)
  116. :type date: time.struct_time
  117. :return: The date and time information for the sunset
  118. :rtype: time.struct_time
  119. This Method calculates the time for sunrise for a given date and coordinate.
  120. .. code-block:: python
  121. >>> import geo
  122. >>> ...
  123. """
  124. date = date or time.localtime()
  125. year, month, day = date[0:3]
  126. dst = date[8] # Sommerzeit
  127. UM = Sonnenauf_untergang(JulianischesDatum(year, month, day, 12, 0, 0), dst + 1, coord)[1]
  128. tup_list = list(date)
  129. tup_list[3] = 0
  130. tup_list[4] = 0
  131. tup_list[5] = 0
  132. tm = time.mktime(time.struct_time(tup_list))
  133. return time.localtime(tm + UM * 3600)