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