2 * Copyright (c) 2010-2023 Contributors to the openHAB project
4 * See the NOTICE file(s) distributed with this work for additional
7 * This program and the accompanying materials are made available under the
8 * terms of the Eclipse Public License 2.0 which is available at
9 * http://www.eclipse.org/legal/epl-2.0
11 * SPDX-License-Identifier: EPL-2.0
13 package org.openhab.binding.astro.internal.calc;
15 import static org.junit.jupiter.api.Assertions.*;
17 import java.util.Calendar;
18 import java.util.GregorianCalendar;
19 import java.util.TimeZone;
21 import org.junit.jupiter.api.BeforeEach;
22 import org.junit.jupiter.api.Test;
23 import org.openhab.binding.astro.internal.model.Moon;
24 import org.openhab.binding.astro.internal.model.ZodiacSign;
27 * Specific unit tests to check if {@link MoonCalc} generates correct data for
28 * Amsterdam city on 27 February 2019. In particular the following cases are
31 * <li>checks if generated data are the same (with some accuracy) as produced by
32 * haevens-above.com</li>
35 * @author Leo Siepel - Initial contribution
36 * @see <a href="https://www.heavens-above.com/Moon.aspx">Heavens Above Moon</a>
38 public class MoonCalcTest {
40 private static final TimeZone TIME_ZONE = TimeZone.getTimeZone("Europe/Amsterdam");
41 private static final Calendar FEB_27_2019 = MoonCalcTest.newCalendar(2019, Calendar.FEBRUARY, 27, 1, 0, TIME_ZONE);
42 private static final double AMSTERDAM_LATITUDE = 52.367607;
43 private static final double AMSTERDAM_LONGITUDE = 4.8978293;
45 private static final int ACCURACY_IN_MILLIS = 5 * 60 * 1000;
46 private static final int ACCURACY_IN_KILOMETRES = 4;
47 private static final double ACCURACY_IN_DEGREE = 0.3;
49 private MoonCalc moonCalc;
53 moonCalc = new MoonCalc();
57 public void testGetMoonInfoForOldDate() {
58 Moon moon = moonCalc.getMoonInfo(FEB_27_2019, AMSTERDAM_LATITUDE, AMSTERDAM_LONGITUDE);
60 assertNotNull(moon.getApogee());
61 assertNotNull(moon.getPerigee());
63 assertNotNull(moon.getDistance());
64 assertNotNull(moon.getEclipse());
66 assertNotNull(moon.getPhase());
67 assertNotNull(moon.getPosition());
68 assertNotNull(moon.getRise());
69 assertNotNull(moon.getSet());
70 assertNotNull(moon.getZodiac());
72 // for an old date the phase should not be calculated
73 assertNull(moon.getPhase().getName());
77 public void testGetMoonInfoForApogeeAccuracy() {
78 Moon moon = moonCalc.getMoonInfo(FEB_27_2019, AMSTERDAM_LATITUDE, AMSTERDAM_LONGITUDE);
80 // expected result from haevens-above.com is 406,391 km @ 04 March 2019 12:27
81 assertEquals(406391, moon.getApogee().getDistance().doubleValue(), ACCURACY_IN_KILOMETRES);
82 assertEquals(MoonCalcTest.newCalendar(2019, Calendar.MARCH, 4, 12, 27, TIME_ZONE).getTimeInMillis(),
83 moon.getApogee().getDate().getTimeInMillis(), ACCURACY_IN_MILLIS);
87 public void testGetMoonInfoForPerigeeAccuracy() {
88 Moon moon = moonCalc.getMoonInfo(FEB_27_2019, AMSTERDAM_LATITUDE, AMSTERDAM_LONGITUDE);
90 // expected result from haevens-above.com is 359,377 km @ 19 February 2019 20:44
91 assertEquals(359377, moon.getPerigee().getDistance().doubleValue(), ACCURACY_IN_KILOMETRES);
93 assertEquals(MoonCalcTest.newCalendar(2019, Calendar.MARCH, 19, 20, 48, TIME_ZONE).getTimeInMillis(),
94 moon.getPerigee().getDate().getTimeInMillis(), ACCURACY_IN_MILLIS);
98 public void testGetMoonInfoForRiseAccuracy() {
99 Moon moon = moonCalc.getMoonInfo(FEB_27_2019, AMSTERDAM_LATITUDE, AMSTERDAM_LONGITUDE);
101 // expected result from haevens-above.com is 03:00
102 assertEquals(MoonCalcTest.newCalendar(2019, Calendar.FEBRUARY, 27, 3, 0, TIME_ZONE).getTimeInMillis(),
103 moon.getRise().getStart().getTimeInMillis(), ACCURACY_IN_MILLIS);
107 public void testGetMoonInfoForSetAccuracy() {
108 Moon moon = moonCalc.getMoonInfo(FEB_27_2019, AMSTERDAM_LATITUDE, AMSTERDAM_LONGITUDE);
110 // expected result from haevens-above.com is 11:35
111 assertEquals(MoonCalcTest.newCalendar(2019, Calendar.FEBRUARY, 27, 11, 35, TIME_ZONE).getTimeInMillis(),
112 moon.getSet().getStart().getTimeInMillis(), ACCURACY_IN_MILLIS);
116 public void testGetMoonInfoForZodiac() {
117 Moon moon = moonCalc.getMoonInfo(FEB_27_2019, AMSTERDAM_LATITUDE, AMSTERDAM_LONGITUDE);
118 moonCalc.setPositionalInfo(FEB_27_2019, AMSTERDAM_LATITUDE, AMSTERDAM_LONGITUDE, moon);
120 assertEquals(ZodiacSign.SAGITTARIUS, moon.getZodiac().getSign());
124 public void testGetMoonInfoForMoonPositionAccuracy() {
125 Moon moon = moonCalc.getMoonInfo(FEB_27_2019, AMSTERDAM_LATITUDE, AMSTERDAM_LONGITUDE);
126 moonCalc.setPositionalInfo(FEB_27_2019, AMSTERDAM_LATITUDE, AMSTERDAM_LONGITUDE, moon);
128 // expected result from haevens-above.com is Azimuth: 100.5, altitude -17
129 assertEquals(100.5, moon.getPosition().getAzimuth().doubleValue(), ACCURACY_IN_DEGREE);
130 assertEquals(-17, moon.getPosition().getElevation().doubleValue(), ACCURACY_IN_DEGREE);
134 public void testGetMoonInfoForMoonDistanceAccuracy() {
135 Moon moon = moonCalc.getMoonInfo(FEB_27_2019, AMSTERDAM_LATITUDE, AMSTERDAM_LONGITUDE);
136 moonCalc.setPositionalInfo(FEB_27_2019, AMSTERDAM_LATITUDE, AMSTERDAM_LONGITUDE, moon);
138 // expected result from haevens-above.com is 392612 km
139 assertEquals(392612, moon.getDistance().getDistance().doubleValue(), ACCURACY_IN_KILOMETRES);
143 public void testGetMoonInfoForMoonPhaseAccuracy() {
144 Moon moon = moonCalc.getMoonInfo(FEB_27_2019, AMSTERDAM_LATITUDE, AMSTERDAM_LONGITUDE);
145 moonCalc.setPositionalInfo(FEB_27_2019, AMSTERDAM_LATITUDE, AMSTERDAM_LONGITUDE, moon);
147 // New moon 06 March 2019 17:04
148 // First quarter 14 March 2019 11:27
149 // Full moon 21 March 2019 02:43
150 // Last quarter 28 March 2019 05:10
151 assertEquals(MoonCalcTest.newCalendar(2019, Calendar.MARCH, 06, 17, 04, TIME_ZONE).getTimeInMillis(),
152 moon.getPhase().getNew().getTimeInMillis(), ACCURACY_IN_MILLIS);
153 assertEquals(MoonCalcTest.newCalendar(2019, Calendar.MARCH, 14, 11, 27, TIME_ZONE).getTimeInMillis(),
154 moon.getPhase().getFirstQuarter().getTimeInMillis(), ACCURACY_IN_MILLIS);
155 assertEquals(MoonCalcTest.newCalendar(2019, Calendar.MARCH, 21, 02, 43, TIME_ZONE).getTimeInMillis(),
156 moon.getPhase().getFull().getTimeInMillis(), ACCURACY_IN_MILLIS);
157 assertEquals(MoonCalcTest.newCalendar(2019, Calendar.MARCH, 28, 05, 10, TIME_ZONE).getTimeInMillis(),
158 moon.getPhase().getThirdQuarter().getTimeInMillis(), ACCURACY_IN_MILLIS);
162 * Constructs a <code>GregorianCalendar</code> with the given date and time set
163 * for the provided time zone.
166 * the value used to set the <code>YEAR</code> calendar field in the
169 * the value used to set the <code>MONTH</code> calendar field in the
170 * calendar. Month value is 0-based. e.g., 0 for January.
172 * the value used to set the <code>DAY_OF_MONTH</code> calendar field
175 * the value used to set the <code>HOUR_OF_DAY</code> calendar field
178 * the value used to set the <code>MINUTE</code> calendar field in
181 * the given time zone.
184 private static Calendar newCalendar(int year, int month, int dayOfMonth, int hourOfDay, int minute, TimeZone zone) {
185 Calendar result = new GregorianCalendar(year, month, dayOfMonth, hourOfDay, minute);
186 result.setTimeZone(zone);