[astro] Refresh SeasonCalc and add icon package (#19875)

* Refresh SeasonCalc and add icon package

Signed-off-by: gael@lhopital.org <gael@lhopital.org>
This commit is contained in:
Gaël L'hopital
2025-12-29 16:55:25 +01:00
committed by GitHub
parent 5a07c5ba92
commit a5063ed45e
25 changed files with 480 additions and 327 deletions
+3
View File
@@ -11,6 +11,9 @@ https://www.eclipse.org/legal/epl-2.0/.
Zodiac Icon Set provided by SVG Repo under CC0 License (Public Domain) at
https://www.svgrepo.com/collection/zodiac-2/
Season Icon Set provided by Free SVG under Public Domain at
https://freesvg.org/seasons-icons76143
== Source Code
https://github.com/openhab/openhab-addons
@@ -47,6 +47,11 @@ This binding has its own IconProvider and makes available the following list of
| oh:astro:zodiac-scorpio | Yes | ![Scorpio](doc/images/zodiac-scorpio.svg) |
| oh:astro:zodiac-taurus | Yes | ![Taurus](doc/images/zodiac-taurus.svg) |
| oh:astro:zodiac-virgo | Yes | ![Virgo](doc/images/zodiac-virgo.svg) |
| oh:astro:season | Yes | ![Season](doc/images/season.svg) |
| oh:astro:season-autumn | Yes | ![Autumn](doc/images/season-autumn.svg) |
| oh:astro:season-spring | Yes | ![Spring](doc/images/season-spring.svg) |
| oh:astro:season-summer | Yes | ![Summer](doc/images/season-summer.svg) |
| oh:astro:season-winter | Yes | ![Winter](doc/images/season-winter.svg) |
## Channels
@@ -0,0 +1,6 @@
<svg height="64" width="64" viewBox="0 0 274 274" xmlns="http://www.w3.org/2000/svg">
<path fill="#e86016"
d="M273.95 219.16c0 30.261-24.528 54.792-54.79 54.792H54.79C24.53 273.952 0 249.422 0 219.16V54.79C0 24.53 24.53 0 54.79 0h164.37c30.262 0 54.79 24.53 54.79 54.79z" />
<path fill="#fff"
d="M242.472 154.694c-8.047 2.6-30.666-6.893-13.476-11.978 9.757-7.122 8.74-22.482 6.57-33.425-3.442-14.589-6.888-29.314-14.665-42.308-6.247-11.25-14.817-26.588-29.768-25.468-6.19 3.33-10.682 15.083-21.09 10.388-9.857-3.109-19.806-6.254-29.348-9.831-16.995-7.126-37.566-5.395-52.192-17.96-6.967 20.558-18.466 39.259-25.815 59.654-5.905 8.397-10.077 20.385-12.079 28.564-9.277.965-22.21-2.03-27.74 7.447.072 12.16 7.202 23.53 9.75 35.507a110.63 110.63 0 0019.886 37.096c6.638 13.591 24.91 17.723 37.382 9.774 4.418-2.23 9.445-8.302 5.104-.411-4.227 11.845-4.287 29.622 9.118 35.478 20.156 6.391 43.285-6.852 51.264-25.739 1.517-9.046-10.33-19.482-4.55-28.785 13.424 1.47 15.566 18.693 19.71 29.081 3.802 12.846 6.727 26.234 13.826 37.78 14.722 8.837 3.956-13.924.274-19.497-6.41-9.814-9.378-21.045-14.845-31.38-4.588-6.81-10.484-25.704 4.314-21.486.396 12.902 11.933 24.107 25.161 22.177 20.442-1.558 38.827-15.744 47.2-34.158 1.546-3.985-.345-8.441-3.991-10.52zm-10.614 11.915c.026 12.516-17.03-2.675-24.752.86-13.22 3.091-5.641 15.499 3.873 17.816 9.91 9.024-12.87 2.34-15.256-4.025-3.927-4.593-12.669-9.16-6.387.326 4.796 8.313-8.43-5.6-12.464-7.129-8.143-6.487-22.18-8.65-28.093 1.962-8.37 7.286-2.457 19.544-.907 28.64-.808 6.498-12.284-14.501-11.966.176-.35 6.937 4.4 19.905-5.749 21.256 4.305-6.551-4.614-23.869-8.163-9.63-.81 4.919-1.056 17.409-6.089 6.586-1.336-9.474-13.289 9.969-10.195-2.951 4.053-4.636 8.759-8.566.947-12.242-9.676-7.277 21.537 1.607 14.472-10.206-4.948-3.109-9.543-2.385-1.315-3.024 9.677-2.333 24.108-8.608 22.324-20.57-6.092-11.699-20.639-3.973-28.56 1.49-11.184 7.602-23.452 18.752-38.02 15.481 8-7.745 21.264-9.723 31.267-15.276 10.777-2.073 12.846-17.731-.29-16.217-12.06-2.043-21.407 6.085-31.019 10.65-5.353 2.359-17.961-3.654-5.903-4.054 10.134 2.708 21.227-11.456 7.642-15.567-7.64-1.74-25.423 4.629-26.27-4.717 7.667 2.325 12.817-8.191 2.486-7.655-5.177-.138-21.307 1.19-12.198-6.85-8.004-.434-9.75-19.414-1.213-8.802 5.334 11.36 24.16-1.108 25.114 14.439 4.73 14.553 19.902 4.151 15.332-2.96 3.804 10.283 13.782 19.426 24.937 20.424 8.842.93 3.023-17.32 9.176-7.145 7.106 7.099 14.685 16.593 25.482 17.086 14.939-6.738-2.714-23.225-11.953-26.542-17.725-7.963-39.092-9.218-53.172-24.08-7.353-11.234 15.11 3.97 19.703 5.607 10.37 4.638 21.052 14.168 33.04 11.25 10.485-10.177-5.957-23.101-15.453-26.66-9.968-4.834-23.413-9.26-25.614-21.754 8.326 6.987 17.766 13.829 28.664 15.794 13.586-5.693-3.647-19.524-11.732-23.117-4.586-2.087-13.043-9.908-2.149-6.288 11.749-1.527-1.638-11.742-7.946-12.116-12.774-5.271 10.39-2.369 3.131-10.134-2.141-4.52-4.67-16.838 1.703-6.26 2.672 7.858 11.221 6.17 16.534 3.26-2.188 4.234-7.136 24.078 1.993 12.758 5.77-10.585 3.258 10.34 2.655 15.105-3.325 7.468 3.623 25.299 9.88 19.139-.257-7.257-2.222-20.927 3.804-24.013 6.18 12.118-1.101 25.499-1.286 38.15-3.159 9.275 4.69 27.079 14.899 20.37 9.607-20.381 7.497-43.918 15.965-64.658 4.607 17.924-2.363 35.836-6.3 53.17-6.95 11.057-11.3 25.375-7.662 38.275 4.562 11.59 26.057 2.528 19.768-9.17-1.034-4.967-13.004-17.726-5.997-17.127 4.558 14.929 20.39 3.814 20.224-7.308 4.518-12.362-7.678-18.765-11.888-28.3 6.016 8.35 22.215 11.248 20.317-3.19-.068-6.44-10.112-13.314-8.57-17.829 13.275 10.189 10.994-9.985 12.89-18.313 11.935 3.437 4 17.397 3.37 26.04 1.187 8.852 15.721-9.944 8.968 3.342-3.824 9.2-17.727 15.72-15.06 26.289 8.334 4.85 14.344-15.093 24.946-10.877-4.42 10.572-17.415 13.754-24.836 21.985-9.131 3.674-14.148 23.834.597 18.353 11.027-4.016 20.308-12.16 31.788-14.897 7.114 4.652-10.562 11.054-15.134 13.44-15.133 6.588-35.23 9.586-42.77 26.307 1.31 10.66 17.716 4.492 22.7-1.967 4.325-6.854 20.949-7.405 8.564-.033-5.362 11.006 18.27 5.852 20.835-1.786 2.5 6.274 21.51 2.71 17.927 7.78-1.821.73-3.704 1.286-5.586 1.833z" />
</svg>

After

Width:  |  Height:  |  Size: 4.0 KiB

@@ -0,0 +1,8 @@
<svg height="64" width="64" viewBox="0 0 274 274" xmlns="http://www.w3.org/2000/svg">
<path fill="#b3d92c"
d="M273.95 219.161c.876 30.481-27.57 57.17-57.89 54.79-54.696-.047-109.395.095-164.09-.071-29.767-.72-54.535-29.06-51.97-58.593.047-54.439-.095-108.88.071-163.317C.791 22.203 29.131-2.565 58.664 0c54.438.047 108.879-.095 163.316.071 29.767.719 54.535 29.06 51.97 58.593v160.497z" />
<path fill="#fff"
d="M59.326 47.752c.084-5.102-7.718-8.716-4.822-13.795 5.78-1.578 1.14-14.6 9.583-11.653 5.513 3.516 9.222-6.93 14.708-1.995 5.124 2.671-.354 6.923-3.295 7.794-3.115 5.324 1.89 10.896 6.157 13.714 2.917 4.026 9.887 1.95 6.552-3.1-4.801-6.694 9.217-7.815 6.379-.375-4.35 4.573-3.47 13.645 3.34 15.192 7.784.425-1.975-10.58 5.97-11.323 8.348.411.112 9.044-.347 13.232-2.178 5.073 7.467 11.46 8.233 4.114-1.392-4.437 2.875-9.661 6.698-4.918 3.411 5.692-8.77 6.975-4.995 13.691 1.767 5.66 7.217 8.903 10.071 13.945 10.443 15.462 18.837 33.547 18.31 52.583 1.234 5.655-4.691 9.858-9.789 8.024-5.595-1.226-7.07-7.39-8.005-12.218-1.024-7.199-1.162-14.526-3.143-21.569-3.25-15.334-8.488-30.683-17.883-43.364-5-4.282-12.656 9.533-15.293.123.024-5.936 8.37-3.523 10.506-4.647.457-7.106-10.154-10.842-14.24-4.795-4.588 5.2-11.013-4.238-4.646-5.862 3.575 2.016 11.316 1.546 6.532-3.926-4.206-3.063-12.1-8.134-16.442-3.078-1.675 4.356-6.58 11.564-10.139 4.206z" />
<path fill="#fff"
d="M30.193 178.158c4.608-9.605 17.084-19.721 5.754-29.74-2.211-16.767 18.688-23.231 31.787-18.573 7.931.218 26.717 10.589 27.567.71-7.397-11.673-23.966-4.857-35.345-6.767-11.123 1.473-36.356-7.846-22.993-21.269 13.002-7.561-12.562-24.345 7.304-27.807 12.853 2.427 28.784-11.315 40.915 1.379 17.206 10.11 29.346 28.551 31.459 48.436-13.127-4.976-15.468-26.956-31.92-24.86-13.781 9.26 4.963 21.24 13.508 25.684 11.348 2.63 13.831 20.766-.956 15.514-12.584-3.455-21.774 7.84-12.98 18.278-3.84 7.588-7.606 22.599 6.872 17.289 8.542-2.362 17.166-22.502 24.541-15.565-7.58 8.005-15.467 15.884-20.255 26.049-5.898 9.925-13.079 22.73-25.61 24.134-12.202-3.837-24.678-9.069-35.651-15.02-4.565-4.505-7.192-11.87-3.997-17.872zm114.085-64.918c-7.328-21.768-7.532-49.76 10.94-66.177 10.147-4.928 22.3 4.432 31.152-5.363 17.055-2.358 21.527 15.985 19.307 28.539 11.842 8.36 9.127 24.549-3.68 30.555-12.118 5.662-26.004 8.007-35.963 17.72-3.985 4.966-13.76 12.025-8.283.705 7.525-9.657 16.584-18.801 20.687-30.536 2.088-18.243-19.07-8.557-21.357 3.042-7.402 3.072-3.749 29.112-12.803 21.515zm47.285 66.323c-11.239-8.71-31.742-19.584-42.174-17.45 4.107 8.328 30.031 17.45 10.619 24.874-4.266 6.69 10.558 18.994-3.266 23.836-14.589 5.402-10.552-18.573-18.48-19.141-11.517 16.405-24.167-10.312-11.156-17.955 9.628-14.346-9.227-10.533-13.474-1.613-12.21 13.982-21.862 34.672-14.088 52.998 8.381 15.895 27.27 9.516 40.495 10.898 10.497 8.906 23.488 18.82 38.043 11.944 16.484-5.907 15.187-25.927 25.441-37.795 5.296-11.344-4.652-22.843-11.96-30.596zm59.431-34.556c-5.797-7.654-26.316-2.437-18.485-17.349-2.573-13.896-20.233-16.232-31.948-15.327-18.45 1.929-34.435 13.175-46.978 26.225 1.506 5.762 12.117-8.488 18.63-6.918 9.208-4.473 25.956-1.715 16.357 10.561 4.762 4.238 20.764 4.112 14.633 16.142-12.958 6.393-27.835-10.015-42.537-6.825-17.348 4.13 12.834 9.14 18.177 13.985 13.415 7.618 23.287 20.533 37.291 27.09 12.52 5.115 22.706-6.667 25.283-16.332 11.796-4.399 22.004-19.843 10.526-30.217.072-.496-.95-.566-.949-1.035z" />
</svg>

After

Width:  |  Height:  |  Size: 3.3 KiB

@@ -0,0 +1,6 @@
<svg height="64" width="64" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 274 274">
<path fill="#ffcf09"
d="M273.95 219.16c0 30.261-24.528 54.792-54.79 54.792H54.79C24.53 273.952 0 249.422 0 219.16V54.79C0 24.53 24.53 0 54.79 0h164.37c30.262 0 54.79 24.53 54.79 54.79z" />
<path fill="#fff"
d="M77.52 154.764C68.87 122.778 88.027 89.9 120.31 81.33c32.284-8.572 65.465 10.41 74.117 42.397 8.65 31.984-10.509 64.862-42.792 73.433-32.283 8.57-65.465-10.412-74.115-42.396zM112.168 209.398l-39.871 39.111 14.25-53.767 10.963 10.497zM206.77 162.814l39.474 39.504-54.266-14.12 10.595-10.863zM159.753 69.08l39.868-39.108-14.249 53.765L174.41 73.24zM65.15 115.666L25.68 76.163l54.263 14.116-10.593 10.864zM69.079 172.166l-56.102-.277 48.445-28.037.262 15.105zM169.218 205.504l-.281 55.587-28.292-48 15.243-.26zM202.867 106.287l56.104.276-48.447 28.037-.26-15.104zM102.727 72.947l.278-55.585 28.295 48-15.244.257z" />
</svg>

After

Width:  |  Height:  |  Size: 934 B

@@ -0,0 +1,12 @@
<svg height="64" width="64" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 274 274">
<path fill="#02b1e8"
d="M273.95 219.161c0 30.26-24.528 54.79-54.79 54.79H54.79c-30.26 0-54.79-24.53-54.79-54.79V54.79C0 24.53 24.53 0 54.79 0h164.37c30.262 0 54.79 24.53 54.79 54.79z" />
<path fill="#02b1e8"
d="M273.95 219.161c0 30.26-24.528 54.79-54.79 54.79H54.79c-30.26 0-54.79-24.53-54.79-54.79V54.79C0 24.53 24.53 0 54.79 0h164.37c30.262 0 54.79 24.53 54.79 54.79z" />
<path fill="#02b1e8"
d="M273.95 219.161c0 30.26-24.528 54.79-54.79 54.79H54.79c-30.26 0-54.79-24.53-54.79-54.79V54.79C0 24.53 24.53 0 54.79 0h164.37c30.262 0 54.79 24.53 54.79 54.79z" />
<path fill="#fff"
d="M100.332 115.657l-1.429 41.814 35.498 22.144 36.927-19.672 1.427-41.814-35.498-22.143zm60.627 36.523l-25.622 14.353-25.242-15.013.38-29.365 25.624-14.353 25.24 15.013z" />
<path fill="#fff"
d="M240.36 175.275l-15.436 7.932-22.482-12.807 21.133-12.515-4.24-7.923-16.14 9.041-16.96-10.625.134-5.418.092.174.258-13.714 17.358-10.835 16.828 10.986 6.061-8.217-23.098-13.86 22.187-13.662 18.07 9.363 3.965-7.716-19.526-9.163 1.74-19.808-8.949-.747-.848 17.336-22.333 13.066-.271-24.56-8.983-.288-.24 18.56-18.433 8.98-3.94-2.582.115.006-1.34-.807-5.921-3.881.24.456-4.576-2.76-.707-20.45 17.926-9.078-4.083-9.36-23.552 13.074-.739-26.045 17.146-10.969-4.7-7.291-17.7 12.33-16.283-11.412-5.122 7.377 14.59 9.401.15 25.874-21.406-12.044-4.74 7.636 15.883 9.447-.526 19.81-10.91 5.813.282.015-6.219 3.435-18.061-9.614 1.1-20.065-10.148-1.143-.454 26.934L53.627 80.58 52.7 60.248l-8.665.425 1.83 21.492-18.027 8.396 3.829 8.124 15.436-7.934 22.482 12.807-21.133 12.516 4.242 7.923 16.122-9.03 16.016 9.804.534 16.953-.054 2.816-17.356 10.836-16.828-10.986-6.063 8.216 23.098 13.86-22.186 13.665-18.07-9.365-3.965 7.717 19.527 9.161-1.741 19.809 8.95.747.846-17.336 22.334-13.066.27 24.56 8.984.286.24-18.46 16.966-9.4 5.195 2.786-.071-.003 6.181 3.726.358.235-.013-.027 5.245 3.162.705 20.45-17.927 9.079 4.085 9.361 23.551-13.075.74 26.046-17.146 10.969 4.7 7.29 17.7-12.33 16.284 11.412 5.12-7.378-14.59-9.4-.148-25.873 21.406 12.042 4.74-7.634-15.91-9.463.83-19.826 12.27-6.785-.119-.004 4.408-2.435 18.062 9.613-1.1 20.066 10.147 1.143.454-26.935 22.925 12.383.927 20.333 8.665-.426-1.83-21.492 18.026-8.395zm-45.046-.984a2.727 2.727 0 01-3.747.93l-17.508-10.547-36.84 19.625-.583 22.075a2.731 2.731 0 01-2.728 2.658h-.073a2.73 2.73 0 01-2.657-2.802l.577-21.832-33.078-20.633-18.364 10.365a2.727 2.727 0 01-3.72-1.035 2.73 2.73 0 011.036-3.718l15.772-8.903-.062-.038 1.486-43.493-15.497-9.335a2.731 2.731 0 012.818-4.677l14.297 8.612 37.767-20.119.55-20.814c.04-1.507 1.272-2.722 2.801-2.657a2.73 2.73 0 012.656 2.8l-.535 20.31 36.426 22.724 17.294-9.763a2.73 2.73 0 012.685 4.755l-17.895 10.1-1.403 41.066 17.596 10.6a2.728 2.728 0 01.929 3.747zm-11.41-35.984l-.091.145-.009-.336z" />
</svg>

After

Width:  |  Height:  |  Size: 2.8 KiB

@@ -0,0 +1,28 @@
<svg height="64" width="64" viewBox="0 0 574 574" xmlns="http://www.w3.org/2000/svg">
<path fill="#FFCF09"
d="M273.95 519.16c0 30.261-24.528 54.792-54.79 54.792H54.79C24.53 573.952 0 549.422 0 519.16V354.79C0 324.53 24.53 300 54.79 300h164.37c30.262 0 54.79 24.53 54.79 54.79v164.37z" />
<path fill="#FFF"
d="M77.52 454.764c-8.65-31.986 10.508-64.864 42.79-73.434 32.284-8.572 65.466 10.41 74.117 42.397 8.65 31.984-10.509 64.862-42.792 73.433-32.282 8.57-65.465-10.412-74.114-42.396zm34.648 54.634l-39.87 39.111 14.25-53.767 10.962 10.497 14.658 4.159zm94.602-46.584l39.475 39.504-54.267-14.12 10.596-10.863 4.196-14.521zm-47.017-93.734l39.869-39.108-14.25 53.765-10.962-10.497-14.657-4.16zM65.15 415.666l-39.47-39.503 54.262 14.116-10.593 10.864-4.198 14.523zm3.93 56.5l-56.103-.277 48.445-28.037.262 15.105 7.395 13.209zm100.138 33.338l-.281 55.587-28.292-48 15.243-.26 13.33-7.327zm33.65-99.217l56.103.276-48.446 28.037-.26-15.104-7.397-13.21zm-100.141-33.34l.278-55.585 28.295 48-15.244.257-13.329 7.328z" />
<path fill="#e86016"
d="M573.95 519.16c0 30.261-24.528 54.792-54.79 54.792H354.79c-30.26 0-54.79-24.53-54.79-54.791V354.79c0-30.26 24.53-54.79 54.79-54.79h164.37c30.262 0 54.79 24.53 54.79 54.79z" />
<path fill="#fff"
d="M542.472 454.694c-8.095.618-34.962-5.61-14.91-11.072 19.423-11.34 3.68-36.773 4.35-54.698-8.701-17.34-16.423-35.546-32.232-47.698-12.893-15.69-17.523 29.623-35.234 7.42-5.087-4.843-15.726 3.478-20.89-5.412-12.707-9.119-17.385 1.173-28.741-8.85-13.605 5.831-32.897-27.809-30.452.71-4.848 17.215-14.53 26.34-20.465 45.932-1.231 14.16-16.926 11.437-8.564 26.023-4.686 15.075-44.45-4.866-29.096 20.352 1.812 22.77 10.474 46.182 26.217 62.714 7.001 24.12 33.428 18.524 46.27 4.79-8.766 13.304-11.034 43.504 15.143 43.463 18.25 2.727 42.573-16.66 41.392-34.166-7.766-7.978-11.088-33.092 4.249-18.204 10.143 18.996 14.775 40.232 22.766 60.056 15.176 22.317 11.551-7.928 1.115-16.689-6.445-17.974-19.915-35.99-19.314-54.924 18.654.451 15.364 38.803 40.044 23.98 19.254-3.862 37.915-17.45 42.985-36.743l-1.307-3.455zm-10.613 11.915c-1.287 6.288 6.579 8.865-6.213 3.345-12.815-6.798-42.453 4.691-17.017 13.657 23.404 10.546-14.678 7.244-16.54-6.245-11.69-9.7-10.542-5.908-2.02 4.11 3.993 19.367-13.397-18.882-26.398-12.32-26.92-.714-15.74 33.97-15.448 41.513-3.957-9.53-16.792-20.555-11.282-2.609 3.394 11.055-11.308 32.559-5.93 9.545-2.154-22.837-10.952 1.632-10.998 11.235-6.159 7.33 1.056-20.725-11.063-5.751-18.517 13.825 18.933-21.656-8.448-14.712.591-7.463 37.15-1.926 18.259-10.058-20.362-7.52 24.025-.378 22.699-17.682 5.827-26.166-28.93-5.159-38.328 3.106-7.352 6.341-48.288 16.306-24.436 4.27 10.989-5.977 56.606-17.128 31.4-28.408-15.638-3.557-41.288 20.063-48.656 7.908 12.447 3.27 38.004-14.465 12.967-15.862-8.638 1.656-42.134-5.036-18.354-5.663 20.272-9.88-35.667-5.02-13.76-12.455-8.388-6.385-15.417-23.836-.429-9.163 3.798 5.219 18.717 11.94 14.638-1.009 6.806 18.244 30.345 33.02 22.964 7.943 4.333 11.905 24.972 33.245 32.234 19.187-2.317-21.91 11.99 16.391 23.445 13.596 29.21 1.143-4.55-33.237-21.597-30.533-13.203-3.161-43.557-17.41-41.197-25.59 19.57 10.64 39.342 23.235 62.07 25.402-3.165-21.78-23.425-30.436-40.448-38.985-11.36-4.978-12.743-18.684-.002-7.202 6.593 10.025 37.01 21.25 24.852-.075-3.091-7.65-41.714-24.741-18.846-18.742 25.327 8.253-11.408-17.387-13.05-15.093 19.054 7.166 7.893-12.12 5.704-19.411 6.737 7.094 16.05 20.712 22.434 7.706-4.556 7.736-4.87 34.514.559 14.115 12.805-17.842-.7 18.987 4.455 26.546 1.58 12.81 12.714 18.206 9.78 1.772-4.128-10.545 4.207-34.837 5.325-11.952 2.713 18.28-10.19 37.206 1.49 54.025 16.37 13.026 16.165-32.875 20.909-44.328-.535-11.016 7.408-31.855 6.959-8.718-1.605 23.021-9.023 44.945-17.885 66.13-5.16 19.94 20.842 27.731 23.352 5.802-6.809-5.13-17.835-38.915-7.357-17.836 19.521 22.079 27.913-23.187 9.537-32.36-11.133-24.649 18.292 22.842 18.271-5.517 3.866-7.328-20.89-29.913-4.81-17.617 16.296 12.593 4.277-43.576 12.056-18.691 1.52 8.951 15.288 1.332 3.296 13.358-5.726 6.989-3.631 26.034 3.142 9.907 16.004-5.367-14.768 23.28-14.139 31.676 7.689 11.694 24.556-24.199 29.188-12.311-9.419 14.665-43.15 25.285-35.301 43.136 15.03.144 38.947-24.887 46.185-16.27-17.422 14.09-41.15 17.647-58.438 30.835-20.626 17.07 19.472 15.776 24.222 1.051 16.259-10.135 7.542 4.246-1.814 8.951 9.862 10.655 30.504-16.19 31.629-1.61 8.947-1.718 27.92-.5 6.183 4.951z" />
<path fill="#B3D92C"
d="M573.95 219.161c0 30.26-24.528 54.79-54.79 54.79H354.79c-30.26 0-54.79-24.53-54.79-54.79V54.79C300 24.53 324.53 0 354.79 0h164.37c30.262 0 54.79 24.53 54.79 54.79v164.371z" />
<path fill="#FFF"
d="M359.327 47.752c.134-5.21-10.975-12.162-2.503-15.06 1.876-4.213.151-13.643 7.969-10.093 5.798 2.704 7.042-6.582 13.051-2.65 5.59 1.696 2.748 7.193-1.475 7.104-5.4 5.457 1.817 13.38 7.447 15.97 4.35 3.515 6.982-1.383 3.878-4.996-2.594-7.048 9.057-6.65 6.894.315-3.642 4.486-4.362 12.287 2.546 14.886 4.469 2.05 5.16-2.723 3.197-5.86-1.308-5.633 8.317-7.725 7.508-1.184-2.545 4.68-7.905 11.691-1.026 16.248 5.11 2.815 5.487-4.123 4.969-7.395 2.635-6.223 11.845 1.794 5.228 4.87-6.527 3.395-3.876 11.038 1.097 15.41 7.745 8.905 13.528 19.411 18.047 30.197 4.223 10.732 6.845 22.451 5.34 33.523-2.578 6.614-13.932 5.103-15.71-2.307-3.272-7.964-1.87-16.506-4.26-24.63-3.01-16.025-8.384-32.128-17.96-45.886-5.537-5.726-9.81 7.168-15.161 1.77-3.193-6.276 6.12-7.713 9.49-5.807 2.723-5.111-7.004-11.448-11.103-8.002-2.845 3.144-10.035 6.586-10.041-1.006 1.103-6.63 8.978 2.036 10.789-2.978-.624-5.679-8.301-7.356-12.772-8.777-7.192-1.63-5.789 8.887-11.632 9.586-1.745-.2-3.08-1.659-3.807-3.246v-.002z" />
<path fill="#fff"
d="M330.194 178.158c7.83-9.708 13.718-22.133 5.602-32.763.768-13.887 17.744-19.206 29.399-16.293 9.198.385 24.411 10.679 30.08 2.104-6.376-12.222-22.082-5.79-32.881-7.355-9.719-.113-21.323-1.07-27.837-9.213-5.752-9.844 13.154-16.235 4.115-26.32-9.522-10.848 7.956-14.977 15.573-14.118 12.838-6.788 28.405-2.975 38.338 6.992 13.225 10.584 22.264 26.44 24.059 43.335-12.562-4.862-14.465-23.593-28.996-24.98-16.543 3.086-1.706 22.16 8.402 24.44 8.457.873 18.892 19.29 4.017 16.64-11.925-3.771-25.377 6.953-16.015 18.183-2.13 7.008-8.12 21.317 5.45 18.276 11.027-2.49 14.04-19.08 26.532-17.681-6.529 9.912-16.746 17.057-21.121 28.483-5.448 9.466-12.064 19.555-22.888 23.284-13.407-2.278-25.388-9.564-37.594-14.89-4.682-4.507-7.503-12.015-4.235-18.124zm114.085-64.918c-7.43-21.746-7.424-49.743 10.939-66.177 10.154-4.625 22.868 3.982 31.42-5.422 13.09-2.195 23.775 13.727 18.056 25.302 5.807 9.008 15.1 21.499 2.613 29.836-10.982 9.949-27.658 9.275-38.588 19.432-3.16 4.061-16.772 15.177-10.495 2.669 7.29-10.58 18.478-19.99 20.81-33.05-4.736-15.93-21.107-1.964-23.702 8.093-3.562 3.506-4.733 26.868-11.053 19.317zm47.284 66.323c-12.266-9.947-27.314-15.753-42.518-19.471.136 11.003 26.328 13.608 14.663 25.28-12.948 4.143 9.225 22.667-7.649 25.535-12.364 4.053-11.656-17.762-16.956-18.676-8.14 10.362-22.498-.465-16.716-11.423 3.039-4.343 12.982-17.947 1.696-16.634-14.381 7.699-22.859 23.571-26.515 39.01-2.818 11.29.12 24.94 11.074 30.806 11.382 7.288 26.715-4.537 37.008 5.625 10.183 13.766 33.394 13.7 43.618.046 3.721-13.149 13.973-24.246 15.646-37.679-.966-9.013-7.509-16.031-13.351-22.419zm59.432-34.556c-8.404-5.868-25.064-5.565-19.14-19.821-5.595-13.078-22.547-14.018-34.724-12.386-17.085 2.92-31.762 13.5-43.547 25.756 4.891 3.536 11.492-8.3 18.437-7.258 8.456-4.212 25.05-.972 16.82 10.483 4.185 6.2 20.832 3.343 14.565 15.823-8.623 7.643-20.286-4.192-30.117-4.737-4.88-1.62-20.178-2.905-18.102 1.87 11.5 7.069 25.71 9.04 35.544 18.936 10.652 8.382 20.94 22.007 36.144 19.65 11.831-4.13 12.329-19.209 24.108-23.535 7.517-6.889 8.11-18.108.012-24.781z" />
<g>
<path fill="#02B1E8"
d="M273.95 219.161c0 30.26-24.528 54.79-54.79 54.79H54.79c-30.26 0-54.79-24.53-54.79-54.79V54.79C0 24.53 24.53 0 54.79 0h164.37c30.262 0 54.79 24.53 54.79 54.79v164.371z" />
<path fill="#02B1E8"
d="M273.95 219.161c0 30.26-24.528 54.79-54.79 54.79H54.79c-30.26 0-54.79-24.53-54.79-54.79V54.79C0 24.53 24.53 0 54.79 0h164.37c30.262 0 54.79 24.53 54.79 54.79v164.371z" />
<path fill="#02B1E8"
d="M273.95 219.161c0 30.26-24.528 54.79-54.79 54.79H54.79c-30.26 0-54.79-24.53-54.79-54.79V54.79C0 24.53 24.53 0 54.79 0h164.37c30.262 0 54.79 24.53 54.79 54.79v164.371z" />
<path fill="#FFF"
d="M100.332 115.657l-1.429 41.814 35.498 22.144 36.927-19.672 1.427-41.814-35.498-22.143-36.925 19.67zm60.626 36.523l-25.621 14.353-25.242-15.013.38-29.365 25.624-14.353 25.24 15.013-.38 29.365z" />
<path fill="#FFF"
d="M240.36 175.275l-15.436 7.932-22.482-12.807 21.133-12.515-4.24-7.923-16.14 9.041-16.96-10.625.134-5.418.092.174.258-13.714 17.358-10.835 16.828 10.986 6.061-8.217-23.098-13.86 22.187-13.662 18.07 9.363 3.965-7.716-19.526-9.163 1.74-19.808-8.949-.747-.848 17.336-22.333 13.066-.271-24.56-8.983-.288-.24 18.56-18.433 8.98-3.94-2.582.115.006-1.34-.807-5.921-3.881.24.456-4.576-2.76-.707-20.45 17.926-9.078-4.083-9.36-23.552 13.074-.739-26.045 17.146-10.969-4.7-7.291-17.7 12.33-16.283-11.412-5.122 7.377 14.59 9.401.15 25.874-21.406-12.044-4.74 7.636 15.883 9.447-.526 19.81-10.91 5.813.282.015-6.219 3.435-18.061-9.614 1.1-20.065-10.148-1.143-.454 26.934L53.627 80.58 52.7 60.248l-8.665.425 1.83 21.492-18.027 8.396 3.829 8.124 15.436-7.934 22.482 12.807-21.133 12.516 4.242 7.923 16.122-9.03 16.016 9.804.534 16.953-.054 2.816-17.356 10.836-16.828-10.986-6.063 8.216 23.098 13.86-22.186 13.665-18.07-9.365-3.965 7.717 19.527 9.161-1.741 19.809 8.95.747.846-17.336 22.334-13.066.27 24.56 8.984.286.24-18.46 16.966-9.4 5.195 2.786-.071-.003 6.181 3.726.358.235-.013-.027 5.245 3.162.705 20.45-17.927 9.079 4.085 9.361 23.551-13.075.74 26.046-17.146 10.97 4.7 7.29 17.7-12.33 16.284 11.41 5.12-7.377-14.59-9.4-.148-25.873 21.406 12.042 4.74-7.634-15.91-9.462.83-19.827 12.27-6.785-.119-.004 4.408-2.435 18.062 9.613-1.1 20.067 10.147 1.142.454-26.935L218.4 193.38l.927 20.333 8.665-.425-1.83-21.493 18.026-8.395-3.828-8.124zm-45.046-.984a2.727 2.727 0 01-3.747.93l-17.508-10.547-36.84 19.625-.583 22.075a2.731 2.731 0 01-2.728 2.658l-.073-.001a2.73 2.73 0 01-2.657-2.801l.577-21.833-33.078-20.632-18.364 10.365a2.727 2.727 0 01-3.72-1.035 2.73 2.73 0 011.036-3.719l15.772-8.902-.062-.039 1.486-43.493-15.497-9.334a2.731 2.731 0 012.818-4.677l14.297 8.612 37.767-20.12.55-20.814c.04-1.506 1.272-2.722 2.801-2.657a2.73 2.73 0 012.656 2.801l-.535 20.31 36.426 22.723 17.294-9.763a2.73 2.73 0 012.685 4.755l-17.895 10.101-1.403 41.065 17.596 10.6a2.728 2.728 0 01.929 3.747zm-11.41-35.984l-.091.145-.009-.336.1.19z" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 10 KiB

@@ -24,6 +24,7 @@ import java.util.Set;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable;
import org.openhab.binding.astro.internal.model.SeasonName;
import org.openhab.binding.astro.internal.model.ZodiacSign;
import org.openhab.core.i18n.TranslationProvider;
import org.openhab.core.ui.icon.IconProvider;
@@ -47,7 +48,9 @@ import org.slf4j.LoggerFactory;
public class AstroIconProvider implements IconProvider {
private static final String DEFAULT_LABEL = "Astro Icons";
private static final String DEFAULT_DESCRIPTION = "Icons provided for the Astro Binding";
private static final String ZODIAC_ICON = "zodiac";
private static final String ZODIAC_SET = "zodiac";
private static final String SEASON_SET = "season";
private static final Set<String> ICON_SETS = Set.of(SEASON_SET, ZODIAC_SET);
private final Logger logger = LoggerFactory.getLogger(AstroIconProvider.class);
private final TranslationProvider i18nProvider;
@@ -79,18 +82,23 @@ public class AstroIconProvider implements IconProvider {
@Override
public @Nullable Integer hasIcon(String category, String iconSetId, Format format) {
return Format.SVG.equals(format) && iconSetId.equals(BINDING_ID) && category.equals(ZODIAC_ICON) ? 0 : null;
return Format.SVG.equals(format) && iconSetId.equals(BINDING_ID) && ICON_SETS.contains(category) ? 0 : null;
}
@Override
public @Nullable InputStream getIcon(String category, String iconSetId, @Nullable String state, Format format) {
String iconName = "icon/%s.svg".formatted(category);
if (category.equals(ZODIAC_ICON) && state != null) {
if (ICON_SETS.contains(category) && state != null) {
try {
var sign = ZodiacSign.valueOf(state);
iconName = iconName.replace(".", "-%s.".formatted(sign.name().toLowerCase(Locale.US)));
} catch (IllegalArgumentException ignore) {
Enum<?> stateEnum = switch (category) {
case ZODIAC_SET -> ZodiacSign.valueOf(state);
case SEASON_SET -> SeasonName.valueOf(state);
default -> throw new IllegalArgumentException("Category of icon not found: %s".formatted(category));
};
iconName = iconName.replace(".", "-%s.".formatted(stateEnum.name().toLowerCase(Locale.US)));
} catch (IllegalArgumentException e) {
// Invalid state for the icon set, we'll remain on default icon
logger.warn("Error retrieving icon name '{}' - using default: {}", state, e.getMessage());
}
}
@@ -12,14 +12,11 @@
*/
package org.openhab.binding.astro.internal.calc;
import java.util.Calendar;
import java.util.Locale;
import java.time.Instant;
import java.util.TimeZone;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable;
import org.openhab.binding.astro.internal.model.Season;
import org.openhab.binding.astro.internal.model.SeasonName;
import org.openhab.binding.astro.internal.util.DateTimeUtils;
import org.openhab.binding.astro.internal.util.MathUtils;
@@ -31,181 +28,61 @@ import org.openhab.binding.astro.internal.util.MathUtils;
*/
@NonNullByDefault
public class SeasonCalc {
private int currentYear;
private @Nullable Season currentSeason;
private static final int[] AMPLITUDE = new int[] { 485, 203, 199, 182, 156, 136, 77, 74, 70, 58, 52, 50, 45, 44, 29,
18, 17, 16, 14, 12, 12, 12, 9, 8 };
private static final double[] PHASE = new double[] { 324.96, 337.23, 342.08, 27.85, 73.14, 171.52, 222.54, 296.72,
243.58, 119.81, 297.17, 21.02, 247.54, 325.15, 60.93, 155.12, 288.79, 198.04, 199.76, 95.39, 287.11, 320.81,
227.73, 15.45 };
private static final double[] FREQUENCY = new double[] { 1934.136, 32964.467, 20.186, 445267.112, 45036.886,
22518.443, 65928.934, 3034.906, 9037.513, 33718.147, 150.678, 2281.226, 29929.562, 31555.956, 4443.417,
67555.328, 4562.452, 62894.029, 31436.921, 14577.848, 31931.756, 34777.259, 1222.114, 16859.074 };
/**
* Returns the seasons of the year of the specified calendar.
*/
public Season getSeason(Calendar calendar, double latitude, boolean useMeteorologicalSeason, TimeZone zone,
Locale locale) {
int year = calendar.get(Calendar.YEAR);
boolean isSouthernHemisphere = latitude < 0.0;
Season season = currentSeason;
if (currentYear != year) {
season = new Season(zone, locale);
if (!isSouthernHemisphere) {
season.setSpring(calcEquiSol(0, year, zone, locale));
season.setSummer(calcEquiSol(1, year, zone, locale));
season.setAutumn(calcEquiSol(2, year, zone, locale));
season.setWinter(calcEquiSol(3, year, zone, locale));
} else {
season.setSpring(calcEquiSol(2, year, zone, locale));
season.setSummer(calcEquiSol(3, year, zone, locale));
season.setAutumn(calcEquiSol(0, year, zone, locale));
season.setWinter(calcEquiSol(1, year, zone, locale));
}
currentSeason = season;
currentYear = year;
}
if (useMeteorologicalSeason && season != null) {
Calendar cal = season.getSpring();
if (cal != null) {
atMidnightOfFirstMonthDay(cal);
}
cal = season.getSummer();
if (cal != null) {
atMidnightOfFirstMonthDay(cal);
}
cal = season.getAutumn();
if (cal != null) {
atMidnightOfFirstMonthDay(cal);
}
cal = season.getWinter();
if (cal != null) {
atMidnightOfFirstMonthDay(cal);
}
}
if (season != null) {
season.setName(!isSouthernHemisphere ? getCurrentSeasonNameNorthern(calendar)
: getCurrentSeasonNameSouthern(calendar));
return season;
}
return new Season(zone, locale);
}
private void atMidnightOfFirstMonthDay(Calendar calendar) {
calendar.set(Calendar.DAY_OF_MONTH, 1);
calendar.set(Calendar.HOUR_OF_DAY, 0);
calendar.set(Calendar.MINUTE, 0);
calendar.set(Calendar.SECOND, 0);
calendar.set(Calendar.MILLISECOND, 0);
}
/**
* Returns the current season name for the northern hemisphere.
*/
@Nullable
private SeasonName getCurrentSeasonNameNorthern(Calendar calendar) {
Season currentSeason = this.currentSeason;
if (currentSeason == null) {
return null;
}
long currentMillis = calendar.getTimeInMillis();
Calendar spring = currentSeason.getSpring();
Calendar summer = currentSeason.getSummer();
Calendar autumn = currentSeason.getAutumn();
Calendar winter = currentSeason.getWinter();
if ((spring != null && currentMillis < spring.getTimeInMillis())
|| (winter != null && currentMillis >= winter.getTimeInMillis())) {
return SeasonName.WINTER;
} else if (spring != null && summer != null && currentMillis >= spring.getTimeInMillis()
&& currentMillis < summer.getTimeInMillis()) {
return SeasonName.SPRING;
} else if (summer != null && autumn != null && currentMillis >= summer.getTimeInMillis()
&& currentMillis < autumn.getTimeInMillis()) {
return SeasonName.SUMMER;
} else if (autumn != null && winter != null && currentMillis >= autumn.getTimeInMillis()
&& currentMillis < winter.getTimeInMillis()) {
return SeasonName.AUTUMN;
}
return null;
}
/**
* Returns the current season name for the southern hemisphere.
*/
@Nullable
private SeasonName getCurrentSeasonNameSouthern(Calendar calendar) {
Season currentSeason = this.currentSeason;
if (currentSeason == null) {
return null;
}
long currentMillis = calendar.getTimeInMillis();
Calendar spring = currentSeason.getSpring();
Calendar summer = currentSeason.getSummer();
Calendar autumn = currentSeason.getAutumn();
Calendar winter = currentSeason.getWinter();
if ((autumn != null && currentMillis < autumn.getTimeInMillis())
|| (summer != null && currentMillis >= summer.getTimeInMillis())) {
return SeasonName.SUMMER;
} else if (autumn != null && winter != null && currentMillis >= autumn.getTimeInMillis()
&& currentMillis < winter.getTimeInMillis()) {
return SeasonName.AUTUMN;
} else if (winter != null && spring != null && currentMillis >= winter.getTimeInMillis()
&& currentMillis < spring.getTimeInMillis()) {
return SeasonName.WINTER;
} else if (spring != null && summer != null && currentMillis >= spring.getTimeInMillis()
&& currentMillis < summer.getTimeInMillis()) {
return SeasonName.SPRING;
}
return null;
public static Season calculate(int year, double latitude, boolean useMeteorologicalSeason, TimeZone zone) {
return new Season(latitude, useMeteorologicalSeason, zone, calcEquiSol(3, year - 1), calcEquiSol(0, year),
calcEquiSol(1, year), calcEquiSol(2, year), calcEquiSol(3, year), calcEquiSol(0, year + 1));
}
/**
* Calculates the date of the season.
*/
@Nullable
private Calendar calcEquiSol(int season, int year, TimeZone zone, Locale locale) {
private static Instant calcEquiSol(int season, int year) {
double estimate = calcInitial(season, year);
double t = DateTimeUtils.toJulianCenturies(estimate);
double w = 35999.373 * t - 2.47;
double dl = 1 + 0.0334 * MathUtils.cosDeg(w) + 0.0007 * MathUtils.cosDeg(2 * w);
double s = periodic24(t);
double julianDate = estimate + ((0.00001 * s) / dl);
return DateTimeUtils.toCalendar(julianDate, zone, locale);
return DateTimeUtils.jdToInstant(julianDate);
}
/**
* Calculate an initial guess of the Equinox or Solstice of a given year.
*/
private double calcInitial(int season, int year) {
private static double calcInitial(int season, int year) {
double y = (year - 2000) / 1000d;
switch (season) {
case 0:
return 2451623.80984 + 365242.37404 * y + 0.05169 * Math.pow(y, 2) - 0.00411 * Math.pow(y, 3)
- 0.00057 * Math.pow(y, 4);
case 1:
return 2451716.56767 + 365241.62603 * y + 0.00325 * Math.pow(y, 2) + 0.00888 * Math.pow(y, 3)
- 0.00030 * Math.pow(y, 4);
case 2:
return 2451810.21715 + 365242.01767 * y - 0.11575 * Math.pow(y, 2) + 0.00337 * Math.pow(y, 3)
+ 0.00078 * Math.pow(y, 4);
case 3:
return 2451900.05952 + 365242.74049 * y - 0.06223 * Math.pow(y, 2) - 0.00823 * Math.pow(y, 3)
+ 0.00032 * Math.pow(y, 4);
}
return 0;
return switch (season) {
case 0 -> 2451623.80984 + 365242.37404 * y + 0.05169 * Math.pow(y, 2) - 0.00411 * Math.pow(y, 3)
- 0.00057 * Math.pow(y, 4);
case 1 -> 2451716.56767 + 365241.62603 * y + 0.00325 * Math.pow(y, 2) + 0.00888 * Math.pow(y, 3)
- 0.00030 * Math.pow(y, 4);
case 2 -> 2451810.21715 + 365242.01767 * y - 0.11575 * Math.pow(y, 2) + 0.00337 * Math.pow(y, 3)
+ 0.00078 * Math.pow(y, 4);
case 3 -> 2451900.05952 + 365242.74049 * y - 0.06223 * Math.pow(y, 2) - 0.00823 * Math.pow(y, 3)
+ 0.00032 * Math.pow(y, 4);
default -> throw new IllegalArgumentException("Unexpected value: " + season);
};
}
/**
* Calculate 24 periodic terms
*/
private double periodic24(double T) {
int[] a = new int[] { 485, 203, 199, 182, 156, 136, 77, 74, 70, 58, 52, 50, 45, 44, 29, 18, 17, 16, 14, 12, 12,
12, 9, 8 };
double[] b = new double[] { 324.96, 337.23, 342.08, 27.85, 73.14, 171.52, 222.54, 296.72, 243.58, 119.81,
297.17, 21.02, 247.54, 325.15, 60.93, 155.12, 288.79, 198.04, 199.76, 95.39, 287.11, 320.81, 227.73,
15.45 };
double[] c = new double[] { 1934.136, 32964.467, 20.186, 445267.112, 45036.886, 22518.443, 65928.934, 3034.906,
9037.513, 33718.147, 150.678, 2281.226, 29929.562, 31555.956, 4443.417, 67555.328, 4562.452, 62894.029,
31436.921, 14577.848, 31931.756, 34777.259, 1222.114, 16859.074 };
private static double periodic24(double t) {
double result = 0;
for (int i = 0; i < 24; i++) {
result += a[i] * MathUtils.cosDeg(b[i] + (c[i] * T));
result += AMPLITUDE[i] * MathUtils.cosDeg(PHASE[i] + (FREQUENCY[i] * t));
}
return result;
}
@@ -30,6 +30,7 @@ import org.openhab.binding.astro.internal.model.EclipseType;
import org.openhab.binding.astro.internal.model.Position;
import org.openhab.binding.astro.internal.model.Radiation;
import org.openhab.binding.astro.internal.model.Range;
import org.openhab.binding.astro.internal.model.Season;
import org.openhab.binding.astro.internal.model.Sun;
import org.openhab.binding.astro.internal.model.SunPhaseName;
import org.openhab.binding.astro.internal.util.DateTimeUtils;
@@ -272,8 +273,11 @@ public class SunCalc {
sun.setZodiac(ZodiacCalc.calculate(lsun, calendar.toInstant()));
SeasonCalc seasonCalc = new SeasonCalc();
sun.setSeason(seasonCalc.getSeason(calendar, latitude, useMeteorologicalSeason, zone, locale));
Season season = sun.getSeason();
var year = calendar.get(Calendar.YEAR);
if (season == null || season.getYear() != year) {
sun.setSeason(SeasonCalc.calculate(year, latitude, useMeteorologicalSeason, zone));
}
// phase
for (Entry<SunPhaseName, Range> rangeEntry : sortByValue(sun.getAllRanges()).entrySet()) {
@@ -26,6 +26,7 @@ import org.openhab.binding.astro.internal.handler.AstroThingHandler;
import org.openhab.binding.astro.internal.model.Eclipse;
import org.openhab.binding.astro.internal.model.Planet;
import org.openhab.binding.astro.internal.model.Range;
import org.openhab.binding.astro.internal.model.Season;
import org.openhab.binding.astro.internal.model.Sun;
/**
@@ -127,7 +128,10 @@ public final class DailyJobSun extends AbstractJob {
if (sun.getZodiac().getEnd() instanceof Instant when) {
schedulePublishPlanet(handler, when);
}
schedulePublishPlanet(handler, sun.getSeason().getNextSeason(), zone, locale);
if (sun.getSeason() instanceof Season season) {
schedulePublishPlanet(handler, season.getNextSeason());
}
// schedule phase jobs
Calendar cal = sun.getRise().getStart();
@@ -0,0 +1,30 @@
/*
* Copyright (c) 2010-2025 Contributors to the openHAB project
*
* See the NOTICE file(s) distributed with this work for additional
* information.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0
*
* SPDX-License-Identifier: EPL-2.0
*/
package org.openhab.binding.astro.internal.model;
import org.eclipse.jdt.annotation.NonNullByDefault;
/**
* Earth hemispheres
*
* @author Gaël L'hopital - Initial contribution
*/
@NonNullByDefault
public enum Hemisphere {
NORTHERN,
SOUTHERN;
public static Hemisphere getHemisphere(double latitude) {
return latitude < 0.0 ? SOUTHERN : NORTHERN;
}
}
@@ -13,15 +13,19 @@
package org.openhab.binding.astro.internal.model;
import java.time.Duration;
import java.time.temporal.ChronoUnit;
import java.util.Calendar;
import java.util.Locale;
import java.time.Instant;
import java.time.ZonedDateTime;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.NoSuchElementException;
import java.util.Objects;
import java.util.TimeZone;
import javax.measure.quantity.Time;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable;
import org.openhab.binding.astro.internal.util.DateTimeUtils;
import org.openhab.core.library.types.QuantityType;
import org.openhab.core.library.unit.Units;
@@ -33,122 +37,112 @@ import org.openhab.core.library.unit.Units;
*/
@NonNullByDefault
public class Season {
private @Nullable Calendar spring;
private @Nullable Calendar summer;
private @Nullable Calendar autumn;
private @Nullable Calendar winter;
private static final Map<Hemisphere, List<SeasonName>> SEASON_ORDER = Map.of(Hemisphere.NORTHERN,
List.of(SeasonName.WINTER, SeasonName.SPRING, SeasonName.SUMMER, SeasonName.AUTUMN, SeasonName.WINTER,
SeasonName.SPRING),
Hemisphere.SOUTHERN, List.of(SeasonName.SUMMER, SeasonName.AUTUMN, SeasonName.WINTER, SeasonName.SPRING,
SeasonName.SUMMER, SeasonName.AUTUMN));
private @Nullable SeasonName name;
private record LocalSeason(SeasonName name, Instant startsOn, Instant endsOn, int year) {
boolean contains(Instant when) {
return !startsOn.isAfter(when) && endsOn.isAfter(when);
}
}
private TimeZone timeZone;
private Locale locale;
private final List<LocalSeason> seasons = new ArrayList<>(5);
private final int year;
public Season(TimeZone timeZone, Locale locale) {
this.timeZone = timeZone;
this.locale = locale;
public Season(double latitude, boolean useMeteorologicalSeason, TimeZone zone, Instant... equiSols) {
// Expect to receive last of previous year, all from current year, first of next year
if (equiSols.length != SeasonName.values().length + 2) {
throw new IllegalArgumentException("Incorrect number of seasons provided");
}
var hemisphere = Hemisphere.getHemisphere(latitude);
List<Instant> moments = Arrays.stream(equiSols).sorted()
.map(i -> useMeteorologicalSeason ? DateTimeUtils.atMidnightOfFirstMonthDay(i, zone) : i).toList();
for (int i = 0; i < moments.size() - 1; i++) {
var current = moments.get(i);
var next = moments.get(i + 1);
var seasonName = Objects.requireNonNull(SEASON_ORDER.get(hemisphere)).get(i);
ZonedDateTime zonedDateTime = current.atZone(zone.toZoneId());
seasons.add(new LocalSeason(seasonName, current, next, zonedDateTime.getYear()));
}
year = seasons.stream().mapToInt(LocalSeason::year).max().orElseThrow(NoSuchElementException::new);
}
public int getYear() {
return year;
}
private Instant getSeasonStart(SeasonName season) {
return seasons.stream().filter(s -> s.name.equals(season) && s.year == year).map(s -> s.startsOn).findFirst()
.orElseThrow(NoSuchElementException::new);
}
/**
* Returns the date of the beginning of spring.
*/
@Nullable
public Calendar getSpring() {
return spring;
}
/**
* Sets the date of the beginning of spring.
*/
public void setSpring(@Nullable Calendar spring) {
this.spring = spring;
public Instant getSpring() {
return getSeasonStart(SeasonName.SPRING);
}
/**
* Returns the date of the beginning of summer.
*/
@Nullable
public Calendar getSummer() {
return summer;
}
/**
* Sets the date of the beginning of summer.
*/
public void setSummer(@Nullable Calendar summer) {
this.summer = summer;
public Instant getSummer() {
return getSeasonStart(SeasonName.SUMMER);
}
/**
* Returns the date of the beginning of autumn.
*/
@Nullable
public Calendar getAutumn() {
return autumn;
}
/**
* Sets the date of the beginning of autumn.
*/
public void setAutumn(@Nullable Calendar autumn) {
this.autumn = autumn;
public Instant getAutumn() {
return getSeasonStart(SeasonName.AUTUMN);
}
/**
* Returns the date of the beginning of winter.
*/
@Nullable
public Calendar getWinter() {
return winter;
public Instant getWinter() {
return getSeasonStart(SeasonName.WINTER);
}
/**
* Returns the date of the beginning of winter.
*/
public void setWinter(@Nullable Calendar winter) {
this.winter = winter;
private LocalSeason getSeason(Instant when) {
return seasons.stream().filter(s -> s.contains(when)).findFirst().orElseThrow(NoSuchElementException::new);
}
/**
* Returns the current season name.
*/
@Nullable
public SeasonName getName() {
return name;
}
/**
* Sets the current season name.
*/
public void setName(@Nullable SeasonName name) {
this.name = name;
return getSeason(Instant.now()).name;
}
/**
* Returns the next season.
*/
public Calendar getNextSeason() {
return DateTimeUtils.getNextFromToday(timeZone, locale, spring, summer, autumn, winter);
public Instant getNextSeason() {
return getSeason(Instant.now()).endsOn;
}
/**
* Returns the next season name.
*/
public SeasonName getNextName() {
int ordinal = name == null ? 0 : name.ordinal() + 1;
if (ordinal > 3) {
ordinal = 0;
}
return SeasonName.values()[ordinal];
return getSeason(Instant.now()).name.next();
}
/**
* Returns the time left for current season
*/
public QuantityType<Time> getTimeLeft() {
final Calendar now = Calendar.getInstance(timeZone, locale);
final Calendar next = getNextSeason();
final Duration timeLeft = Duration.of(next.getTimeInMillis() - now.getTimeInMillis(), ChronoUnit.MILLIS);
var now = Instant.now();
var timeLeft = Duration.between(now, getSeason(now).endsOn);
return new QuantityType<>(timeLeft.toDays(), Units.DAY);
}
public Instant getNext(Instant when) {
return getSeason(when).endsOn;
}
}
@@ -24,5 +24,10 @@ public enum SeasonName {
SPRING,
SUMMER,
AUTUMN,
WINTER
WINTER;
public SeasonName next() {
SeasonName[] values = values();
return values[(this.ordinal() + 1) % values.length];
}
}
@@ -13,9 +13,7 @@
package org.openhab.binding.astro.internal.model;
import java.util.HashMap;
import java.util.Locale;
import java.util.Map;
import java.util.TimeZone;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable;
@@ -34,7 +32,7 @@ public class Sun extends RiseSet implements Planet {
private Zodiac zodiac = Zodiac.NULL;
private Season season = new Season(TimeZone.getDefault(), Locale.getDefault());
private @Nullable Season season = null;
private Eclipse eclipse = new Eclipse(EclipseKind.PARTIAL, EclipseKind.TOTAL, EclipseKind.RING);
@@ -265,6 +263,7 @@ public class Sun extends RiseSet implements Planet {
/**
* Returns the seasons.
*/
@Nullable
public Season getSeason() {
return season;
}
@@ -40,6 +40,7 @@ public class DateTimeUtils {
public static final double JD_UNIX_EPOCH = 2440587.5; // 1970-01-01 00:00 UTC
private static final double J1970 = JD_UNIX_EPOCH + 0.5; // 1970-01-01 12:00 UTC (julian solar noon)
private static final int JULIAN_CENTURY_DAYS = 36525; // Length of a Julian Century in days
private static final double SECONDS_PER_DAY = 60 * 60 * 24;
/** Constructor */
private DateTimeUtils() {
@@ -412,4 +413,23 @@ public class DateTimeUtils {
}
return -1;
}
public static Instant jdToInstant(double jd) {
double secondsFromEpoch = (jd - JD_UNIX_EPOCH) * SECONDS_PER_DAY;
long epochSeconds = (long) Math.floor(secondsFromEpoch);
long nanos = Math.round((secondsFromEpoch - epochSeconds) * 1_000_000_000L);
// correct if rounded is above 1 second
if (nanos == 1_000_000_000L) {
epochSeconds++;
nanos = 0;
}
return Instant.ofEpochSecond(epochSeconds, nanos);
}
public static Instant atMidnightOfFirstMonthDay(Instant instant, TimeZone zone) {
return instant.atZone(zone.toZoneId()).withDayOfMonth(1).truncatedTo(ChronoUnit.DAYS).toInstant();
}
}
@@ -220,6 +220,7 @@
<item-type>String</item-type>
<label>Season Name</label>
<description>The name of the current season</description>
<category>oh:astro:season</category>
<tags>
<tag>Status</tag>
<tag>Info</tag>
@@ -238,6 +239,7 @@
<item-type>DateTime</item-type>
<label>Spring</label>
<description>The beginning of spring</description>
<category>calendar</category>
<tags>
<tag>Calculation</tag>
<tag>Timestamp</tag>
@@ -249,6 +251,7 @@
<item-type>DateTime</item-type>
<label>Summer</label>
<description>The beginning of summer</description>
<category>calendar</category>
<tags>
<tag>Calculation</tag>
<tag>Timestamp</tag>
@@ -260,6 +263,7 @@
<item-type>DateTime</item-type>
<label>Autumn</label>
<description>The beginning of autumn</description>
<category>calendar</category>
<tags>
<tag>Calculation</tag>
<tag>Timestamp</tag>
@@ -271,6 +275,7 @@
<item-type>DateTime</item-type>
<label>Winter</label>
<description>The beginning of winter</description>
<category>calendar</category>
<tags>
<tag>Calculation</tag>
<tag>Timestamp</tag>
@@ -0,0 +1,6 @@
<svg height="64" width="64" viewBox="0 0 274 274" xmlns="http://www.w3.org/2000/svg">
<path fill="#e86016"
d="M273.95 219.16c0 30.261-24.528 54.792-54.79 54.792H54.79C24.53 273.952 0 249.422 0 219.16V54.79C0 24.53 24.53 0 54.79 0h164.37c30.262 0 54.79 24.53 54.79 54.79z" />
<path fill="#fff"
d="M242.472 154.694c-8.047 2.6-30.666-6.893-13.476-11.978 9.757-7.122 8.74-22.482 6.57-33.425-3.442-14.589-6.888-29.314-14.665-42.308-6.247-11.25-14.817-26.588-29.768-25.468-6.19 3.33-10.682 15.083-21.09 10.388-9.857-3.109-19.806-6.254-29.348-9.831-16.995-7.126-37.566-5.395-52.192-17.96-6.967 20.558-18.466 39.259-25.815 59.654-5.905 8.397-10.077 20.385-12.079 28.564-9.277.965-22.21-2.03-27.74 7.447.072 12.16 7.202 23.53 9.75 35.507a110.63 110.63 0 0019.886 37.096c6.638 13.591 24.91 17.723 37.382 9.774 4.418-2.23 9.445-8.302 5.104-.411-4.227 11.845-4.287 29.622 9.118 35.478 20.156 6.391 43.285-6.852 51.264-25.739 1.517-9.046-10.33-19.482-4.55-28.785 13.424 1.47 15.566 18.693 19.71 29.081 3.802 12.846 6.727 26.234 13.826 37.78 14.722 8.837 3.956-13.924.274-19.497-6.41-9.814-9.378-21.045-14.845-31.38-4.588-6.81-10.484-25.704 4.314-21.486.396 12.902 11.933 24.107 25.161 22.177 20.442-1.558 38.827-15.744 47.2-34.158 1.546-3.985-.345-8.441-3.991-10.52zm-10.614 11.915c.026 12.516-17.03-2.675-24.752.86-13.22 3.091-5.641 15.499 3.873 17.816 9.91 9.024-12.87 2.34-15.256-4.025-3.927-4.593-12.669-9.16-6.387.326 4.796 8.313-8.43-5.6-12.464-7.129-8.143-6.487-22.18-8.65-28.093 1.962-8.37 7.286-2.457 19.544-.907 28.64-.808 6.498-12.284-14.501-11.966.176-.35 6.937 4.4 19.905-5.749 21.256 4.305-6.551-4.614-23.869-8.163-9.63-.81 4.919-1.056 17.409-6.089 6.586-1.336-9.474-13.289 9.969-10.195-2.951 4.053-4.636 8.759-8.566.947-12.242-9.676-7.277 21.537 1.607 14.472-10.206-4.948-3.109-9.543-2.385-1.315-3.024 9.677-2.333 24.108-8.608 22.324-20.57-6.092-11.699-20.639-3.973-28.56 1.49-11.184 7.602-23.452 18.752-38.02 15.481 8-7.745 21.264-9.723 31.267-15.276 10.777-2.073 12.846-17.731-.29-16.217-12.06-2.043-21.407 6.085-31.019 10.65-5.353 2.359-17.961-3.654-5.903-4.054 10.134 2.708 21.227-11.456 7.642-15.567-7.64-1.74-25.423 4.629-26.27-4.717 7.667 2.325 12.817-8.191 2.486-7.655-5.177-.138-21.307 1.19-12.198-6.85-8.004-.434-9.75-19.414-1.213-8.802 5.334 11.36 24.16-1.108 25.114 14.439 4.73 14.553 19.902 4.151 15.332-2.96 3.804 10.283 13.782 19.426 24.937 20.424 8.842.93 3.023-17.32 9.176-7.145 7.106 7.099 14.685 16.593 25.482 17.086 14.939-6.738-2.714-23.225-11.953-26.542-17.725-7.963-39.092-9.218-53.172-24.08-7.353-11.234 15.11 3.97 19.703 5.607 10.37 4.638 21.052 14.168 33.04 11.25 10.485-10.177-5.957-23.101-15.453-26.66-9.968-4.834-23.413-9.26-25.614-21.754 8.326 6.987 17.766 13.829 28.664 15.794 13.586-5.693-3.647-19.524-11.732-23.117-4.586-2.087-13.043-9.908-2.149-6.288 11.749-1.527-1.638-11.742-7.946-12.116-12.774-5.271 10.39-2.369 3.131-10.134-2.141-4.52-4.67-16.838 1.703-6.26 2.672 7.858 11.221 6.17 16.534 3.26-2.188 4.234-7.136 24.078 1.993 12.758 5.77-10.585 3.258 10.34 2.655 15.105-3.325 7.468 3.623 25.299 9.88 19.139-.257-7.257-2.222-20.927 3.804-24.013 6.18 12.118-1.101 25.499-1.286 38.15-3.159 9.275 4.69 27.079 14.899 20.37 9.607-20.381 7.497-43.918 15.965-64.658 4.607 17.924-2.363 35.836-6.3 53.17-6.95 11.057-11.3 25.375-7.662 38.275 4.562 11.59 26.057 2.528 19.768-9.17-1.034-4.967-13.004-17.726-5.997-17.127 4.558 14.929 20.39 3.814 20.224-7.308 4.518-12.362-7.678-18.765-11.888-28.3 6.016 8.35 22.215 11.248 20.317-3.19-.068-6.44-10.112-13.314-8.57-17.829 13.275 10.189 10.994-9.985 12.89-18.313 11.935 3.437 4 17.397 3.37 26.04 1.187 8.852 15.721-9.944 8.968 3.342-3.824 9.2-17.727 15.72-15.06 26.289 8.334 4.85 14.344-15.093 24.946-10.877-4.42 10.572-17.415 13.754-24.836 21.985-9.131 3.674-14.148 23.834.597 18.353 11.027-4.016 20.308-12.16 31.788-14.897 7.114 4.652-10.562 11.054-15.134 13.44-15.133 6.588-35.23 9.586-42.77 26.307 1.31 10.66 17.716 4.492 22.7-1.967 4.325-6.854 20.949-7.405 8.564-.033-5.362 11.006 18.27 5.852 20.835-1.786 2.5 6.274 21.51 2.71 17.927 7.78-1.821.73-3.704 1.286-5.586 1.833z" />
</svg>

After

Width:  |  Height:  |  Size: 4.0 KiB

@@ -0,0 +1,8 @@
<svg height="64" width="64" viewBox="0 0 274 274" xmlns="http://www.w3.org/2000/svg">
<path fill="#b3d92c"
d="M273.95 219.161c.876 30.481-27.57 57.17-57.89 54.79-54.696-.047-109.395.095-164.09-.071-29.767-.72-54.535-29.06-51.97-58.593.047-54.439-.095-108.88.071-163.317C.791 22.203 29.131-2.565 58.664 0c54.438.047 108.879-.095 163.316.071 29.767.719 54.535 29.06 51.97 58.593v160.497z" />
<path fill="#fff"
d="M59.326 47.752c.084-5.102-7.718-8.716-4.822-13.795 5.78-1.578 1.14-14.6 9.583-11.653 5.513 3.516 9.222-6.93 14.708-1.995 5.124 2.671-.354 6.923-3.295 7.794-3.115 5.324 1.89 10.896 6.157 13.714 2.917 4.026 9.887 1.95 6.552-3.1-4.801-6.694 9.217-7.815 6.379-.375-4.35 4.573-3.47 13.645 3.34 15.192 7.784.425-1.975-10.58 5.97-11.323 8.348.411.112 9.044-.347 13.232-2.178 5.073 7.467 11.46 8.233 4.114-1.392-4.437 2.875-9.661 6.698-4.918 3.411 5.692-8.77 6.975-4.995 13.691 1.767 5.66 7.217 8.903 10.071 13.945 10.443 15.462 18.837 33.547 18.31 52.583 1.234 5.655-4.691 9.858-9.789 8.024-5.595-1.226-7.07-7.39-8.005-12.218-1.024-7.199-1.162-14.526-3.143-21.569-3.25-15.334-8.488-30.683-17.883-43.364-5-4.282-12.656 9.533-15.293.123.024-5.936 8.37-3.523 10.506-4.647.457-7.106-10.154-10.842-14.24-4.795-4.588 5.2-11.013-4.238-4.646-5.862 3.575 2.016 11.316 1.546 6.532-3.926-4.206-3.063-12.1-8.134-16.442-3.078-1.675 4.356-6.58 11.564-10.139 4.206z" />
<path fill="#fff"
d="M30.193 178.158c4.608-9.605 17.084-19.721 5.754-29.74-2.211-16.767 18.688-23.231 31.787-18.573 7.931.218 26.717 10.589 27.567.71-7.397-11.673-23.966-4.857-35.345-6.767-11.123 1.473-36.356-7.846-22.993-21.269 13.002-7.561-12.562-24.345 7.304-27.807 12.853 2.427 28.784-11.315 40.915 1.379 17.206 10.11 29.346 28.551 31.459 48.436-13.127-4.976-15.468-26.956-31.92-24.86-13.781 9.26 4.963 21.24 13.508 25.684 11.348 2.63 13.831 20.766-.956 15.514-12.584-3.455-21.774 7.84-12.98 18.278-3.84 7.588-7.606 22.599 6.872 17.289 8.542-2.362 17.166-22.502 24.541-15.565-7.58 8.005-15.467 15.884-20.255 26.049-5.898 9.925-13.079 22.73-25.61 24.134-12.202-3.837-24.678-9.069-35.651-15.02-4.565-4.505-7.192-11.87-3.997-17.872zm114.085-64.918c-7.328-21.768-7.532-49.76 10.94-66.177 10.147-4.928 22.3 4.432 31.152-5.363 17.055-2.358 21.527 15.985 19.307 28.539 11.842 8.36 9.127 24.549-3.68 30.555-12.118 5.662-26.004 8.007-35.963 17.72-3.985 4.966-13.76 12.025-8.283.705 7.525-9.657 16.584-18.801 20.687-30.536 2.088-18.243-19.07-8.557-21.357 3.042-7.402 3.072-3.749 29.112-12.803 21.515zm47.285 66.323c-11.239-8.71-31.742-19.584-42.174-17.45 4.107 8.328 30.031 17.45 10.619 24.874-4.266 6.69 10.558 18.994-3.266 23.836-14.589 5.402-10.552-18.573-18.48-19.141-11.517 16.405-24.167-10.312-11.156-17.955 9.628-14.346-9.227-10.533-13.474-1.613-12.21 13.982-21.862 34.672-14.088 52.998 8.381 15.895 27.27 9.516 40.495 10.898 10.497 8.906 23.488 18.82 38.043 11.944 16.484-5.907 15.187-25.927 25.441-37.795 5.296-11.344-4.652-22.843-11.96-30.596zm59.431-34.556c-5.797-7.654-26.316-2.437-18.485-17.349-2.573-13.896-20.233-16.232-31.948-15.327-18.45 1.929-34.435 13.175-46.978 26.225 1.506 5.762 12.117-8.488 18.63-6.918 9.208-4.473 25.956-1.715 16.357 10.561 4.762 4.238 20.764 4.112 14.633 16.142-12.958 6.393-27.835-10.015-42.537-6.825-17.348 4.13 12.834 9.14 18.177 13.985 13.415 7.618 23.287 20.533 37.291 27.09 12.52 5.115 22.706-6.667 25.283-16.332 11.796-4.399 22.004-19.843 10.526-30.217.072-.496-.95-.566-.949-1.035z" />
</svg>

After

Width:  |  Height:  |  Size: 3.3 KiB

@@ -0,0 +1,6 @@
<svg height="64" width="64" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 274 274">
<path fill="#ffcf09"
d="M273.95 219.16c0 30.261-24.528 54.792-54.79 54.792H54.79C24.53 273.952 0 249.422 0 219.16V54.79C0 24.53 24.53 0 54.79 0h164.37c30.262 0 54.79 24.53 54.79 54.79z" />
<path fill="#fff"
d="M77.52 154.764C68.87 122.778 88.027 89.9 120.31 81.33c32.284-8.572 65.465 10.41 74.117 42.397 8.65 31.984-10.509 64.862-42.792 73.433-32.283 8.57-65.465-10.412-74.115-42.396zM112.168 209.398l-39.871 39.111 14.25-53.767 10.963 10.497zM206.77 162.814l39.474 39.504-54.266-14.12 10.595-10.863zM159.753 69.08l39.868-39.108-14.249 53.765L174.41 73.24zM65.15 115.666L25.68 76.163l54.263 14.116-10.593 10.864zM69.079 172.166l-56.102-.277 48.445-28.037.262 15.105zM169.218 205.504l-.281 55.587-28.292-48 15.243-.26zM202.867 106.287l56.104.276-48.447 28.037-.26-15.104zM102.727 72.947l.278-55.585 28.295 48-15.244.257z" />
</svg>

After

Width:  |  Height:  |  Size: 934 B

@@ -0,0 +1,12 @@
<svg height="64" width="64" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 274 274">
<path fill="#02b1e8"
d="M273.95 219.161c0 30.26-24.528 54.79-54.79 54.79H54.79c-30.26 0-54.79-24.53-54.79-54.79V54.79C0 24.53 24.53 0 54.79 0h164.37c30.262 0 54.79 24.53 54.79 54.79z" />
<path fill="#02b1e8"
d="M273.95 219.161c0 30.26-24.528 54.79-54.79 54.79H54.79c-30.26 0-54.79-24.53-54.79-54.79V54.79C0 24.53 24.53 0 54.79 0h164.37c30.262 0 54.79 24.53 54.79 54.79z" />
<path fill="#02b1e8"
d="M273.95 219.161c0 30.26-24.528 54.79-54.79 54.79H54.79c-30.26 0-54.79-24.53-54.79-54.79V54.79C0 24.53 24.53 0 54.79 0h164.37c30.262 0 54.79 24.53 54.79 54.79z" />
<path fill="#fff"
d="M100.332 115.657l-1.429 41.814 35.498 22.144 36.927-19.672 1.427-41.814-35.498-22.143zm60.627 36.523l-25.622 14.353-25.242-15.013.38-29.365 25.624-14.353 25.24 15.013z" />
<path fill="#fff"
d="M240.36 175.275l-15.436 7.932-22.482-12.807 21.133-12.515-4.24-7.923-16.14 9.041-16.96-10.625.134-5.418.092.174.258-13.714 17.358-10.835 16.828 10.986 6.061-8.217-23.098-13.86 22.187-13.662 18.07 9.363 3.965-7.716-19.526-9.163 1.74-19.808-8.949-.747-.848 17.336-22.333 13.066-.271-24.56-8.983-.288-.24 18.56-18.433 8.98-3.94-2.582.115.006-1.34-.807-5.921-3.881.24.456-4.576-2.76-.707-20.45 17.926-9.078-4.083-9.36-23.552 13.074-.739-26.045 17.146-10.969-4.7-7.291-17.7 12.33-16.283-11.412-5.122 7.377 14.59 9.401.15 25.874-21.406-12.044-4.74 7.636 15.883 9.447-.526 19.81-10.91 5.813.282.015-6.219 3.435-18.061-9.614 1.1-20.065-10.148-1.143-.454 26.934L53.627 80.58 52.7 60.248l-8.665.425 1.83 21.492-18.027 8.396 3.829 8.124 15.436-7.934 22.482 12.807-21.133 12.516 4.242 7.923 16.122-9.03 16.016 9.804.534 16.953-.054 2.816-17.356 10.836-16.828-10.986-6.063 8.216 23.098 13.86-22.186 13.665-18.07-9.365-3.965 7.717 19.527 9.161-1.741 19.809 8.95.747.846-17.336 22.334-13.066.27 24.56 8.984.286.24-18.46 16.966-9.4 5.195 2.786-.071-.003 6.181 3.726.358.235-.013-.027 5.245 3.162.705 20.45-17.927 9.079 4.085 9.361 23.551-13.075.74 26.046-17.146 10.969 4.7 7.29 17.7-12.33 16.284 11.412 5.12-7.378-14.59-9.4-.148-25.873 21.406 12.042 4.74-7.634-15.91-9.463.83-19.826 12.27-6.785-.119-.004 4.408-2.435 18.062 9.613-1.1 20.066 10.147 1.143.454-26.935 22.925 12.383.927 20.333 8.665-.426-1.83-21.492 18.026-8.395zm-45.046-.984a2.727 2.727 0 01-3.747.93l-17.508-10.547-36.84 19.625-.583 22.075a2.731 2.731 0 01-2.728 2.658h-.073a2.73 2.73 0 01-2.657-2.802l.577-21.832-33.078-20.633-18.364 10.365a2.727 2.727 0 01-3.72-1.035 2.73 2.73 0 011.036-3.718l15.772-8.903-.062-.038 1.486-43.493-15.497-9.335a2.731 2.731 0 012.818-4.677l14.297 8.612 37.767-20.119.55-20.814c.04-1.507 1.272-2.722 2.801-2.657a2.73 2.73 0 012.656 2.8l-.535 20.31 36.426 22.724 17.294-9.763a2.73 2.73 0 012.685 4.755l-17.895 10.1-1.403 41.066 17.596 10.6a2.728 2.728 0 01.929 3.747zm-11.41-35.984l-.091.145-.009-.336z" />
</svg>

After

Width:  |  Height:  |  Size: 2.8 KiB

@@ -0,0 +1,28 @@
<svg height="64" width="64" viewBox="0 0 574 574" xmlns="http://www.w3.org/2000/svg">
<path fill="#FFCF09"
d="M273.95 519.16c0 30.261-24.528 54.792-54.79 54.792H54.79C24.53 573.952 0 549.422 0 519.16V354.79C0 324.53 24.53 300 54.79 300h164.37c30.262 0 54.79 24.53 54.79 54.79v164.37z" />
<path fill="#FFF"
d="M77.52 454.764c-8.65-31.986 10.508-64.864 42.79-73.434 32.284-8.572 65.466 10.41 74.117 42.397 8.65 31.984-10.509 64.862-42.792 73.433-32.282 8.57-65.465-10.412-74.114-42.396zm34.648 54.634l-39.87 39.111 14.25-53.767 10.962 10.497 14.658 4.159zm94.602-46.584l39.475 39.504-54.267-14.12 10.596-10.863 4.196-14.521zm-47.017-93.734l39.869-39.108-14.25 53.765-10.962-10.497-14.657-4.16zM65.15 415.666l-39.47-39.503 54.262 14.116-10.593 10.864-4.198 14.523zm3.93 56.5l-56.103-.277 48.445-28.037.262 15.105 7.395 13.209zm100.138 33.338l-.281 55.587-28.292-48 15.243-.26 13.33-7.327zm33.65-99.217l56.103.276-48.446 28.037-.26-15.104-7.397-13.21zm-100.141-33.34l.278-55.585 28.295 48-15.244.257-13.329 7.328z" />
<path fill="#e86016"
d="M573.95 519.16c0 30.261-24.528 54.792-54.79 54.792H354.79c-30.26 0-54.79-24.53-54.79-54.791V354.79c0-30.26 24.53-54.79 54.79-54.79h164.37c30.262 0 54.79 24.53 54.79 54.79z" />
<path fill="#fff"
d="M542.472 454.694c-8.095.618-34.962-5.61-14.91-11.072 19.423-11.34 3.68-36.773 4.35-54.698-8.701-17.34-16.423-35.546-32.232-47.698-12.893-15.69-17.523 29.623-35.234 7.42-5.087-4.843-15.726 3.478-20.89-5.412-12.707-9.119-17.385 1.173-28.741-8.85-13.605 5.831-32.897-27.809-30.452.71-4.848 17.215-14.53 26.34-20.465 45.932-1.231 14.16-16.926 11.437-8.564 26.023-4.686 15.075-44.45-4.866-29.096 20.352 1.812 22.77 10.474 46.182 26.217 62.714 7.001 24.12 33.428 18.524 46.27 4.79-8.766 13.304-11.034 43.504 15.143 43.463 18.25 2.727 42.573-16.66 41.392-34.166-7.766-7.978-11.088-33.092 4.249-18.204 10.143 18.996 14.775 40.232 22.766 60.056 15.176 22.317 11.551-7.928 1.115-16.689-6.445-17.974-19.915-35.99-19.314-54.924 18.654.451 15.364 38.803 40.044 23.98 19.254-3.862 37.915-17.45 42.985-36.743l-1.307-3.455zm-10.613 11.915c-1.287 6.288 6.579 8.865-6.213 3.345-12.815-6.798-42.453 4.691-17.017 13.657 23.404 10.546-14.678 7.244-16.54-6.245-11.69-9.7-10.542-5.908-2.02 4.11 3.993 19.367-13.397-18.882-26.398-12.32-26.92-.714-15.74 33.97-15.448 41.513-3.957-9.53-16.792-20.555-11.282-2.609 3.394 11.055-11.308 32.559-5.93 9.545-2.154-22.837-10.952 1.632-10.998 11.235-6.159 7.33 1.056-20.725-11.063-5.751-18.517 13.825 18.933-21.656-8.448-14.712.591-7.463 37.15-1.926 18.259-10.058-20.362-7.52 24.025-.378 22.699-17.682 5.827-26.166-28.93-5.159-38.328 3.106-7.352 6.341-48.288 16.306-24.436 4.27 10.989-5.977 56.606-17.128 31.4-28.408-15.638-3.557-41.288 20.063-48.656 7.908 12.447 3.27 38.004-14.465 12.967-15.862-8.638 1.656-42.134-5.036-18.354-5.663 20.272-9.88-35.667-5.02-13.76-12.455-8.388-6.385-15.417-23.836-.429-9.163 3.798 5.219 18.717 11.94 14.638-1.009 6.806 18.244 30.345 33.02 22.964 7.943 4.333 11.905 24.972 33.245 32.234 19.187-2.317-21.91 11.99 16.391 23.445 13.596 29.21 1.143-4.55-33.237-21.597-30.533-13.203-3.161-43.557-17.41-41.197-25.59 19.57 10.64 39.342 23.235 62.07 25.402-3.165-21.78-23.425-30.436-40.448-38.985-11.36-4.978-12.743-18.684-.002-7.202 6.593 10.025 37.01 21.25 24.852-.075-3.091-7.65-41.714-24.741-18.846-18.742 25.327 8.253-11.408-17.387-13.05-15.093 19.054 7.166 7.893-12.12 5.704-19.411 6.737 7.094 16.05 20.712 22.434 7.706-4.556 7.736-4.87 34.514.559 14.115 12.805-17.842-.7 18.987 4.455 26.546 1.58 12.81 12.714 18.206 9.78 1.772-4.128-10.545 4.207-34.837 5.325-11.952 2.713 18.28-10.19 37.206 1.49 54.025 16.37 13.026 16.165-32.875 20.909-44.328-.535-11.016 7.408-31.855 6.959-8.718-1.605 23.021-9.023 44.945-17.885 66.13-5.16 19.94 20.842 27.731 23.352 5.802-6.809-5.13-17.835-38.915-7.357-17.836 19.521 22.079 27.913-23.187 9.537-32.36-11.133-24.649 18.292 22.842 18.271-5.517 3.866-7.328-20.89-29.913-4.81-17.617 16.296 12.593 4.277-43.576 12.056-18.691 1.52 8.951 15.288 1.332 3.296 13.358-5.726 6.989-3.631 26.034 3.142 9.907 16.004-5.367-14.768 23.28-14.139 31.676 7.689 11.694 24.556-24.199 29.188-12.311-9.419 14.665-43.15 25.285-35.301 43.136 15.03.144 38.947-24.887 46.185-16.27-17.422 14.09-41.15 17.647-58.438 30.835-20.626 17.07 19.472 15.776 24.222 1.051 16.259-10.135 7.542 4.246-1.814 8.951 9.862 10.655 30.504-16.19 31.629-1.61 8.947-1.718 27.92-.5 6.183 4.951z" />
<path fill="#B3D92C"
d="M573.95 219.161c0 30.26-24.528 54.79-54.79 54.79H354.79c-30.26 0-54.79-24.53-54.79-54.79V54.79C300 24.53 324.53 0 354.79 0h164.37c30.262 0 54.79 24.53 54.79 54.79v164.371z" />
<path fill="#FFF"
d="M359.327 47.752c.134-5.21-10.975-12.162-2.503-15.06 1.876-4.213.151-13.643 7.969-10.093 5.798 2.704 7.042-6.582 13.051-2.65 5.59 1.696 2.748 7.193-1.475 7.104-5.4 5.457 1.817 13.38 7.447 15.97 4.35 3.515 6.982-1.383 3.878-4.996-2.594-7.048 9.057-6.65 6.894.315-3.642 4.486-4.362 12.287 2.546 14.886 4.469 2.05 5.16-2.723 3.197-5.86-1.308-5.633 8.317-7.725 7.508-1.184-2.545 4.68-7.905 11.691-1.026 16.248 5.11 2.815 5.487-4.123 4.969-7.395 2.635-6.223 11.845 1.794 5.228 4.87-6.527 3.395-3.876 11.038 1.097 15.41 7.745 8.905 13.528 19.411 18.047 30.197 4.223 10.732 6.845 22.451 5.34 33.523-2.578 6.614-13.932 5.103-15.71-2.307-3.272-7.964-1.87-16.506-4.26-24.63-3.01-16.025-8.384-32.128-17.96-45.886-5.537-5.726-9.81 7.168-15.161 1.77-3.193-6.276 6.12-7.713 9.49-5.807 2.723-5.111-7.004-11.448-11.103-8.002-2.845 3.144-10.035 6.586-10.041-1.006 1.103-6.63 8.978 2.036 10.789-2.978-.624-5.679-8.301-7.356-12.772-8.777-7.192-1.63-5.789 8.887-11.632 9.586-1.745-.2-3.08-1.659-3.807-3.246v-.002z" />
<path fill="#fff"
d="M330.194 178.158c7.83-9.708 13.718-22.133 5.602-32.763.768-13.887 17.744-19.206 29.399-16.293 9.198.385 24.411 10.679 30.08 2.104-6.376-12.222-22.082-5.79-32.881-7.355-9.719-.113-21.323-1.07-27.837-9.213-5.752-9.844 13.154-16.235 4.115-26.32-9.522-10.848 7.956-14.977 15.573-14.118 12.838-6.788 28.405-2.975 38.338 6.992 13.225 10.584 22.264 26.44 24.059 43.335-12.562-4.862-14.465-23.593-28.996-24.98-16.543 3.086-1.706 22.16 8.402 24.44 8.457.873 18.892 19.29 4.017 16.64-11.925-3.771-25.377 6.953-16.015 18.183-2.13 7.008-8.12 21.317 5.45 18.276 11.027-2.49 14.04-19.08 26.532-17.681-6.529 9.912-16.746 17.057-21.121 28.483-5.448 9.466-12.064 19.555-22.888 23.284-13.407-2.278-25.388-9.564-37.594-14.89-4.682-4.507-7.503-12.015-4.235-18.124zm114.085-64.918c-7.43-21.746-7.424-49.743 10.939-66.177 10.154-4.625 22.868 3.982 31.42-5.422 13.09-2.195 23.775 13.727 18.056 25.302 5.807 9.008 15.1 21.499 2.613 29.836-10.982 9.949-27.658 9.275-38.588 19.432-3.16 4.061-16.772 15.177-10.495 2.669 7.29-10.58 18.478-19.99 20.81-33.05-4.736-15.93-21.107-1.964-23.702 8.093-3.562 3.506-4.733 26.868-11.053 19.317zm47.284 66.323c-12.266-9.947-27.314-15.753-42.518-19.471.136 11.003 26.328 13.608 14.663 25.28-12.948 4.143 9.225 22.667-7.649 25.535-12.364 4.053-11.656-17.762-16.956-18.676-8.14 10.362-22.498-.465-16.716-11.423 3.039-4.343 12.982-17.947 1.696-16.634-14.381 7.699-22.859 23.571-26.515 39.01-2.818 11.29.12 24.94 11.074 30.806 11.382 7.288 26.715-4.537 37.008 5.625 10.183 13.766 33.394 13.7 43.618.046 3.721-13.149 13.973-24.246 15.646-37.679-.966-9.013-7.509-16.031-13.351-22.419zm59.432-34.556c-8.404-5.868-25.064-5.565-19.14-19.821-5.595-13.078-22.547-14.018-34.724-12.386-17.085 2.92-31.762 13.5-43.547 25.756 4.891 3.536 11.492-8.3 18.437-7.258 8.456-4.212 25.05-.972 16.82 10.483 4.185 6.2 20.832 3.343 14.565 15.823-8.623 7.643-20.286-4.192-30.117-4.737-4.88-1.62-20.178-2.905-18.102 1.87 11.5 7.069 25.71 9.04 35.544 18.936 10.652 8.382 20.94 22.007 36.144 19.65 11.831-4.13 12.329-19.209 24.108-23.535 7.517-6.889 8.11-18.108.012-24.781z" />
<g>
<path fill="#02B1E8"
d="M273.95 219.161c0 30.26-24.528 54.79-54.79 54.79H54.79c-30.26 0-54.79-24.53-54.79-54.79V54.79C0 24.53 24.53 0 54.79 0h164.37c30.262 0 54.79 24.53 54.79 54.79v164.371z" />
<path fill="#02B1E8"
d="M273.95 219.161c0 30.26-24.528 54.79-54.79 54.79H54.79c-30.26 0-54.79-24.53-54.79-54.79V54.79C0 24.53 24.53 0 54.79 0h164.37c30.262 0 54.79 24.53 54.79 54.79v164.371z" />
<path fill="#02B1E8"
d="M273.95 219.161c0 30.26-24.528 54.79-54.79 54.79H54.79c-30.26 0-54.79-24.53-54.79-54.79V54.79C0 24.53 24.53 0 54.79 0h164.37c30.262 0 54.79 24.53 54.79 54.79v164.371z" />
<path fill="#FFF"
d="M100.332 115.657l-1.429 41.814 35.498 22.144 36.927-19.672 1.427-41.814-35.498-22.143-36.925 19.67zm60.626 36.523l-25.621 14.353-25.242-15.013.38-29.365 25.624-14.353 25.24 15.013-.38 29.365z" />
<path fill="#FFF"
d="M240.36 175.275l-15.436 7.932-22.482-12.807 21.133-12.515-4.24-7.923-16.14 9.041-16.96-10.625.134-5.418.092.174.258-13.714 17.358-10.835 16.828 10.986 6.061-8.217-23.098-13.86 22.187-13.662 18.07 9.363 3.965-7.716-19.526-9.163 1.74-19.808-8.949-.747-.848 17.336-22.333 13.066-.271-24.56-8.983-.288-.24 18.56-18.433 8.98-3.94-2.582.115.006-1.34-.807-5.921-3.881.24.456-4.576-2.76-.707-20.45 17.926-9.078-4.083-9.36-23.552 13.074-.739-26.045 17.146-10.969-4.7-7.291-17.7 12.33-16.283-11.412-5.122 7.377 14.59 9.401.15 25.874-21.406-12.044-4.74 7.636 15.883 9.447-.526 19.81-10.91 5.813.282.015-6.219 3.435-18.061-9.614 1.1-20.065-10.148-1.143-.454 26.934L53.627 80.58 52.7 60.248l-8.665.425 1.83 21.492-18.027 8.396 3.829 8.124 15.436-7.934 22.482 12.807-21.133 12.516 4.242 7.923 16.122-9.03 16.016 9.804.534 16.953-.054 2.816-17.356 10.836-16.828-10.986-6.063 8.216 23.098 13.86-22.186 13.665-18.07-9.365-3.965 7.717 19.527 9.161-1.741 19.809 8.95.747.846-17.336 22.334-13.066.27 24.56 8.984.286.24-18.46 16.966-9.4 5.195 2.786-.071-.003 6.181 3.726.358.235-.013-.027 5.245 3.162.705 20.45-17.927 9.079 4.085 9.361 23.551-13.075.74 26.046-17.146 10.97 4.7 7.29 17.7-12.33 16.284 11.41 5.12-7.377-14.59-9.4-.148-25.873 21.406 12.042 4.74-7.634-15.91-9.462.83-19.827 12.27-6.785-.119-.004 4.408-2.435 18.062 9.613-1.1 20.067 10.147 1.142.454-26.935L218.4 193.38l.927 20.333 8.665-.425-1.83-21.493 18.026-8.395-3.828-8.124zm-45.046-.984a2.727 2.727 0 01-3.747.93l-17.508-10.547-36.84 19.625-.583 22.075a2.731 2.731 0 01-2.728 2.658l-.073-.001a2.73 2.73 0 01-2.657-2.801l.577-21.833-33.078-20.632-18.364 10.365a2.727 2.727 0 01-3.72-1.035 2.73 2.73 0 011.036-3.719l15.772-8.902-.062-.039 1.486-43.493-15.497-9.334a2.731 2.731 0 012.818-4.677l14.297 8.612 37.767-20.12.55-20.814c.04-1.506 1.272-2.722 2.801-2.657a2.73 2.73 0 012.656 2.801l-.535 20.31 36.426 22.723 17.294-9.763a2.73 2.73 0 012.685 4.755l-17.895 10.101-1.403 41.065 17.596 10.6a2.728 2.728 0 01.929 3.747zm-11.41-35.984l-.091.145-.009-.336.1.19z" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 10 KiB

@@ -0,0 +1,145 @@
/*
* Copyright (c) 2010-2025 Contributors to the openHAB project
*
* See the NOTICE file(s) distributed with this work for additional
* information.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0
*
* SPDX-License-Identifier: EPL-2.0
*/
package org.openhab.binding.astro.internal.calc;
import static org.junit.jupiter.api.Assertions.*;
import java.time.Instant;
import java.time.ZonedDateTime;
import java.util.Calendar;
import java.util.GregorianCalendar;
import java.util.Locale;
import java.util.TimeZone;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.openhab.binding.astro.internal.model.Season;
import org.openhab.binding.astro.internal.model.Sun;
import org.openhab.binding.astro.internal.util.DateTimeUtils;
/**
* Unit tests for {@code SeasonCalc}, verifying calculation of seasons for
* different locations and dates. In particular the following cases are
* covered:
*
* season determination for locations in different hemispheres (e.g. Amsterdam vs Sydney)
* distinguishing between meteorological and astronomical seasons
* consistency of calculated season data across representative dates
*
* @author Witold Markowski - Initial contribution
*/
public class SeasonCalcTest {
private static final TimeZone AMSTERDAM_TZ = TimeZone.getTimeZone("Europe/Amsterdam");
private static final TimeZone SYDNEY_TZ = TimeZone.getTimeZone("Australia/Sydney");
private static final Instant MAY_20_2020 = Instant.parse("2020-05-20T01:00:00Z");
private static final Instant JAN_20_2020 = Instant.parse("2020-01-20T01:00:00Z");
private static final Instant SEPT_20_2020 = Instant.parse("2020-09-20T01:00:00Z");
private static final Instant DEC_10_2020 = Instant.parse("2020-12-10T01:00:00Z");
private static final double AMSTERDAM_LATITUDE = 52.367607;
private static final double SYDNEY_LATITUDE = -33.87;
private static final Calendar FEB_27_2019 = SeasonCalcTest.newCalendar(2019, Calendar.FEBRUARY, 27, 1, 0,
AMSTERDAM_TZ);
private static final double AMSTERDAM_LONGITUDE = 4.8978293;
private static final double AMSTERDAM_ALTITUDE = 0.0;
private SunCalc sunCalc;
@BeforeEach
public void init() {
sunCalc = new SunCalc();
}
/***
* Constructs a <code>GregorianCalendar</code> with the given date and time set
* for the provided time zone.
*
* @param year
* the value used to set the <code>YEAR</code> calendar field in the
* calendar.
* @param month
* the value used to set the <code>MONTH</code> calendar field in the
* calendar. Month value is 0-based. e.g., 0 for January.
* @param dayOfMonth
* the value used to set the <code>DAY_OF_MONTH</code> calendar field
* in the calendar.
* @param hourOfDay
* the value used to set the <code>HOUR_OF_DAY</code> calendar field
* in the calendar.
* @param minute
* the value used to set the <code>MINUTE</code> calendar field in
* the calendar.
* @param zone
* the given time zone.
* @return a {@link Calendar} representing the specified date and time in the
* given time zone, truncated to the nearest minute.
*/
private static Calendar newCalendar(int year, int month, int dayOfMonth, int hourOfDay, int minute, TimeZone zone) {
Calendar result = new GregorianCalendar(zone, Locale.ROOT);
result.set(year, month, dayOfMonth, hourOfDay, minute);
return DateTimeUtils.truncateToMinute(result);
}
private static void assertNextSeason(Instant expectedSeason, int expectedYear, Instant date, Season season,
TimeZone tz) {
final Instant nextSeason = season.getNext(date);
assertEquals(expectedSeason, nextSeason, "Should return the expected season name.");
assertNotNull(nextSeason);
int year = nextSeason.atZone(tz.toZoneId()).getYear();
assertEquals(expectedYear, year, "Should return the year matching the next season.");
}
@Test
public void testAstroAndMeteoSeasons() {
Sun meteoSun = sunCalc.getSunInfo(FEB_27_2019, AMSTERDAM_LATITUDE, AMSTERDAM_LONGITUDE, AMSTERDAM_ALTITUDE,
true, AMSTERDAM_TZ, Locale.ROOT);
Sun equiSun = sunCalc.getSunInfo(FEB_27_2019, AMSTERDAM_LATITUDE, AMSTERDAM_LONGITUDE, AMSTERDAM_ALTITUDE,
false, AMSTERDAM_TZ, Locale.ROOT);
var season = meteoSun.getSeason();
assertNotNull(season);
ZonedDateTime cal = season.getSpring().atZone(AMSTERDAM_TZ.toZoneId());
assertNotNull(cal);
var season2 = equiSun.getSeason();
assertNotNull(season2);
ZonedDateTime cal2 = season2.getSpring().atZone(AMSTERDAM_TZ.toZoneId());
assertNotNull(cal2);
assertEquals(cal.getMonth(), cal2.getMonth());
assertEquals(cal.getYear(), cal2.getYear());
assertEquals(1, cal.getDayOfMonth());
assertFalse(cal.getDayOfMonth() == cal2.getDayOfMonth());
}
@Test
public void testGetSeasonAmsterdam() {
final Season season = SeasonCalc.calculate(2020, AMSTERDAM_LATITUDE, true, AMSTERDAM_TZ);
assertNextSeason(season.getSpring(), 2020, JAN_20_2020, season, AMSTERDAM_TZ);
assertNextSeason(season.getSummer(), 2020, MAY_20_2020, season, AMSTERDAM_TZ);
assertNextSeason(season.getWinter(), 2020, SEPT_20_2020, season, AMSTERDAM_TZ);
assertNextSeason(SeasonCalc.calculate(2021, AMSTERDAM_LATITUDE, true, AMSTERDAM_TZ).getSpring(), 2021,
DEC_10_2020, season, AMSTERDAM_TZ);
}
@Test
public void testGetSeasonSydney() {
final Season season = SeasonCalc.calculate(2020, SYDNEY_LATITUDE, true, SYDNEY_TZ);
assertNextSeason(season.getAutumn(), 2020, JAN_20_2020, season, SYDNEY_TZ);
assertNextSeason(season.getWinter(), 2020, MAY_20_2020, season, SYDNEY_TZ);
assertNextSeason(season.getSummer(), 2020, SEPT_20_2020, season, SYDNEY_TZ);
assertNextSeason(SeasonCalc.calculate(2021, SYDNEY_LATITUDE, true, SYDNEY_TZ).getAutumn(), 2021, DEC_10_2020,
season, SYDNEY_TZ);
}
}
@@ -14,7 +14,6 @@ package org.openhab.binding.astro.internal.calc;
import static org.junit.jupiter.api.Assertions.*;
import java.lang.reflect.Method;
import java.util.Calendar;
import java.util.GregorianCalendar;
import java.util.Locale;
@@ -53,14 +52,6 @@ public class SunCalcTest {
private static final double AMSTERDAM_LONGITUDE = 4.8978293;
private static final double AMSTERDAM_ALTITUDE = 0.0;
private static final int ACCURACY_IN_MILLIS = 3 * 60 * 1000;
private static final TimeZone BARROW_TIME_ZONE = TimeZone.getTimeZone("America/Anchorage");
private static final double BARROW_LATITUDE = 71.2906;
private static final double BARROW_LONGITUDE = -156.7886;
private static final double BARROW_ALTITUDE = 0.0;
private static final Calendar SUMMER_SOLSTICE_AMSTERDAM = SunCalcTest.newCalendar(2024, Calendar.JUNE, 21, 12, 0,
AMSTERDAM_TIME_ZONE);
private static final Calendar SUMMER_SOLSTICE_BARROW = SunCalcTest.newCalendar(2024, Calendar.JUNE, 21, 12, 0,
BARROW_TIME_ZONE);
private SunCalc sunCalc;
@@ -458,40 +449,4 @@ public class SunCalcTest {
return DateTimeUtils.truncateToMinute(result);
}
@Test
public void testAstroAndMeteoSeasons() {
Sun meteoSun = sunCalc.getSunInfo(FEB_27_2019, AMSTERDAM_LATITUDE, AMSTERDAM_LONGITUDE, AMSTERDAM_ALTITUDE,
true, AMSTERDAM_TIME_ZONE, Locale.ROOT);
Sun equiSun = sunCalc.getSunInfo(FEB_27_2019, AMSTERDAM_LATITUDE, AMSTERDAM_LONGITUDE, AMSTERDAM_ALTITUDE,
false, AMSTERDAM_TIME_ZONE, Locale.ROOT);
Calendar cal = meteoSun.getSeason().getSpring();
assertNotNull(cal);
Calendar cal2 = equiSun.getSeason().getSpring();
assertNotNull(cal2);
assertEquals(cal.get(Calendar.MONTH), cal2.get(Calendar.MONTH));
assertEquals(cal.get(Calendar.YEAR), cal2.get(Calendar.YEAR));
assertEquals(1, cal.get(Calendar.DAY_OF_MONTH));
assertFalse(cal.get(Calendar.DAY_OF_MONTH) == cal2.get(Calendar.DAY_OF_MONTH));
}
@Test
public void testIsSunUpAllDayForBarrowAlaska() throws Exception {
Method isSunUpAllDay = SunCalc.class.getDeclaredMethod("isSunUpAllDay", Calendar.class, double.class,
double.class, Double.class);
isSunUpAllDay.setAccessible(true);
// At summer solstice in Barrow, Alaska, sun stays up all day
boolean result = (boolean) isSunUpAllDay.invoke(sunCalc, SUMMER_SOLSTICE_BARROW, BARROW_LATITUDE,
BARROW_LONGITUDE, BARROW_ALTITUDE);
assertTrue(result);
// It's not the case in Amsterdam
result = (boolean) isSunUpAllDay.invoke(sunCalc, SUMMER_SOLSTICE_AMSTERDAM, AMSTERDAM_LATITUDE,
AMSTERDAM_LONGITUDE, AMSTERDAM_ALTITUDE);
assertFalse(result);
}
}
@@ -20,11 +20,8 @@ import java.util.GregorianCalendar;
import java.util.Locale;
import java.util.TimeZone;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.openhab.binding.astro.internal.calc.SeasonCalc;
import org.openhab.binding.astro.internal.config.AstroChannelConfig;
import org.openhab.binding.astro.internal.model.Season;
/**
* Test class for {@link DateTimeUtils}.
@@ -36,42 +33,6 @@ public class DateTimeUtilsTest {
private static final TimeZone TIME_ZONE = TimeZone.getTimeZone("Europe/Amsterdam");
private static final Calendar JAN_20_2020 = newCalendar(2020, Calendar.JANUARY, 20, 1, 0, TIME_ZONE);
private static final Calendar MAY_20_2020 = newCalendar(2020, Calendar.MAY, 20, 1, 0, TIME_ZONE);
private static final Calendar SEPT_20_2020 = newCalendar(2020, Calendar.SEPTEMBER, 20, 1, 0, TIME_ZONE);
private static final Calendar DEC_10_2020 = newCalendar(2020, Calendar.DECEMBER, 1, 1, 0, TIME_ZONE);
private static final Calendar DEC_10_2021 = newCalendar(2021, Calendar.DECEMBER, 1, 1, 0, TIME_ZONE);
private static final double AMSTERDAM_LATITUDE = 52.367607;
private static final double SYDNEY_LATITUDE = -33.87;
private SeasonCalc seasonCalc;
@BeforeEach
public void init() {
seasonCalc = new SeasonCalc();
}
@Test
public void testGetSeasonAmsterdam() {
final Season season = seasonCalc.getSeason(DEC_10_2020, AMSTERDAM_LATITUDE, true, TIME_ZONE, Locale.ROOT);
assertNextSeason(season.getSpring(), 2020, JAN_20_2020, season);
assertNextSeason(season.getSummer(), 2020, MAY_20_2020, season);
assertNextSeason(season.getWinter(), 2020, SEPT_20_2020, season);
assertNextSeason(
seasonCalc.getSeason(DEC_10_2021, AMSTERDAM_LATITUDE, true, TIME_ZONE, Locale.ROOT).getSpring(), 2021,
DEC_10_2020, season);
}
@Test
public void testGetSeasonSydney() {
final Season season = seasonCalc.getSeason(DEC_10_2020, SYDNEY_LATITUDE, true, TIME_ZONE, Locale.ROOT);
assertNextSeason(season.getAutumn(), 2020, JAN_20_2020, season);
assertNextSeason(season.getWinter(), 2020, MAY_20_2020, season);
assertNextSeason(season.getSummer(), 2020, SEPT_20_2020, season);
assertNextSeason(seasonCalc.getSeason(DEC_10_2021, SYDNEY_LATITUDE, true, TIME_ZONE, Locale.ROOT).getAutumn(),
2021, DEC_10_2020, season);
}
@Test
void testTruncate() {
@@ -200,14 +161,6 @@ public class DateTimeUtilsTest {
assertEquals(1223, DateTimeUtils.getMinutesFromTime("20:23"));
}
private static void assertNextSeason(Calendar expectedSeason, int expectedYear, Calendar date, Season season) {
final Calendar nextSeason = DateTimeUtils.getNext(date, season.getSpring(), season.getSummer(),
season.getAutumn(), season.getWinter());
assertEquals(expectedSeason, nextSeason, "Should return the expected season name.");
assertNotNull(nextSeason);
assertEquals(expectedYear, nextSeason.get(Calendar.YEAR), "Should return the year matching the next season.");
}
private static Calendar newCalendar(int year, int month, int dayOfMonth, int hourOfDay, int minute, TimeZone zone) {
Calendar result = new GregorianCalendar(zone, Locale.ROOT);
result.set(Calendar.MILLISECOND, 0);
@@ -215,4 +168,30 @@ public class DateTimeUtilsTest {
return result;
}
@Test
public void testJdToInstant() {
// Test with Unix Epoch (1970-01-01T00:00:00Z) corresponding to JD 2440587.5
Instant expectedEpoch = Instant.EPOCH;
Instant actualEpoch = DateTimeUtils.jdToInstant(2440587.5);
assertEquals(expectedEpoch, actualEpoch, "Julian Day 2440587.5 should match Unix Epoch");
// same with J2000.0 (2000-01-01T12:00:00Z) toward JD 2451545.0
Instant expectedJ2000 = Instant.parse("2000-01-01T12:00:00Z");
Instant actualJ2000 = DateTimeUtils.jdToInstant(2451545.0);
assertEquals(expectedJ2000, actualJ2000, "Julian Day 2451545.0 should match J2000.0");
}
@Test
public void testAtMidnightOfFirstMonthDay() {
Instant initialInstant = Instant.parse("2024-05-15T14:30:45.123Z");
// UTC
Instant expectedUtc = Instant.parse("2024-05-01T00:00:00Z");
assertEquals(expectedUtc, DateTimeUtils.atMidnightOfFirstMonthDay(initialInstant, TimeZone.getTimeZone("UTC")));
// Europe/Amsterdam (UTC+2 in May). Local midnight is 22:00 UTC on the previous day.
Instant expectedAmsterdam = Instant.parse("2024-04-30T22:00:00Z");
assertEquals(expectedAmsterdam, DateTimeUtils.atMidnightOfFirstMonthDay(initialInstant, TIME_ZONE));
}
}