From 7f796156b236854abf824a7297724b00ddbe13f6 Mon Sep 17 00:00:00 2001 From: Eskimue Date: Fri, 3 Apr 2026 13:41:31 +0200 Subject: [PATCH] Finsternisse eingebaut --- .codex-temp/php-server.err.log | 244 ++++++++++++++++++++++ public/monatsvorhersage_old.php | 35 ++++ public/py/__pycache__/api.cpython-314.pyc | Bin 101935 -> 112411 bytes public/py/api.py | 197 ++++++++++++++++- 4 files changed, 474 insertions(+), 2 deletions(-) diff --git a/.codex-temp/php-server.err.log b/.codex-temp/php-server.err.log index e69de29..7494f4e 100644 --- a/.codex-temp/php-server.err.log +++ b/.codex-temp/php-server.err.log @@ -0,0 +1,244 @@ +[Fri Apr 3 12:55:30 2026] PHP 8.5.4 Development Server (http://127.0.0.1:8000) started +[Fri Apr 3 12:55:31 2026] 127.0.0.1:61744 Accepted +[Fri Apr 3 12:55:31 2026] 127.0.0.1:61744 [200]: GET / +[Fri Apr 3 12:55:31 2026] 127.0.0.1:61744 Closing +[Fri Apr 3 12:55:43 2026] 127.0.0.1:62501 Accepted +[Fri Apr 3 12:55:43 2026] 127.0.0.1:62501 [200]: GET / +[Fri Apr 3 12:55:43 2026] 127.0.0.1:62501 Closing +[Fri Apr 3 12:55:43 2026] 127.0.0.1:57288 Accepted +[Fri Apr 3 12:55:43 2026] 127.0.0.1:57288 [200]: GET /css/style.css +[Fri Apr 3 12:55:43 2026] 127.0.0.1:57288 Closing +[Fri Apr 3 12:55:43 2026] 127.0.0.1:60157 Accepted +[Fri Apr 3 12:55:43 2026] 127.0.0.1:59285 Accepted +[Fri Apr 3 12:55:43 2026] 127.0.0.1:60157 [200]: GET /images/star16x16.png +[Fri Apr 3 12:55:43 2026] 127.0.0.1:59285 [200]: GET /images/star16x16_rays.png +[Fri Apr 3 12:55:43 2026] 127.0.0.1:60157 Closing +[Fri Apr 3 12:55:43 2026] 127.0.0.1:59285 Closing +[Fri Apr 3 12:55:43 2026] 127.0.0.1:51393 Accepted +[Fri Apr 3 12:55:43 2026] 127.0.0.1:51393 [200]: GET /favicon.ico +[Fri Apr 3 12:55:43 2026] 127.0.0.1:51393 Closing +[Fri Apr 3 12:55:45 2026] 127.0.0.1:61468 Accepted +[Fri Apr 3 12:55:45 2026] 127.0.0.1:61468 [200]: GET /login.php +[Fri Apr 3 12:55:45 2026] 127.0.0.1:61468 Closing +[Fri Apr 3 12:55:45 2026] 127.0.0.1:63560 Accepted +[Fri Apr 3 12:55:45 2026] 127.0.0.1:63560 [200]: GET /css/style.css +[Fri Apr 3 12:55:45 2026] 127.0.0.1:63560 Closing +[Fri Apr 3 12:55:45 2026] 127.0.0.1:63181 Accepted +[Fri Apr 3 12:55:45 2026] 127.0.0.1:58293 Accepted +[Fri Apr 3 12:55:45 2026] 127.0.0.1:63181 [200]: GET /images/star16x16.png +[Fri Apr 3 12:55:45 2026] 127.0.0.1:58293 [200]: GET /images/star16x16_rays.png +[Fri Apr 3 12:55:45 2026] 127.0.0.1:63181 Closing +[Fri Apr 3 12:55:45 2026] 127.0.0.1:58293 Closing +[Fri Apr 3 12:55:45 2026] 127.0.0.1:59169 Accepted +[Fri Apr 3 12:55:45 2026] 127.0.0.1:59169 [200]: GET /favicon.ico +[Fri Apr 3 12:55:45 2026] 127.0.0.1:59169 Closing +[Fri Apr 3 12:55:52 2026] 127.0.0.1:61270 Accepted +[Fri Apr 3 12:55:52 2026] 127.0.0.1:61270 [302]: POST /login.php +[Fri Apr 3 12:55:52 2026] 127.0.0.1:61270 Closing +[Fri Apr 3 12:55:52 2026] 127.0.0.1:53857 Accepted +[Fri Apr 3 12:55:54 2026] 127.0.0.1:53857 [200]: GET /index.php +[Fri Apr 3 12:55:54 2026] 127.0.0.1:53857 Closing +[Fri Apr 3 12:55:54 2026] 127.0.0.1:60472 Accepted +[Fri Apr 3 12:55:54 2026] 127.0.0.1:60472 [200]: GET /css/style.css +[Fri Apr 3 12:55:54 2026] 127.0.0.1:60472 Closing +[Fri Apr 3 12:55:54 2026] 127.0.0.1:51512 Accepted +[Fri Apr 3 12:55:54 2026] 127.0.0.1:55657 Accepted +[Fri Apr 3 12:55:54 2026] 127.0.0.1:51512 [200]: GET /images/star16x16.png +[Fri Apr 3 12:55:54 2026] 127.0.0.1:55657 [200]: GET /images/star16x16_rays.png +[Fri Apr 3 12:55:54 2026] 127.0.0.1:51512 Closing +[Fri Apr 3 12:55:54 2026] 127.0.0.1:55657 Closing +[Fri Apr 3 12:55:54 2026] 127.0.0.1:65352 Accepted +[Fri Apr 3 12:55:55 2026] 127.0.0.1:65352 [200]: GET /favicon.ico +[Fri Apr 3 12:55:55 2026] 127.0.0.1:65352 Closing +[Fri Apr 3 12:56:03 2026] 127.0.0.1:55831 Accepted +[Fri Apr 3 12:56:03 2026] 127.0.0.1:55831 [200]: GET /monatsvorhersage.php +[Fri Apr 3 12:56:03 2026] 127.0.0.1:55831 Closing +[Fri Apr 3 12:56:03 2026] 127.0.0.1:49989 Accepted +[Fri Apr 3 12:56:03 2026] 127.0.0.1:49989 [200]: GET /css/style.css +[Fri Apr 3 12:56:03 2026] 127.0.0.1:49989 Closing +[Fri Apr 3 12:56:03 2026] 127.0.0.1:59540 Accepted +[Fri Apr 3 12:56:03 2026] 127.0.0.1:58424 Accepted +[Fri Apr 3 12:56:03 2026] 127.0.0.1:59540 [200]: GET /images/star16x16.png +[Fri Apr 3 12:56:03 2026] 127.0.0.1:58424 [200]: GET /images/star16x16_rays.png +[Fri Apr 3 12:56:03 2026] 127.0.0.1:59540 Closing +[Fri Apr 3 12:56:03 2026] 127.0.0.1:58424 Closing +[Fri Apr 3 12:56:03 2026] 127.0.0.1:53882 Accepted +[Fri Apr 3 12:56:04 2026] 127.0.0.1:53882 [200]: GET /favicon.ico +[Fri Apr 3 12:56:04 2026] 127.0.0.1:53882 Closing +[Fri Apr 3 12:56:06 2026] 127.0.0.1:57400 Accepted +[Fri Apr 3 12:56:09 2026] 127.0.0.1:57400 [200]: GET /monatsvorhersage_old.php?year=2026&month=4 +[Fri Apr 3 12:56:09 2026] 127.0.0.1:57400 Closing +[Fri Apr 3 12:56:09 2026] 127.0.0.1:57166 Accepted +[Fri Apr 3 12:56:09 2026] 127.0.0.1:57166 [200]: GET /css/style.css +[Fri Apr 3 12:56:09 2026] 127.0.0.1:53955 Accepted +[Fri Apr 3 12:56:09 2026] 127.0.0.1:53955 [200]: GET /js/astronomy.browser.min.js +[Fri Apr 3 12:56:09 2026] 127.0.0.1:57166 Closing +[Fri Apr 3 12:56:09 2026] 127.0.0.1:53955 Closing +[Fri Apr 3 12:56:09 2026] 127.0.0.1:61310 Accepted +[Fri Apr 3 12:56:09 2026] 127.0.0.1:61310 [200]: GET /images/star16x16.png +[Fri Apr 3 12:56:09 2026] 127.0.0.1:53333 Accepted +[Fri Apr 3 12:56:09 2026] 127.0.0.1:53333 [200]: GET /images/star16x16_rays.png +[Fri Apr 3 12:56:09 2026] 127.0.0.1:61310 Closing +[Fri Apr 3 12:56:09 2026] 127.0.0.1:53333 Closing +[Fri Apr 3 12:56:09 2026] 127.0.0.1:57930 Accepted +[Fri Apr 3 12:56:10 2026] 127.0.0.1:57930 [200]: GET /favicon.ico +[Fri Apr 3 12:56:10 2026] 127.0.0.1:57930 Closing +[Fri Apr 3 13:07:35 2026] 127.0.0.1:62131 Accepted +[Fri Apr 3 13:07:45 2026] 127.0.0.1:62131 [200]: GET /monatsvorhersage_old.php?year=2026&month=3 +[Fri Apr 3 13:07:45 2026] 127.0.0.1:62131 Closing +[Fri Apr 3 13:08:21 2026] 127.0.0.1:58476 Accepted +[Fri Apr 3 13:08:31 2026] 127.0.0.1:58476 [200]: GET /monatsvorhersage_old.php?year=2026&month=3 +[Fri Apr 3 13:08:31 2026] 127.0.0.1:58476 Closing +[Fri Apr 3 13:08:31 2026] 127.0.0.1:59671 Accepted +[Fri Apr 3 13:08:31 2026] 127.0.0.1:49906 Accepted +[Fri Apr 3 13:08:31 2026] 127.0.0.1:59671 [200]: GET /css/style.css +[Fri Apr 3 13:08:31 2026] 127.0.0.1:49906 [200]: GET /js/astronomy.browser.min.js +[Fri Apr 3 13:08:31 2026] 127.0.0.1:59671 Closing +[Fri Apr 3 13:08:31 2026] 127.0.0.1:49906 Closing +[Fri Apr 3 13:08:31 2026] 127.0.0.1:56322 Accepted +[Fri Apr 3 13:08:31 2026] 127.0.0.1:56322 [200]: GET /images/star16x16.png +[Fri Apr 3 13:08:31 2026] 127.0.0.1:64778 Accepted +[Fri Apr 3 13:08:31 2026] 127.0.0.1:64778 [200]: GET /images/star16x16_rays.png +[Fri Apr 3 13:08:31 2026] 127.0.0.1:56322 Closing +[Fri Apr 3 13:08:31 2026] 127.0.0.1:64778 Closing +[Fri Apr 3 13:08:31 2026] 127.0.0.1:57777 Accepted +[Fri Apr 3 13:08:32 2026] 127.0.0.1:57777 [200]: GET /favicon.ico +[Fri Apr 3 13:08:32 2026] 127.0.0.1:57777 Closing +[Fri Apr 3 13:10:24 2026] 127.0.0.1:55499 Accepted +[Fri Apr 3 13:10:36 2026] 127.0.0.1:55499 [200]: GET /monatsvorhersage_old.php?year=2026&month=3 +[Fri Apr 3 13:10:36 2026] 127.0.0.1:55499 Closing +[Fri Apr 3 13:10:36 2026] 127.0.0.1:55501 Accepted +[Fri Apr 3 13:10:47 2026] 127.0.0.1:55501 [200]: GET /monatsvorhersage_old.php?year=2026&month=3 +[Fri Apr 3 13:10:47 2026] 127.0.0.1:55501 Closing +[Fri Apr 3 13:11:58 2026] 127.0.0.1:65503 Accepted +[Fri Apr 3 13:12:08 2026] 127.0.0.1:65503 [200]: GET /monatsvorhersage_old.php?year=2026&month=3 +[Fri Apr 3 13:12:08 2026] 127.0.0.1:65503 Closing +[Fri Apr 3 13:12:08 2026] 127.0.0.1:62139 Accepted +[Fri Apr 3 13:12:08 2026] 127.0.0.1:62139 [200]: GET /css/style.css +[Fri Apr 3 13:12:08 2026] 127.0.0.1:62139 Closing +[Fri Apr 3 13:12:08 2026] 127.0.0.1:53163 Accepted +[Fri Apr 3 13:12:08 2026] 127.0.0.1:53163 [200]: GET /js/astronomy.browser.min.js +[Fri Apr 3 13:12:08 2026] 127.0.0.1:53163 Closing +[Fri Apr 3 13:12:08 2026] 127.0.0.1:57019 Accepted +[Fri Apr 3 13:12:08 2026] 127.0.0.1:57019 [200]: GET /images/star16x16.png +[Fri Apr 3 13:12:08 2026] 127.0.0.1:55337 Accepted +[Fri Apr 3 13:12:08 2026] 127.0.0.1:55337 [200]: GET /images/star16x16_rays.png +[Fri Apr 3 13:12:08 2026] 127.0.0.1:57019 Closing +[Fri Apr 3 13:12:08 2026] 127.0.0.1:55337 Closing +[Fri Apr 3 13:12:08 2026] 127.0.0.1:60473 Accepted +[Fri Apr 3 13:12:09 2026] 127.0.0.1:60473 [200]: GET /favicon.ico +[Fri Apr 3 13:12:09 2026] 127.0.0.1:60473 Closing +[Fri Apr 3 13:17:32 2026] 127.0.0.1:61313 Accepted +[Fri Apr 3 13:17:32 2026] PHP Fatal error: strict_types declaration must be the very first statement in the script in C:\Users\HP\source\repos\skyview.astronomiemuseum.de\public\monatsvorhersage_old.php on line 2 +Stack trace: +#0 {main} +[Fri Apr 3 13:17:32 2026] 127.0.0.1:61313 [200]: GET /monatsvorhersage_old.php?year=2026&month=3 - strict_types declaration must be the very first statement in the script in C:\Users\HP\source\repos\skyview.astronomiemuseum.de\public\monatsvorhersage_old.php on line 2 +[Fri Apr 3 13:17:32 2026] 127.0.0.1:61313 Closing +[Fri Apr 3 13:17:45 2026] 127.0.0.1:65268 Accepted +[Fri Apr 3 13:17:56 2026] 127.0.0.1:65268 [200]: GET /monatsvorhersage_old.php?year=2026&month=3 +[Fri Apr 3 13:17:56 2026] 127.0.0.1:65268 Closing +[Fri Apr 3 13:18:58 2026] 127.0.0.1:49481 Accepted +[Fri Apr 3 13:19:07 2026] 127.0.0.1:49481 [200]: GET /monatsvorhersage_old.php?year=2026&month=3 +[Fri Apr 3 13:19:07 2026] 127.0.0.1:49481 Closing +[Fri Apr 3 13:19:07 2026] 127.0.0.1:55985 Accepted +[Fri Apr 3 13:19:07 2026] 127.0.0.1:64118 Accepted +[Fri Apr 3 13:19:07 2026] 127.0.0.1:55985 [200]: GET /css/style.css +[Fri Apr 3 13:19:07 2026] 127.0.0.1:64118 [200]: GET /js/astronomy.browser.min.js +[Fri Apr 3 13:19:07 2026] 127.0.0.1:55985 Closing +[Fri Apr 3 13:19:07 2026] 127.0.0.1:64118 Closing +[Fri Apr 3 13:19:07 2026] 127.0.0.1:53485 Accepted +[Fri Apr 3 13:19:07 2026] 127.0.0.1:49504 Accepted +[Fri Apr 3 13:19:07 2026] 127.0.0.1:53485 [200]: GET /images/star16x16.png +[Fri Apr 3 13:19:07 2026] 127.0.0.1:49504 [200]: GET /images/star16x16_rays.png +[Fri Apr 3 13:19:07 2026] 127.0.0.1:53485 Closing +[Fri Apr 3 13:19:07 2026] 127.0.0.1:49504 Closing +[Fri Apr 3 13:19:07 2026] 127.0.0.1:55983 Accepted +[Fri Apr 3 13:19:09 2026] 127.0.0.1:55983 [200]: GET /favicon.ico +[Fri Apr 3 13:19:09 2026] 127.0.0.1:55983 Closing +[Fri Apr 3 13:26:13 2026] 127.0.0.1:54897 Accepted +[Fri Apr 3 13:26:21 2026] 127.0.0.1:54897 [200]: GET /monatsvorhersage_old.php?year=2026&month=4 +[Fri Apr 3 13:26:21 2026] 127.0.0.1:54897 Closing +[Fri Apr 3 13:26:54 2026] 127.0.0.1:58751 Accepted +[Fri Apr 3 13:27:02 2026] 127.0.0.1:58751 [200]: GET /monatsvorhersage_old.php?year=2026&month=4 +[Fri Apr 3 13:27:02 2026] 127.0.0.1:58751 Closing +[Fri Apr 3 13:27:02 2026] 127.0.0.1:57821 Accepted +[Fri Apr 3 13:27:02 2026] 127.0.0.1:57821 [200]: GET /css/style.css +[Fri Apr 3 13:27:02 2026] 127.0.0.1:57821 Closing +[Fri Apr 3 13:27:02 2026] 127.0.0.1:60458 Accepted +[Fri Apr 3 13:27:02 2026] 127.0.0.1:60458 [200]: GET /js/astronomy.browser.min.js +[Fri Apr 3 13:27:02 2026] 127.0.0.1:60458 Closing +[Fri Apr 3 13:27:02 2026] 127.0.0.1:65479 Accepted +[Fri Apr 3 13:27:02 2026] 127.0.0.1:53843 Accepted +[Fri Apr 3 13:27:02 2026] 127.0.0.1:65479 [200]: GET /images/star16x16.png +[Fri Apr 3 13:27:02 2026] 127.0.0.1:53843 [200]: GET /images/star16x16_rays.png +[Fri Apr 3 13:27:02 2026] 127.0.0.1:65479 Closing +[Fri Apr 3 13:27:02 2026] 127.0.0.1:53843 Closing +[Fri Apr 3 13:27:02 2026] 127.0.0.1:49425 Accepted +[Fri Apr 3 13:27:03 2026] 127.0.0.1:49425 [200]: GET /favicon.ico +[Fri Apr 3 13:27:03 2026] 127.0.0.1:49425 Closing +[Fri Apr 3 13:27:40 2026] 127.0.0.1:56116 Accepted +[Fri Apr 3 13:27:55 2026] 127.0.0.1:56116 [200]: GET /monatsvorhersage_old.php?year=2026&month=3 +[Fri Apr 3 13:27:55 2026] 127.0.0.1:56116 Closing +[Fri Apr 3 13:27:55 2026] 127.0.0.1:62096 Accepted +[Fri Apr 3 13:27:55 2026] 127.0.0.1:62096 [200]: GET /css/style.css +[Fri Apr 3 13:27:55 2026] 127.0.0.1:62096 Closing +[Fri Apr 3 13:27:55 2026] 127.0.0.1:63051 Accepted +[Fri Apr 3 13:27:55 2026] 127.0.0.1:63051 [200]: GET /js/astronomy.browser.min.js +[Fri Apr 3 13:27:55 2026] 127.0.0.1:63051 Closing +[Fri Apr 3 13:27:55 2026] 127.0.0.1:56973 Accepted +[Fri Apr 3 13:27:55 2026] 127.0.0.1:56973 [200]: GET /images/star16x16.png +[Fri Apr 3 13:27:55 2026] 127.0.0.1:59670 Accepted +[Fri Apr 3 13:27:55 2026] 127.0.0.1:59670 [200]: GET /images/star16x16_rays.png +[Fri Apr 3 13:27:55 2026] 127.0.0.1:56973 Closing +[Fri Apr 3 13:27:55 2026] 127.0.0.1:59670 Closing +[Fri Apr 3 13:27:55 2026] 127.0.0.1:55675 Accepted +[Fri Apr 3 13:27:56 2026] 127.0.0.1:55675 [200]: GET /favicon.ico +[Fri Apr 3 13:27:56 2026] 127.0.0.1:55675 Closing +[Fri Apr 3 13:29:57 2026] 127.0.0.1:50606 Accepted +[Fri Apr 3 13:29:57 2026] PHP Fatal error: strict_types declaration must be the very first statement in the script in C:\Users\HP\source\repos\skyview.astronomiemuseum.de\public\monatsvorhersage_old.php on line 2 +Stack trace: +#0 {main} +[Fri Apr 3 13:29:57 2026] 127.0.0.1:50606 [200]: GET /monatsvorhersage_old.php?year=2026&month=4 - strict_types declaration must be the very first statement in the script in C:\Users\HP\source\repos\skyview.astronomiemuseum.de\public\monatsvorhersage_old.php on line 2 +[Fri Apr 3 13:29:57 2026] 127.0.0.1:50606 Closing +[Fri Apr 3 13:30:21 2026] 127.0.0.1:53183 Accepted +[Fri Apr 3 13:30:35 2026] 127.0.0.1:53183 [200]: GET /monatsvorhersage_old.php?year=2026&month=3 +[Fri Apr 3 13:30:35 2026] 127.0.0.1:53183 Closing +[Fri Apr 3 13:30:35 2026] 127.0.0.1:54365 Accepted +[Fri Apr 3 13:30:35 2026] 127.0.0.1:57332 Accepted +[Fri Apr 3 13:30:35 2026] 127.0.0.1:54365 [200]: GET /css/style.css +[Fri Apr 3 13:30:35 2026] 127.0.0.1:57332 [200]: GET /js/astronomy.browser.min.js +[Fri Apr 3 13:30:35 2026] 127.0.0.1:54365 Closing +[Fri Apr 3 13:30:35 2026] 127.0.0.1:57332 Closing +[Fri Apr 3 13:30:35 2026] 127.0.0.1:63339 Accepted +[Fri Apr 3 13:30:35 2026] 127.0.0.1:61606 Accepted +[Fri Apr 3 13:30:35 2026] 127.0.0.1:63339 [200]: GET /images/star16x16.png +[Fri Apr 3 13:30:35 2026] 127.0.0.1:61606 [200]: GET /images/star16x16_rays.png +[Fri Apr 3 13:30:35 2026] 127.0.0.1:63339 Closing +[Fri Apr 3 13:30:35 2026] 127.0.0.1:61606 Closing +[Fri Apr 3 13:30:35 2026] 127.0.0.1:62852 Accepted +[Fri Apr 3 13:30:36 2026] 127.0.0.1:62852 [200]: GET /favicon.ico +[Fri Apr 3 13:30:36 2026] 127.0.0.1:62852 Closing +[Fri Apr 3 13:31:31 2026] 127.0.0.1:55128 Accepted +[Fri Apr 3 13:31:39 2026] 127.0.0.1:55128 [200]: GET /monatsvorhersage_old.php?year=2026&month=4 +[Fri Apr 3 13:31:39 2026] 127.0.0.1:55128 Closing +[Fri Apr 3 13:33:09 2026] 127.0.0.1:59634 Accepted +[Fri Apr 3 13:33:17 2026] 127.0.0.1:59634 [200]: GET /monatsvorhersage_old.php?year=2026&month=4 +[Fri Apr 3 13:33:17 2026] 127.0.0.1:59634 Closing +[Fri Apr 3 13:34:05 2026] 127.0.0.1:55782 Accepted +[Fri Apr 3 13:34:19 2026] 127.0.0.1:55782 [200]: GET /monatsvorhersage_old.php?year=2026&month=3 +[Fri Apr 3 13:34:19 2026] 127.0.0.1:55782 Closing +[Fri Apr 3 13:34:19 2026] 127.0.0.1:63401 Accepted +[Fri Apr 3 13:34:19 2026] 127.0.0.1:63401 [200]: GET /css/style.css +[Fri Apr 3 13:34:19 2026] 127.0.0.1:63401 Closing +[Fri Apr 3 13:34:19 2026] 127.0.0.1:53737 Accepted +[Fri Apr 3 13:34:19 2026] 127.0.0.1:53737 [200]: GET /js/astronomy.browser.min.js +[Fri Apr 3 13:34:19 2026] 127.0.0.1:53737 Closing +[Fri Apr 3 13:34:19 2026] 127.0.0.1:63715 Accepted +[Fri Apr 3 13:34:19 2026] 127.0.0.1:54210 Accepted +[Fri Apr 3 13:34:19 2026] 127.0.0.1:63715 [200]: GET /images/star16x16.png +[Fri Apr 3 13:34:19 2026] 127.0.0.1:54210 [200]: GET /images/star16x16_rays.png +[Fri Apr 3 13:34:19 2026] 127.0.0.1:63715 Closing +[Fri Apr 3 13:34:19 2026] 127.0.0.1:54210 Closing +[Fri Apr 3 13:34:19 2026] 127.0.0.1:63048 Accepted +[Fri Apr 3 13:34:20 2026] 127.0.0.1:63048 [200]: GET /favicon.ico +[Fri Apr 3 13:34:20 2026] 127.0.0.1:63048 Closing diff --git a/public/monatsvorhersage_old.php b/public/monatsvorhersage_old.php index 1d7ef8d..b3598e3 100644 --- a/public/monatsvorhersage_old.php +++ b/public/monatsvorhersage_old.php @@ -59,6 +59,7 @@ $moonData = null; $moonPhaseEvents = []; $moonPlanetApproaches = []; $planetConjunctions = []; +$eclipseEvents = []; $moonOccultations = []; $seasonChanges = []; $monthEventList = []; @@ -347,6 +348,26 @@ if (is_array($seasonDecoded) && ($seasonDecoded['ok'] ?? false)) { $seasonChanges = is_array($seasonDecoded['changes'] ?? null) ? $seasonDecoded['changes'] : []; } +$eclipseOutput = []; +$eclipseExitCode = 0; +$eclipseArgs = [ + $pythonScriptPath, + 'eclipses_for_month', + (string) $chartLatitude, + (string) $chartLongitude, + (string) $chartElevation, + (string) $selectedYear, + (string) $selectedMonth, + $chartTimezone, +]; +$eclipseCommand = $pythonExecutable . ' ' . implode(' ', array_map('escapeshellarg', $eclipseArgs)) . ' 2>&1'; +exec($eclipseCommand, $eclipseOutput, $eclipseExitCode); +$eclipseRaw = trim(implode("\n", $eclipseOutput)); +$eclipseDecoded = json_decode($eclipseRaw, true); +if (is_array($eclipseDecoded) && ($eclipseDecoded['ok'] ?? false)) { + $eclipseEvents = is_array($eclipseDecoded['events'] ?? null) ? $eclipseDecoded['events'] : []; +} + $moonPlanetOutput = []; $moonPlanetExitCode = 0; $moonPlanetArgs = [ @@ -482,6 +503,20 @@ foreach ($seasonChanges as $seasonChange) { ]; } +foreach ($eclipseEvents as $eclipseEvent) { + if (!is_array($eclipseEvent)) { + continue; + } + + $monthEventList[] = [ + 'event' => (string) ($eclipseEvent['label'] ?? 'Finsternis'), + 'date' => (string) ($eclipseEvent['local_date'] ?? ''), + 'time' => (string) ($eclipseEvent['local_time'] ?? ''), + 'local_iso' => (string) ($eclipseEvent['local_iso'] ?? ''), + 'type' => (string) ($eclipseEvent['category'] ?? 'eclipse'), + ]; +} + foreach ($moonPlanetApproaches as $approachEvent) { if (!is_array($approachEvent)) { continue; diff --git a/public/py/__pycache__/api.cpython-314.pyc b/public/py/__pycache__/api.cpython-314.pyc index 79ef597a103d345108bb8c54c523bf60c21c42ef..2a0d7ecad968aac84bd2edbe6a6bb6c9fc10056e 100644 GIT binary patch delta 16787 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 h7a{4~Zw}Rqf?B`7`W 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 diff --git a/public/py/api.py b/public/py/api.py index f9e5b35..d957fbb 100644 --- a/public/py/api.py +++ b/public/py/api.py @@ -826,6 +826,194 @@ def action_planet_conjunctions_for_month(args: list[str]) -> dict: } +def eclipse_kind_label(kind: astronomy.EclipseKind) -> str: + if kind == astronomy.EclipseKind.Penumbral: + return "Halbschatten" + if kind == astronomy.EclipseKind.Partial: + return "Partielle" + if kind == astronomy.EclipseKind.Annular: + return "Ringfoermige" + if kind == astronomy.EclipseKind.Total: + return "Totale" + return "Unbekannte" + + +def serialize_time_only(time_value: astronomy.Time, tz: ZoneInfo) -> dict: + dt_utc = time_to_datetime(time_value) + local_dt = dt_utc.astimezone(tz) + return { + "utc_iso": dt_utc.isoformat().replace("+00:00", "Z"), + "local_iso": local_dt.isoformat(), + "local_date": local_dt.strftime("%d.%m.%Y"), + "local_time": local_dt.strftime("%H:%M"), + } + + +def action_eclipses_for_month(args: list[str]) -> dict: + if len(args) != 6: + fail( + "Aktion eclipses_for_month erwartet 6 Argumente: latitude longitude elevation year month timezone", + extra={"argv": args}, + ) + + latitude = parse_float(args[0], "Latitude") + longitude = parse_float(args[1], "Longitude") + elevation = parse_float(args[2], "Elevation") + + try: + year = int(args[3]) + month = int(args[4]) + except ValueError as exc: + fail("Jahr oder Monat sind ungueltig.", extra={"details": str(exc), "argv": args}) + + if month < 1 or month > 12: + fail("Monat muss zwischen 1 und 12 liegen.", extra={"month": month}) + + timezone_name = args[5] + try: + tz = ZoneInfo(timezone_name) + except Exception as exc: + fail("Zeitzone ist ungueltig oder auf dem Server nicht verfuegbar.", extra={"details": str(exc)}) + + observer = astronomy.Observer(latitude, longitude, elevation) + local_start = datetime(year, month, 1, 0, 0, 0, tzinfo=tz) + if month == 12: + local_end = datetime(year + 1, 1, 1, 0, 0, 0, tzinfo=tz) + else: + local_end = datetime(year, month + 1, 1, 0, 0, 0, tzinfo=tz) + + utc_start = local_start.astimezone(timezone.utc) + utc_end = local_end.astimezone(timezone.utc) + scan_start = dt_to_time(utc_start - timedelta(days=40)) + + events: list[dict] = [] + + lunar = astronomy.SearchLunarEclipse(scan_start) + while True: + peak_dt_utc = time_to_datetime(lunar.peak) + if peak_dt_utc >= utc_end: + break + + local_peak = peak_dt_utc.astimezone(tz) + if local_peak >= local_start: + kind_label = eclipse_kind_label(lunar.kind) + penum_begin = lunar.peak.AddDays(-lunar.sd_penum / 1440.0) + penum_end = lunar.peak.AddDays(+lunar.sd_penum / 1440.0) + + events.append({ + "category": "lunar_eclipse", + "stage": "peak", + "kind": lunar.kind.name.lower(), + "label": f"{kind_label} Mondfinsternis - Maximum", + **serialize_time_only(lunar.peak, tz), + }) + + if lunar.sd_penum > 0: + events.append({ + "category": "lunar_eclipse", + "stage": "penumbral_begin", + "kind": lunar.kind.name.lower(), + "label": f"{kind_label} Mondfinsternis - Halbschatten beginnt", + **serialize_time_only(penum_begin, tz), + }) + events.append({ + "category": "lunar_eclipse", + "stage": "penumbral_end", + "kind": lunar.kind.name.lower(), + "label": f"{kind_label} Mondfinsternis - Halbschatten endet", + **serialize_time_only(penum_end, tz), + }) + + if lunar.sd_partial > 0: + partial_begin = lunar.peak.AddDays(-lunar.sd_partial / 1440.0) + partial_end = lunar.peak.AddDays(+lunar.sd_partial / 1440.0) + events.append({ + "category": "lunar_eclipse", + "stage": "partial_begin", + "kind": lunar.kind.name.lower(), + "label": f"{kind_label} Mondfinsternis - Partielle Phase beginnt", + **serialize_time_only(partial_begin, tz), + }) + events.append({ + "category": "lunar_eclipse", + "stage": "partial_end", + "kind": lunar.kind.name.lower(), + "label": f"{kind_label} Mondfinsternis - Partielle Phase endet", + **serialize_time_only(partial_end, tz), + }) + + if lunar.sd_total > 0: + total_begin = lunar.peak.AddDays(-lunar.sd_total / 1440.0) + total_end = lunar.peak.AddDays(+lunar.sd_total / 1440.0) + events.append({ + "category": "lunar_eclipse", + "stage": "total_begin", + "kind": lunar.kind.name.lower(), + "label": "Totale Mondfinsternis - Totalitaet beginnt", + **serialize_time_only(total_begin, tz), + }) + events.append({ + "category": "lunar_eclipse", + "stage": "total_end", + "kind": lunar.kind.name.lower(), + "label": "Totale Mondfinsternis - Totalitaet endet", + **serialize_time_only(total_end, tz), + }) + + lunar = astronomy.NextLunarEclipse(lunar.peak) + + solar = astronomy.SearchLocalSolarEclipse(scan_start, observer) + while True: + peak_dt_utc = time_to_datetime(solar.peak.time) + if peak_dt_utc >= utc_end: + break + + local_peak = peak_dt_utc.astimezone(tz) + if local_peak >= local_start: + kind_label = eclipse_kind_label(solar.kind) + + def solar_event_payload(label: str, event: astronomy.EclipseEvent, stage: str) -> dict: + payload = { + "category": "solar_eclipse", + "stage": stage, + "kind": solar.kind.name.lower(), + "label": label, + "sun_altitude_deg": float(event.altitude), + "above_horizon": float(event.altitude) >= 0.0, + } + payload.update(serialize_time_only(event.time, tz)) + return payload + + events.append(solar_event_payload(f"{kind_label} Sonnenfinsternis - Beginn", solar.partial_begin, "partial_begin")) + events.append(solar_event_payload(f"{kind_label} Sonnenfinsternis - Maximum", solar.peak, "peak")) + if solar.total_begin is not None: + phase_label = "Ringphase beginnt" if solar.kind == astronomy.EclipseKind.Annular else "Totalitaet beginnt" + events.append(solar_event_payload(f"{kind_label} Sonnenfinsternis - {phase_label}", solar.total_begin, "central_begin")) + if solar.total_end is not None: + phase_label = "Ringphase endet" if solar.kind == astronomy.EclipseKind.Annular else "Totalitaet endet" + events.append(solar_event_payload(f"{kind_label} Sonnenfinsternis - {phase_label}", solar.total_end, "central_end")) + events.append(solar_event_payload(f"{kind_label} Sonnenfinsternis - Ende", solar.partial_end, "partial_end")) + + solar = astronomy.NextLocalSolarEclipse(solar.peak.time, observer) + + events = [ + event for event in events + if local_start <= datetime.fromisoformat(event["local_iso"]) < local_end + ] + events.sort(key=lambda item: item["local_iso"]) + + return { + "ok": True, + "action": "eclipses_for_month", + "selected": { + "year": year, + "month": month, + "timezone": timezone_name, + }, + "events": events, + } + + def action_moon_star_occultations_for_month(args: list[str]) -> dict: if len(args) != 7: fail( @@ -1882,7 +2070,7 @@ def action_satellite_passes(args: list[str]) -> dict: def main() -> None: if len(sys.argv) < 2: - fail("Es wurde keine Aktion uebergeben.", extra={"available_actions": ["sun_moon_rise_set", "moon_star_occultations", "moon_phase_details", "satellite_passes", "planet_rise_set", "month_sky_context", "moon_phases_for_month", "season_changes_for_month", "moon_planet_approaches", "planet_conjunctions_for_month", "moon_star_occultations_for_month"]}) + fail("Es wurde keine Aktion uebergeben.", extra={"available_actions": ["sun_moon_rise_set", "moon_star_occultations", "moon_phase_details", "satellite_passes", "planet_rise_set", "month_sky_context", "moon_phases_for_month", "season_changes_for_month", "moon_planet_approaches", "planet_conjunctions_for_month", "eclipses_for_month", "moon_star_occultations_for_month"]}) action = sys.argv[1] args = sys.argv[2:] @@ -1937,12 +2125,17 @@ def main() -> None: print(json.dumps(result, ensure_ascii=False)) return + if action == "eclipses_for_month": + result = action_eclipses_for_month(args) + print(json.dumps(result, ensure_ascii=False)) + return + if action == "moon_star_occultations_for_month": result = action_moon_star_occultations_for_month(args) print(json.dumps(result, ensure_ascii=False)) return - fail("Unbekannte Aktion.", extra={"action": action, "available_actions": ["sun_moon_rise_set", "moon_star_occultations", "moon_phase_details", "satellite_passes", "planet_rise_set", "month_sky_context", "moon_phases_for_month", "season_changes_for_month", "moon_planet_approaches", "planet_conjunctions_for_month", "moon_star_occultations_for_month"]}) + fail("Unbekannte Aktion.", extra={"action": action, "available_actions": ["sun_moon_rise_set", "moon_star_occultations", "moon_phase_details", "satellite_passes", "planet_rise_set", "month_sky_context", "moon_phases_for_month", "season_changes_for_month", "moon_planet_approaches", "planet_conjunctions_for_month", "eclipses_for_month", "moon_star_occultations_for_month"]}) if __name__ == "__main__":