@@ -77,4 +77,110 @@ public void testAntiMeridianNoonCalculation() {
7777 (resultCalendar .get (Calendar .MONTH ) + 1 ) + "-" +
7878 resultCalendar .get (Calendar .DAY_OF_MONTH ));
7979 }
80+
81+ /**
82+ * Regression test for eastern anti-meridian noon calculation bug.
83+ *
84+ * This test verifies the opposite case from testAntiMeridianNoonCalculation,
85+ * where the location is on the EASTERN side of the anti-meridian (positive
86+ * longitude near +180°).
87+ *
88+ * The original bug had two parts:
89+ * 1. The condition "localTimeHours + hours > 24" was correct but used -1
90+ * (subtract day) which was wrong
91+ * 2. Only handled one side of anti-meridian, not both
92+ *
93+ * The fix uses: (localTimeHours + hours < 0 || localTimeHours + hours > 24)
94+ * and adds +1 day for BOTH cases.
95+ *
96+ * Test case from random testing that originally failed:
97+ * - Date: 1933-11-21
98+ * - Location: (45.272612853681636, 178.99188812570947), Elevation:
99+ * 77.9172657062239
100+ * - Timezone: Pacific/Auckland (approximately GMT+12)
101+ *
102+ * Before fix: Noon was calculated for 1933-11-22 (wrong day, +1 day error)
103+ * After fix: Noon should be calculated for 1933-11-21 (correct day)
104+ */
105+ @ Test
106+ public void testEasternAntiMeridianNoonCalculation () {
107+ // Create location near eastern anti-meridian
108+ double latitude = 45.272612853681636 ;
109+ double longitude = 178.99188812570947 ;
110+ double elevation = 77.9172657062239 ;
111+ TimeZone timeZone = TimeZone .getTimeZone ("Pacific/Auckland" ); // GMT+12/+13
112+
113+ GeoLocation location = new GeoLocation ("Test Location" , latitude , longitude , elevation , timeZone );
114+ AstronomicalCalendar calendar = new AstronomicalCalendar (location );
115+
116+ // Set the test date: November 21, 1933
117+ calendar .getCalendar ().set (Calendar .YEAR , 1933 );
118+ calendar .getCalendar ().set (Calendar .MONTH , Calendar .NOVEMBER );
119+ calendar .getCalendar ().set (Calendar .DAY_OF_MONTH , 21 );
120+ calendar .getCalendar ().set (Calendar .HOUR_OF_DAY , 11 );
121+ calendar .getCalendar ().set (Calendar .MINUTE , 47 );
122+ calendar .getCalendar ().set (Calendar .SECOND , 40 );
123+
124+ // Get solar noon (sun transit)
125+ Date sunTransit = calendar .getSunTransit ();
126+
127+ Assert .assertNotNull ("Sun transit should not be null" , sunTransit );
128+
129+ // Create a calendar to check the date
130+ Calendar resultCalendar = Calendar .getInstance (timeZone );
131+ resultCalendar .setTime (sunTransit );
132+
133+ // The calculated noon should be on November 21, not November 22
134+ Assert .assertEquals ("Solar noon year should match input year" ,
135+ 1933 , resultCalendar .get (Calendar .YEAR ));
136+ Assert .assertEquals ("Solar noon month should match input month" ,
137+ Calendar .NOVEMBER , resultCalendar .get (Calendar .MONTH ));
138+ Assert .assertEquals ("Solar noon day should match input day (was off by +1 day before fix)" ,
139+ 21 , resultCalendar .get (Calendar .DAY_OF_MONTH ));
140+
141+ System .out .println ("Input date: 1933-11-21" );
142+ System .out .println ("Calculated sun transit: " + sunTransit );
143+ System .out .println ("Transit date components: " +
144+ resultCalendar .get (Calendar .YEAR ) + "-" +
145+ (resultCalendar .get (Calendar .MONTH ) + 1 ) + "-" +
146+ resultCalendar .get (Calendar .DAY_OF_MONTH ));
147+ }
148+
149+ /**
150+ * Additional test for anti-meridian with various longitudes.
151+ * Tests that noon always falls on the correct date regardless of longitude.
152+ */
153+ @ Test
154+ public void testNoonDateConsistency () {
155+ // Test various longitudes near both sides of the anti-meridian
156+ double [] testLongitudes = {
157+ -179.5 , // Just west of anti-meridian
158+ -179.0 ,
159+ 178.0 , // Just east of anti-meridian
160+ 178.5 ,
161+ 179.0 ,
162+ 179.5
163+ };
164+
165+ for (double longitude : testLongitudes ) {
166+ TimeZone tz = TimeZone .getTimeZone ("Etc/GMT+12" );
167+ GeoLocation location = new GeoLocation ("Test" , 0.0 , longitude , 0.0 , tz );
168+ AstronomicalCalendar calendar = new AstronomicalCalendar (location );
169+
170+ // Set a specific date
171+ calendar .getCalendar ().set (2024 , Calendar .JUNE , 15 , 12 , 0 , 0 );
172+ int inputDay = calendar .getCalendar ().get (Calendar .DAY_OF_MONTH );
173+
174+ Date sunTransit = calendar .getSunTransit ();
175+ Assert .assertNotNull ("Sun transit should not be null for longitude " + longitude , sunTransit );
176+
177+ Calendar result = Calendar .getInstance (tz );
178+ result .setTime (sunTransit );
179+ int resultDay = result .get (Calendar .DAY_OF_MONTH );
180+
181+ Assert .assertEquals (
182+ "Solar noon day should match input day for longitude " + longitude ,
183+ inputDay , resultDay );
184+ }
185+ }
80186}
0 commit comments