1/* GENERATED SOURCE. DO NOT MODIFY. */
2// © 2016 and later: Unicode, Inc. and others.
3// License & terms of use: http://www.unicode.org/copyright.html#License
4/*
5 *******************************************************************************
6 * Copyright (C) 1996-2010, International Business Machines Corporation and    *
7 * others. All Rights Reserved.                                                *
8 *******************************************************************************
9 */
10package android.icu.dev.test.calendar;
11
12// AstroTest
13
14import java.util.Date;
15import java.util.Locale;
16
17import org.junit.Test;
18import org.junit.runner.RunWith;
19import org.junit.runners.JUnit4;
20
21import android.icu.dev.test.TestFmwk;
22import android.icu.impl.CalendarAstronomer;
23import android.icu.impl.CalendarAstronomer.Ecliptic;
24import android.icu.impl.CalendarAstronomer.Equatorial;
25import android.icu.text.DateFormat;
26import android.icu.util.Calendar;
27import android.icu.util.GregorianCalendar;
28import android.icu.util.SimpleTimeZone;
29import android.icu.util.TimeZone;
30import android.icu.testsharding.MainTestShard;
31
32// TODO: try finding next new moon after  07/28/1984 16:00 GMT
33
34@MainTestShard
35@RunWith(JUnit4.class)
36public class AstroTest extends TestFmwk {
37    static final double PI = Math.PI;
38
39    @Test
40    public void TestSolarLongitude() {
41        GregorianCalendar gc = new GregorianCalendar(new SimpleTimeZone(0, "UTC"));
42        CalendarAstronomer astro = new CalendarAstronomer();
43        // year, month, day, hour, minute, longitude (radians), ascension(radians), declination(radians)
44        final double tests[][] = {
45            { 1980, 7, 27, 00, 00, 2.166442986535465, 2.2070499713207730, 0.3355704075759270 },
46            { 1988, 7, 27, 00, 00, 2.167484927693959, 2.2081183335606176, 0.3353093444275315 },
47        };
48        logln("");
49        for (int i = 0; i < tests.length; i++) {
50            gc.clear();
51            gc.set((int)tests[i][0], (int)tests[i][1]-1, (int)tests[i][2], (int)tests[i][3], (int) tests[i][4]);
52
53            astro.setDate(gc.getTime());
54
55            double longitude = astro.getSunLongitude();
56            if (longitude != tests[i][5]) {
57                if ((float)longitude == (float)tests[i][5]) {
58                    logln("longitude(" + longitude +
59                            ") !=  tests[i][5](" + tests[i][5] +
60                            ") in double for test " + i);
61                } else {
62                    errln("FAIL: longitude(" + longitude +
63                            ") !=  tests[i][5](" + tests[i][5] +
64                            ") for test " + i);
65                }
66            }
67            Equatorial result = astro.getSunPosition();
68            if (result.ascension != tests[i][6]) {
69                if ((float)result.ascension == (float)tests[i][6]) {
70                    logln("result.ascension(" + result.ascension +
71                            ") !=  tests[i][6](" + tests[i][6] +
72                            ") in double for test " + i);
73                } else {
74                    errln("FAIL: result.ascension(" + result.ascension +
75                            ") !=  tests[i][6](" + tests[i][6] +
76                            ") for test " + i);
77                }
78            }
79            if (result.declination != tests[i][7]) {
80                if ((float)result.declination == (float)tests[i][7]) {
81                    logln("result.declination(" + result.declination +
82                            ") !=  tests[i][7](" + tests[i][7] +
83                            ") in double for test " + i);
84                } else {
85                    errln("FAIL: result.declination(" + result.declination +
86                            ") !=  tests[i][7](" + tests[i][7] +
87                            ") for test " + i);
88                }
89            }
90        }
91    }
92
93    @Test
94    public void TestLunarPosition() {
95        GregorianCalendar gc = new GregorianCalendar(new SimpleTimeZone(0, "UTC"));
96        CalendarAstronomer astro = new CalendarAstronomer();
97        // year, month, day, hour, minute, ascension(radians), declination(radians)
98        final double tests[][] = {
99            { 1979, 2, 26, 16, 00, -0.3778379118188744, -0.1399698825594198 },
100        };
101        logln("");
102
103        for (int i = 0; i < tests.length; i++) {
104            gc.clear();
105            gc.set((int)tests[i][0], (int)tests[i][1]-1, (int)tests[i][2], (int)tests[i][3], (int) tests[i][4]);
106            astro.setDate(gc.getTime());
107
108            Equatorial result = astro.getMoonPosition();
109            if (result.ascension != tests[i][5]) {
110                if ((float)result.ascension == (float)tests[i][5]) {
111                    logln("result.ascension(" + result.ascension +
112                            ") !=  tests[i][5](" + tests[i][5] +
113                            ") in double for test " + i);
114                } else {
115                    errln("FAIL: result.ascension(" + result.ascension +
116                            ") !=  tests[i][5](" + tests[i][5] +
117                            ") for test " + i);
118                }
119            }
120            if (result.declination != tests[i][6]) {
121                if ((float)result.declination == (float)tests[i][6]) {
122                    logln("result.declination(" + result.declination +
123                            ") !=  tests[i][6](" + tests[i][6] +
124                            ") in double for test " + i);
125                } else {
126                    errln("FAIL: result.declination(" + result.declination +
127                            ") !=  tests[i][6](" + tests[i][6] +
128                            ") for test " + i);
129                }
130            }
131        }
132    }
133
134    @Test
135    public void TestCoordinates() {
136        CalendarAstronomer astro = new CalendarAstronomer();
137        Equatorial result = astro.eclipticToEquatorial(139.686111 * PI/ 180.0, 4.875278* PI / 180.0);
138        logln("result is " + result + ";  " + result.toHmsString());
139    }
140
141    @Test
142    public void TestCoverage() {
143        GregorianCalendar cal = new GregorianCalendar(1958, Calendar.AUGUST, 15);
144        Date then = cal.getTime();
145        CalendarAstronomer myastro = new CalendarAstronomer(then);
146
147        //Latitude:  34 degrees 05' North
148        //Longitude:  118 degrees 22' West
149        double laLat = 34 + 5d/60, laLong = 360 - (118 + 22d/60);
150        CalendarAstronomer myastro2 = new CalendarAstronomer(laLong, laLat);
151
152        double eclLat = laLat * Math.PI / 360;
153        double eclLong = laLong * Math.PI / 360;
154        Ecliptic ecl = new Ecliptic(eclLat, eclLong);
155        logln("ecliptic: " + ecl);
156
157        CalendarAstronomer myastro3 = new CalendarAstronomer();
158        myastro3.setJulianDay((4713 + 2000) * 365.25);
159
160        CalendarAstronomer[] astronomers = {
161            myastro, myastro2, myastro3, myastro2 // check cache
162
163        };
164
165        for (int i = 0; i < astronomers.length; ++i) {
166            CalendarAstronomer astro = astronomers[i];
167
168            logln("astro: " + astro);
169            logln("   time: " + astro.getTime());
170            logln("   date: " + astro.getDate());
171            logln("   cent: " + astro.getJulianCentury());
172            logln("   gw sidereal: " + astro.getGreenwichSidereal());
173            logln("   loc sidereal: " + astro.getLocalSidereal());
174            logln("   equ ecl: " + astro.eclipticToEquatorial(ecl));
175            logln("   equ long: " + astro.eclipticToEquatorial(eclLong));
176            logln("   horiz: " + astro.eclipticToHorizon(eclLong));
177            logln("   sunrise: " + new Date(astro.getSunRiseSet(true)));
178            logln("   sunset: " + new Date(astro.getSunRiseSet(false)));
179            logln("   moon phase: " + astro.getMoonPhase());
180            logln("   moonrise: " + new Date(astro.getMoonRiseSet(true)));
181            logln("   moonset: " + new Date(astro.getMoonRiseSet(false)));
182            logln("   prev summer solstice: " + new Date(astro.getSunTime(CalendarAstronomer.SUMMER_SOLSTICE, false)));
183            logln("   next summer solstice: " + new Date(astro.getSunTime(CalendarAstronomer.SUMMER_SOLSTICE, true)));
184            logln("   prev full moon: " + new Date(astro.getMoonTime(CalendarAstronomer.FULL_MOON, false)));
185            logln("   next full moon: " + new Date(astro.getMoonTime(CalendarAstronomer.FULL_MOON, true)));
186        }
187
188    }
189
190    static final long DAY_MS = 24*60*60*1000L;
191
192    @Test
193    public void TestSunriseTimes() {
194
195        //        logln("Sunrise/Sunset times for San Jose, California, USA");
196        //        CalendarAstronomer astro = new CalendarAstronomer(-121.55, 37.20);
197        //        TimeZone tz = TimeZone.getTimeZone("America/Los_Angeles");
198
199        // We'll use a table generated by the UNSO website as our reference
200        // From: http://aa.usno.navy.mil/
201        //-Location: W079 25, N43 40
202        //-Rise and Set for the Sun for 2001
203        //-Zone:  4h West of Greenwich
204        int[] USNO = {
205             6,59, 19,45,
206             6,57, 19,46,
207             6,56, 19,47,
208             6,54, 19,48,
209             6,52, 19,49,
210             6,50, 19,51,
211             6,48, 19,52,
212             6,47, 19,53,
213             6,45, 19,54,
214             6,43, 19,55,
215             6,42, 19,57,
216             6,40, 19,58,
217             6,38, 19,59,
218             6,36, 20, 0,
219             6,35, 20, 1,
220             6,33, 20, 3,
221             6,31, 20, 4,
222             6,30, 20, 5,
223             6,28, 20, 6,
224             6,27, 20, 7,
225             6,25, 20, 8,
226             6,23, 20,10,
227             6,22, 20,11,
228             6,20, 20,12,
229             6,19, 20,13,
230             6,17, 20,14,
231             6,16, 20,16,
232             6,14, 20,17,
233             6,13, 20,18,
234             6,11, 20,19,
235        };
236
237        logln("Sunrise/Sunset times for Toronto, Canada");
238        CalendarAstronomer astro = new CalendarAstronomer(-(79+25/60), 43+40/60);
239
240        // As of ICU4J 2.8 the ICU4J time zones implement pass-through
241        // to the underlying JDK.  Because of variation in the
242        // underlying JDKs, we have to use a fixed-offset
243        // SimpleTimeZone to get consistent behavior between JDKs.
244        // The offset we want is [-18000000, 3600000] (raw, dst).
245        // [aliu 10/15/03]
246
247        // TimeZone tz = TimeZone.getTimeZone("America/Montreal");
248        TimeZone tz = new SimpleTimeZone(-18000000 + 3600000, "Montreal(FIXED)");
249
250        GregorianCalendar cal = new GregorianCalendar(tz, Locale.US);
251        GregorianCalendar cal2 = new GregorianCalendar(tz, Locale.US);
252        cal.clear();
253        cal.set(Calendar.YEAR, 2001);
254        cal.set(Calendar.MONTH, Calendar.APRIL);
255        cal.set(Calendar.DAY_OF_MONTH, 1);
256        cal.set(Calendar.HOUR_OF_DAY, 12); // must be near local noon for getSunRiseSet to work
257
258        DateFormat df = DateFormat.getTimeInstance(cal, DateFormat.MEDIUM, Locale.US);
259        DateFormat df2 = DateFormat.getDateTimeInstance(cal, DateFormat.MEDIUM, DateFormat.MEDIUM, Locale.US);
260        DateFormat day = DateFormat.getDateInstance(cal, DateFormat.MEDIUM, Locale.US);
261
262        for (int i=0; i < 30; i++) {
263            astro.setDate(cal.getTime());
264
265            Date sunrise = new Date(astro.getSunRiseSet(true));
266            Date sunset = new Date(astro.getSunRiseSet(false));
267
268            cal2.setTime(cal.getTime());
269            cal2.set(Calendar.SECOND,      0);
270            cal2.set(Calendar.MILLISECOND, 0);
271
272            cal2.set(Calendar.HOUR_OF_DAY, USNO[4*i+0]);
273            cal2.set(Calendar.MINUTE,      USNO[4*i+1]);
274            Date exprise = cal2.getTime();
275            cal2.set(Calendar.HOUR_OF_DAY, USNO[4*i+2]);
276            cal2.set(Calendar.MINUTE,      USNO[4*i+3]);
277            Date expset = cal2.getTime();
278            // Compute delta of what we got to the USNO data, in seconds
279            int deltarise = Math.abs((int)(sunrise.getTime() - exprise.getTime()) / 1000);
280            int deltaset = Math.abs((int)(sunset.getTime() - expset.getTime()) / 1000);
281
282            // Allow a deviation of 0..MAX_DEV seconds
283            // It would be nice to get down to 60 seconds, but at this
284            // point that appears to be impossible without a redo of the
285            // algorithm using something more advanced than Duffett-Smith.
286            final int MAX_DEV = 180;
287            if (deltarise > MAX_DEV || deltaset > MAX_DEV) {
288                if (deltarise > MAX_DEV) {
289                    errln("FAIL: " + day.format(cal.getTime()) +
290                          ", Sunrise: " + df2.format(sunrise) +
291                          " (USNO " + df.format(exprise) +
292                          " d=" + deltarise + "s)");
293                } else {
294                    logln(day.format(cal.getTime()) +
295                          ", Sunrise: " + df.format(sunrise) +
296                          " (USNO " + df.format(exprise) + ")");
297                }
298                if (deltaset > MAX_DEV) {
299                    errln("FAIL: " + day.format(cal.getTime()) +
300                          ", Sunset: " + df2.format(sunset) +
301                          " (USNO " + df.format(expset) +
302                          " d=" + deltaset + "s)");
303                } else {
304                    logln(day.format(cal.getTime()) +
305                          ", Sunset: " + df.format(sunset) +
306                          " (USNO " + df.format(expset) + ")");
307                }
308            } else {
309                logln(day.format(cal.getTime()) +
310                      ", Sunrise: " + df.format(sunrise) +
311                      " (USNO " + df.format(exprise) + ")" +
312                      ", Sunset: " + df.format(sunset) +
313                      " (USNO " + df.format(expset) + ")");
314            }
315            cal.add(Calendar.DATE, 1);
316        }
317
318//        CalendarAstronomer a = new CalendarAstronomer(-(71+5/60), 42+37/60);
319//        cal.clear();
320//        cal.set(cal.YEAR, 1986);
321//        cal.set(cal.MONTH, cal.MARCH);
322//        cal.set(cal.DATE, 10);
323//        cal.set(cal.YEAR, 1988);
324//        cal.set(cal.MONTH, cal.JULY);
325//        cal.set(cal.DATE, 27);
326//        a.setDate(cal.getTime());
327//        long r = a.getSunRiseSet2(true);
328    }
329
330    @Test
331    public void TestBasics() {
332        // Check that our JD computation is the same as the book's (p. 88)
333        CalendarAstronomer astro = new CalendarAstronomer();
334        GregorianCalendar cal3 = new GregorianCalendar(TimeZone.getTimeZone("GMT"), Locale.US);
335        DateFormat d3 = DateFormat.getDateTimeInstance(cal3, DateFormat.MEDIUM,DateFormat.MEDIUM,Locale.US);
336        cal3.clear();
337        cal3.set(Calendar.YEAR, 1980);
338        cal3.set(Calendar.MONTH, Calendar.JULY);
339        cal3.set(Calendar.DATE, 27);
340        astro.setDate(cal3.getTime());
341        double jd = astro.getJulianDay() - 2447891.5;
342        double exp = -3444;
343        if (jd == exp) {
344            logln(d3.format(cal3.getTime()) + " => " + jd);
345        } else {
346            errln("FAIL: " + d3.format(cal3.getTime()) + " => " + jd +
347                  ", expected " + exp);
348        }
349
350
351//        cal3.clear();
352//        cal3.set(cal3.YEAR, 1990);
353//        cal3.set(cal3.MONTH, Calendar.JANUARY);
354//        cal3.set(cal3.DATE, 1);
355//        cal3.add(cal3.DATE, -1);
356//        astro.setDate(cal3.getTime());
357//        astro.foo();
358    }
359
360    @Test
361    public void TestMoonAge(){
362        GregorianCalendar gc = new GregorianCalendar(new SimpleTimeZone(0,"GMT"));
363        CalendarAstronomer calastro = new CalendarAstronomer();
364        // more testcases are around the date 05/20/2012
365        //ticket#3785  UDate ud0 = 1337557623000.0;
366        double testcase[][] = {{2012, 5, 20 , 16 , 48, 59},
367                {2012, 5, 20 , 16 , 47, 34},
368                {2012, 5, 21, 00, 00, 00},
369                {2012, 5, 20, 14, 55, 59},
370                {2012, 5, 21, 7, 40, 40},
371                {2023, 9, 25, 10,00, 00},
372                {2008, 7, 7, 15, 00, 33},
373                {1832, 9, 24, 2, 33, 41 },
374                {2016, 1, 31, 23, 59, 59},
375                {2099, 5, 20, 14, 55, 59}
376        };
377        // Moon phase angle - Got from http://www.moonsystem.to/checkupe.htm
378        double angle[] = {356.8493418421329, 356.8386760059673, 0.09625415252237701, 355.9986960782416, 3.5714026601303317, 124.26906744384183, 59.80247650195558, 357.54163205513123, 268.41779281511094, 4.82340276581624};
379        double precision = PI/32;
380        for(int i=0; i<testcase.length; i++){
381            gc.clear();
382            String testString = "CASE["+i+"]: Year "+(int)testcase[i][0]+" Month "+(int)testcase[i][1]+" Day "+
383                                    (int)testcase[i][2]+" Hour "+(int)testcase[i][3]+" Minutes "+(int)testcase[i][4]+
384                                    " Seconds "+(int)testcase[i][5];
385            gc.set((int)testcase[i][0],(int)testcase[i][1]-1,(int)testcase[i][2],(int)testcase[i][3],(int)testcase[i][4], (int)testcase[i][5]);
386            calastro.setDate(gc.getTime());
387            double expectedAge = (angle[i]*PI)/180;
388            double got = calastro.getMoonAge();
389            logln(testString);
390            if(!(got>expectedAge-precision && got<expectedAge+precision)){
391                errln("FAIL: expected " + expectedAge +
392                        " got " + got);
393            }else{
394                logln("PASS: expected " + expectedAge +
395                        " got " + got);
396            }
397        }
398    }
399}
400