Frank Tang | 3e05d9d | 2021-11-08 14:04:04 -0800 | [diff] [blame] | 1 | // © 2016 and later: Unicode, Inc. and others. |
| 2 | // License & terms of use: http://www.unicode.org/copyright.html |
| 3 | /******************************************************************** |
| 4 | * COPYRIGHT: |
| 5 | * Copyright (c) 1996-2016, International Business Machines Corporation and |
| 6 | * others. All Rights Reserved. |
| 7 | ********************************************************************/ |
| 8 | |
| 9 | /* Test CalendarAstronomer for C++ */ |
| 10 | |
| 11 | #include "unicode/utypes.h" |
| 12 | #include "string.h" |
| 13 | #include "unicode/locid.h" |
| 14 | |
| 15 | #if !UCONFIG_NO_FORMATTING |
| 16 | |
| 17 | #include "astro.h" |
| 18 | #include "astrotst.h" |
| 19 | #include "cmemory.h" |
| 20 | #include "gregoimp.h" // for Math |
| 21 | #include "unicode/simpletz.h" |
| 22 | |
| 23 | |
| 24 | #define CASE(id,test) case id: name = #test; if (exec) { logln(#test "---"); logln((UnicodeString)""); test(); } break |
| 25 | |
| 26 | AstroTest::AstroTest(): astro(NULL), gc(NULL) { |
| 27 | } |
| 28 | |
| 29 | void AstroTest::runIndexedTest( int32_t index, UBool exec, const char* &name, char* /*par*/ ) |
| 30 | { |
| 31 | if (exec) logln("TestSuite AstroTest"); |
| 32 | switch (index) { |
| 33 | // CASE(0,FooTest); |
| 34 | CASE(0,TestSolarLongitude); |
| 35 | CASE(1,TestLunarPosition); |
| 36 | CASE(2,TestCoordinates); |
| 37 | CASE(3,TestCoverage); |
| 38 | CASE(4,TestSunriseTimes); |
| 39 | CASE(5,TestBasics); |
| 40 | CASE(6,TestMoonAge); |
| 41 | default: name = ""; break; |
| 42 | } |
| 43 | } |
| 44 | |
| 45 | #undef CASE |
| 46 | |
| 47 | #define ASSERT_OK(x) UPRV_BLOCK_MACRO_BEGIN { \ |
| 48 | if(U_FAILURE(x)) { \ |
| 49 | dataerrln("%s:%d: %s\n", __FILE__, __LINE__, u_errorName(x)); \ |
| 50 | return; \ |
| 51 | } \ |
| 52 | } UPRV_BLOCK_MACRO_END |
| 53 | |
| 54 | |
| 55 | void AstroTest::initAstro(UErrorCode &status) { |
| 56 | if(U_FAILURE(status)) return; |
| 57 | |
| 58 | if((astro != NULL) || (gc != NULL)) { |
| 59 | dataerrln("Err: initAstro() called twice!"); |
| 60 | closeAstro(status); |
| 61 | if(U_SUCCESS(status)) { |
| 62 | status = U_INTERNAL_PROGRAM_ERROR; |
| 63 | } |
| 64 | } |
| 65 | |
| 66 | if(U_FAILURE(status)) return; |
| 67 | |
| 68 | astro = new CalendarAstronomer(); |
| 69 | gc = Calendar::createInstance(TimeZone::getGMT()->clone(), status); |
| 70 | } |
| 71 | |
| 72 | void AstroTest::closeAstro(UErrorCode &/*status*/) { |
| 73 | if(astro != NULL) { |
| 74 | delete astro; |
| 75 | astro = NULL; |
| 76 | } |
| 77 | if(gc != NULL) { |
| 78 | delete gc; |
| 79 | gc = NULL; |
| 80 | } |
| 81 | } |
| 82 | |
| 83 | void AstroTest::TestSolarLongitude(void) { |
| 84 | UErrorCode status = U_ZERO_ERROR; |
| 85 | initAstro(status); |
| 86 | ASSERT_OK(status); |
| 87 | |
| 88 | struct { |
| 89 | int32_t d[5]; double f ; |
| 90 | } tests[] = { |
| 91 | { { 1980, 7, 27, 0, 00 }, 124.114347 }, |
| 92 | { { 1988, 7, 27, 00, 00 }, 124.187732 } |
| 93 | }; |
| 94 | |
| 95 | logln(""); |
| 96 | for (uint32_t i = 0; i < UPRV_LENGTHOF(tests); i++) { |
| 97 | gc->clear(); |
| 98 | gc->set(tests[i].d[0], tests[i].d[1]-1, tests[i].d[2], tests[i].d[3], tests[i].d[4]); |
| 99 | |
| 100 | astro->setDate(gc->getTime(status)); |
| 101 | |
| 102 | double longitude = astro->getSunLongitude(); |
| 103 | //longitude = 0; |
| 104 | CalendarAstronomer::Equatorial result; |
| 105 | astro->getSunPosition(result); |
| 106 | logln((UnicodeString)"Sun position is " + result.toString() + (UnicodeString)"; " /* + result.toHmsString()*/ + " Sun longitude is " + longitude ); |
| 107 | } |
| 108 | closeAstro(status); |
| 109 | ASSERT_OK(status); |
| 110 | } |
| 111 | |
| 112 | |
| 113 | |
| 114 | void AstroTest::TestLunarPosition(void) { |
| 115 | UErrorCode status = U_ZERO_ERROR; |
| 116 | initAstro(status); |
| 117 | ASSERT_OK(status); |
| 118 | |
| 119 | static const double tests[][7] = { |
| 120 | { 1979, 2, 26, 16, 00, 0, 0 } |
| 121 | }; |
| 122 | logln(""); |
| 123 | |
| 124 | for (int32_t i = 0; i < UPRV_LENGTHOF(tests); i++) { |
| 125 | gc->clear(); |
| 126 | gc->set((int32_t)tests[i][0], (int32_t)tests[i][1]-1, (int32_t)tests[i][2], (int32_t)tests[i][3], (int32_t)tests[i][4]); |
| 127 | astro->setDate(gc->getTime(status)); |
| 128 | |
| 129 | const CalendarAstronomer::Equatorial& result = astro->getMoonPosition(); |
| 130 | logln((UnicodeString)"Moon position is " + result.toString() + (UnicodeString)"; " /* + result->toHmsString()*/); |
| 131 | } |
| 132 | |
| 133 | closeAstro(status); |
| 134 | ASSERT_OK(status); |
| 135 | } |
| 136 | |
| 137 | |
| 138 | |
| 139 | void AstroTest::TestCoordinates(void) { |
| 140 | UErrorCode status = U_ZERO_ERROR; |
| 141 | initAstro(status); |
| 142 | ASSERT_OK(status); |
| 143 | |
| 144 | CalendarAstronomer::Equatorial result; |
| 145 | astro->eclipticToEquatorial(result, 139.686111 * CalendarAstronomer::PI / 180.0, 4.875278* CalendarAstronomer::PI / 180.0); |
| 146 | logln((UnicodeString)"result is " + result.toString() + (UnicodeString)"; " /* + result.toHmsString()*/ ); |
| 147 | closeAstro(status); |
| 148 | ASSERT_OK(status); |
| 149 | } |
| 150 | |
| 151 | |
| 152 | |
| 153 | void AstroTest::TestCoverage(void) { |
| 154 | UErrorCode status = U_ZERO_ERROR; |
| 155 | initAstro(status); |
| 156 | ASSERT_OK(status); |
| 157 | GregorianCalendar *cal = new GregorianCalendar(1958, UCAL_AUGUST, 15,status); |
| 158 | UDate then = cal->getTime(status); |
| 159 | CalendarAstronomer *myastro = new CalendarAstronomer(then); |
| 160 | ASSERT_OK(status); |
| 161 | |
| 162 | //Latitude: 34 degrees 05' North |
| 163 | //Longitude: 118 degrees 22' West |
| 164 | double laLat = 34 + 5./60, laLong = 360 - (118 + 22./60); |
| 165 | CalendarAstronomer *myastro2 = new CalendarAstronomer(laLong, laLat); |
| 166 | |
| 167 | double eclLat = laLat * CalendarAstronomer::PI / 360; |
| 168 | double eclLong = laLong * CalendarAstronomer::PI / 360; |
| 169 | |
| 170 | CalendarAstronomer::Ecliptic ecl(eclLat, eclLong); |
| 171 | CalendarAstronomer::Equatorial eq; |
| 172 | CalendarAstronomer::Horizon hor; |
| 173 | |
| 174 | logln("ecliptic: " + ecl.toString()); |
| 175 | CalendarAstronomer *myastro3 = new CalendarAstronomer(); |
| 176 | myastro3->setJulianDay((4713 + 2000) * 365.25); |
| 177 | |
| 178 | CalendarAstronomer *astronomers[] = { |
| 179 | myastro, myastro2, myastro3, myastro2 // check cache |
| 180 | }; |
| 181 | |
| 182 | for (uint32_t i = 0; i < UPRV_LENGTHOF(astronomers); ++i) { |
| 183 | CalendarAstronomer *anAstro = astronomers[i]; |
| 184 | |
| 185 | //logln("astro: " + astro); |
| 186 | logln((UnicodeString)" date: " + anAstro->getTime()); |
| 187 | logln((UnicodeString)" cent: " + anAstro->getJulianCentury()); |
| 188 | logln((UnicodeString)" gw sidereal: " + anAstro->getGreenwichSidereal()); |
| 189 | logln((UnicodeString)" loc sidereal: " + anAstro->getLocalSidereal()); |
| 190 | logln((UnicodeString)" equ ecl: " + (anAstro->eclipticToEquatorial(eq,ecl)).toString()); |
| 191 | logln((UnicodeString)" equ long: " + (anAstro->eclipticToEquatorial(eq, eclLong)).toString()); |
| 192 | logln((UnicodeString)" horiz: " + (anAstro->eclipticToHorizon(hor, eclLong)).toString()); |
Frank Tang | 1f164ee | 2022-11-08 12:31:27 -0800 | [diff] [blame^] | 193 | logln((UnicodeString)" sunrise: " + (anAstro->getSunRiseSet(true))); |
| 194 | logln((UnicodeString)" sunset: " + (anAstro->getSunRiseSet(false))); |
Frank Tang | 3e05d9d | 2021-11-08 14:04:04 -0800 | [diff] [blame] | 195 | logln((UnicodeString)" moon phase: " + anAstro->getMoonPhase()); |
Frank Tang | 1f164ee | 2022-11-08 12:31:27 -0800 | [diff] [blame^] | 196 | logln((UnicodeString)" moonrise: " + (anAstro->getMoonRiseSet(true))); |
| 197 | logln((UnicodeString)" moonset: " + (anAstro->getMoonRiseSet(false))); |
| 198 | logln((UnicodeString)" prev summer solstice: " + (anAstro->getSunTime(CalendarAstronomer::SUMMER_SOLSTICE(), false))); |
| 199 | logln((UnicodeString)" next summer solstice: " + (anAstro->getSunTime(CalendarAstronomer::SUMMER_SOLSTICE(), true))); |
| 200 | logln((UnicodeString)" prev full moon: " + (anAstro->getMoonTime(CalendarAstronomer::FULL_MOON(), false))); |
| 201 | logln((UnicodeString)" next full moon: " + (anAstro->getMoonTime(CalendarAstronomer::FULL_MOON(), true))); |
Frank Tang | 3e05d9d | 2021-11-08 14:04:04 -0800 | [diff] [blame] | 202 | } |
| 203 | |
| 204 | delete myastro2; |
| 205 | delete myastro3; |
| 206 | delete myastro; |
| 207 | delete cal; |
| 208 | |
| 209 | closeAstro(status); |
| 210 | ASSERT_OK(status); |
| 211 | } |
| 212 | |
| 213 | |
| 214 | |
| 215 | void AstroTest::TestSunriseTimes(void) { |
| 216 | UErrorCode status = U_ZERO_ERROR; |
| 217 | initAstro(status); |
| 218 | ASSERT_OK(status); |
| 219 | |
| 220 | // logln("Sunrise/Sunset times for San Jose, California, USA"); |
| 221 | // CalendarAstronomer *astro2 = new CalendarAstronomer(-121.55, 37.20); |
| 222 | // TimeZone *tz = TimeZone::createTimeZone("America/Los_Angeles"); |
| 223 | |
| 224 | // We'll use a table generated by the UNSO website as our reference |
| 225 | // From: http://aa.usno.navy.mil/ |
| 226 | //-Location: W079 25, N43 40 |
| 227 | //-Rise and Set for the Sun for 2001 |
| 228 | //-Zone: 4h West of Greenwich |
| 229 | int32_t USNO[] = { |
| 230 | 6,59, 19,45, |
| 231 | 6,57, 19,46, |
| 232 | 6,56, 19,47, |
| 233 | 6,54, 19,48, |
| 234 | 6,52, 19,49, |
| 235 | 6,50, 19,51, |
| 236 | 6,48, 19,52, |
| 237 | 6,47, 19,53, |
| 238 | 6,45, 19,54, |
| 239 | 6,43, 19,55, |
| 240 | 6,42, 19,57, |
| 241 | 6,40, 19,58, |
| 242 | 6,38, 19,59, |
| 243 | 6,36, 20, 0, |
| 244 | 6,35, 20, 1, |
| 245 | 6,33, 20, 3, |
| 246 | 6,31, 20, 4, |
| 247 | 6,30, 20, 5, |
| 248 | 6,28, 20, 6, |
| 249 | 6,27, 20, 7, |
| 250 | 6,25, 20, 8, |
| 251 | 6,23, 20,10, |
| 252 | 6,22, 20,11, |
| 253 | 6,20, 20,12, |
| 254 | 6,19, 20,13, |
| 255 | 6,17, 20,14, |
| 256 | 6,16, 20,16, |
| 257 | 6,14, 20,17, |
| 258 | 6,13, 20,18, |
| 259 | 6,11, 20,19, |
| 260 | }; |
| 261 | |
| 262 | logln("Sunrise/Sunset times for Toronto, Canada"); |
| 263 | // long = 79 25", lat = 43 40" |
| 264 | CalendarAstronomer astro3(-(79+25/60), 43+40/60); |
| 265 | |
| 266 | // As of ICU4J 2.8 the ICU4J time zones implement pass-through |
| 267 | // to the underlying JDK. Because of variation in the |
| 268 | // underlying JDKs, we have to use a fixed-offset |
| 269 | // SimpleTimeZone to get consistent behavior between JDKs. |
| 270 | // The offset we want is [-18000000, 3600000] (raw, dst). |
| 271 | // [aliu 10/15/03] |
| 272 | |
| 273 | // TimeZone tz = TimeZone.getTimeZone("America/Montreal"); |
| 274 | SimpleTimeZone tz(-18000000 + 3600000, "Montreal(FIXED)"); |
| 275 | |
| 276 | GregorianCalendar cal(tz.clone(), Locale::getUS(), status); |
| 277 | GregorianCalendar cal2(tz.clone(), Locale::getUS(), status); |
| 278 | cal.clear(); |
| 279 | cal.set(UCAL_YEAR, 2001); |
| 280 | cal.set(UCAL_MONTH, UCAL_APRIL); |
| 281 | cal.set(UCAL_DAY_OF_MONTH, 1); |
| 282 | cal.set(UCAL_HOUR_OF_DAY, 12); // must be near local noon for getSunRiseSet to work |
| 283 | |
| 284 | LocalPointer<DateFormat> df_t(DateFormat::createTimeInstance(DateFormat::MEDIUM,Locale::getUS())); |
| 285 | LocalPointer<DateFormat> df_d(DateFormat::createDateInstance(DateFormat::MEDIUM,Locale::getUS())); |
| 286 | LocalPointer<DateFormat> df_dt(DateFormat::createDateTimeInstance(DateFormat::MEDIUM, DateFormat::MEDIUM, Locale::getUS())); |
| 287 | if(!df_t.isValid() || !df_d.isValid() || !df_dt.isValid()) { |
| 288 | dataerrln("couldn't create dateformats."); |
| 289 | closeAstro(status); |
| 290 | return; |
| 291 | } |
| 292 | df_t->adoptTimeZone(tz.clone()); |
| 293 | df_d->adoptTimeZone(tz.clone()); |
| 294 | df_dt->adoptTimeZone(tz.clone()); |
| 295 | |
| 296 | for (int32_t i=0; i < 30; i++) { |
| 297 | logln("setDate\n"); |
| 298 | astro3.setDate(cal.getTime(status)); |
Frank Tang | 1f164ee | 2022-11-08 12:31:27 -0800 | [diff] [blame^] | 299 | logln("getRiseSet(true)\n"); |
| 300 | UDate sunrise = astro3.getSunRiseSet(true); |
| 301 | logln("getRiseSet(false)\n"); |
| 302 | UDate sunset = astro3.getSunRiseSet(false); |
Frank Tang | 3e05d9d | 2021-11-08 14:04:04 -0800 | [diff] [blame] | 303 | logln("end of getRiseSet\n"); |
| 304 | |
| 305 | cal2.setTime(cal.getTime(status), status); |
| 306 | cal2.set(UCAL_SECOND, 0); |
| 307 | cal2.set(UCAL_MILLISECOND, 0); |
| 308 | |
| 309 | cal2.set(UCAL_HOUR_OF_DAY, USNO[4*i+0]); |
| 310 | cal2.set(UCAL_MINUTE, USNO[4*i+1]); |
| 311 | UDate exprise = cal2.getTime(status); |
| 312 | cal2.set(UCAL_HOUR_OF_DAY, USNO[4*i+2]); |
| 313 | cal2.set(UCAL_MINUTE, USNO[4*i+3]); |
| 314 | UDate expset = cal2.getTime(status); |
| 315 | // Compute delta of what we got to the USNO data, in seconds |
| 316 | int32_t deltarise = (int32_t)uprv_fabs((sunrise - exprise) / 1000); |
| 317 | int32_t deltaset = (int32_t)uprv_fabs((sunset - expset) / 1000); |
| 318 | |
| 319 | // Allow a deviation of 0..MAX_DEV seconds |
| 320 | // It would be nice to get down to 60 seconds, but at this |
| 321 | // point that appears to be impossible without a redo of the |
| 322 | // algorithm using something more advanced than Duffett-Smith. |
| 323 | int32_t MAX_DEV = 180; |
| 324 | UnicodeString s1, s2, s3, s4, s5; |
| 325 | if (deltarise > MAX_DEV || deltaset > MAX_DEV) { |
| 326 | if (deltarise > MAX_DEV) { |
| 327 | errln("FAIL: (rise) " + df_d->format(cal.getTime(status),s1) + |
| 328 | ", Sunrise: " + df_dt->format(sunrise, s2) + |
| 329 | " (USNO " + df_t->format(exprise,s3) + |
| 330 | " d=" + deltarise + "s)"); |
| 331 | } else { |
| 332 | logln(df_d->format(cal.getTime(status),s1) + |
| 333 | ", Sunrise: " + df_dt->format(sunrise,s2) + |
| 334 | " (USNO " + df_t->format(exprise,s3) + ")"); |
| 335 | } |
| 336 | s1.remove(); s2.remove(); s3.remove(); s4.remove(); s5.remove(); |
| 337 | if (deltaset > MAX_DEV) { |
| 338 | errln("FAIL: (set) " + df_d->format(cal.getTime(status),s1) + |
| 339 | ", Sunset: " + df_dt->format(sunset,s2) + |
| 340 | " (USNO " + df_t->format(expset,s3) + |
| 341 | " d=" + deltaset + "s)"); |
| 342 | } else { |
| 343 | logln(df_d->format(cal.getTime(status),s1) + |
| 344 | ", Sunset: " + df_dt->format(sunset,s2) + |
| 345 | " (USNO " + df_t->format(expset,s3) + ")"); |
| 346 | } |
| 347 | } else { |
| 348 | logln(df_d->format(cal.getTime(status),s1) + |
| 349 | ", Sunrise: " + df_dt->format(sunrise,s2) + |
| 350 | " (USNO " + df_t->format(exprise,s3) + ")" + |
| 351 | ", Sunset: " + df_dt->format(sunset,s4) + |
| 352 | " (USNO " + df_t->format(expset,s5) + ")"); |
| 353 | } |
| 354 | cal.add(UCAL_DATE, 1, status); |
| 355 | } |
| 356 | |
| 357 | // CalendarAstronomer a = new CalendarAstronomer(-(71+5/60), 42+37/60); |
| 358 | // cal.clear(); |
| 359 | // cal.set(cal.YEAR, 1986); |
| 360 | // cal.set(cal.MONTH, cal.MARCH); |
| 361 | // cal.set(cal.DATE, 10); |
| 362 | // cal.set(cal.YEAR, 1988); |
| 363 | // cal.set(cal.MONTH, cal.JULY); |
| 364 | // cal.set(cal.DATE, 27); |
| 365 | // a.setDate(cal.getTime()); |
| 366 | // long r = a.getSunRiseSet2(true); |
| 367 | closeAstro(status); |
| 368 | ASSERT_OK(status); |
| 369 | } |
| 370 | |
| 371 | |
| 372 | |
| 373 | void AstroTest::TestBasics(void) { |
| 374 | UErrorCode status = U_ZERO_ERROR; |
| 375 | initAstro(status); |
| 376 | if (U_FAILURE(status)) { |
| 377 | dataerrln("Got error: %s", u_errorName(status)); |
| 378 | return; |
| 379 | } |
| 380 | |
| 381 | // Check that our JD computation is the same as the book's (p. 88) |
| 382 | GregorianCalendar cal3(TimeZone::getGMT()->clone(), Locale::getUS(), status); |
| 383 | LocalPointer<DateFormat> d3(DateFormat::createDateTimeInstance(DateFormat::MEDIUM,DateFormat::MEDIUM,Locale::getUS())); |
| 384 | if (d3.isNull()) { |
| 385 | dataerrln("Got error: %s", u_errorName(status)); |
| 386 | closeAstro(status); |
| 387 | return; |
| 388 | } |
| 389 | d3->setTimeZone(*TimeZone::getGMT()); |
| 390 | cal3.clear(); |
| 391 | cal3.set(UCAL_YEAR, 1980); |
| 392 | cal3.set(UCAL_MONTH, UCAL_JULY); |
| 393 | cal3.set(UCAL_DATE, 2); |
| 394 | logln("cal3[a]=%.1lf, d=%d\n", cal3.getTime(status), cal3.get(UCAL_JULIAN_DAY,status)); |
| 395 | { |
| 396 | UnicodeString s; |
| 397 | logln(UnicodeString("cal3[a] = ") + d3->format(cal3.getTime(status),s)); |
| 398 | } |
| 399 | cal3.clear(); |
| 400 | cal3.set(UCAL_YEAR, 1980); |
| 401 | cal3.set(UCAL_MONTH, UCAL_JULY); |
| 402 | cal3.set(UCAL_DATE, 27); |
| 403 | logln("cal3=%.1lf, d=%d\n", cal3.getTime(status), cal3.get(UCAL_JULIAN_DAY,status)); |
| 404 | |
| 405 | ASSERT_OK(status); |
| 406 | { |
| 407 | UnicodeString s; |
| 408 | logln(UnicodeString("cal3 = ") + d3->format(cal3.getTime(status),s)); |
| 409 | } |
| 410 | astro->setTime(cal3.getTime(status)); |
| 411 | double jd = astro->getJulianDay() - 2447891.5; |
| 412 | double exp = -3444.; |
| 413 | if (jd == exp) { |
| 414 | UnicodeString s; |
| 415 | logln(d3->format(cal3.getTime(status),s) + " => " + jd); |
| 416 | } else { |
| 417 | UnicodeString s; |
| 418 | errln("FAIL: " + d3->format(cal3.getTime(status), s) + " => " + jd + |
| 419 | ", expected " + exp); |
| 420 | } |
| 421 | |
| 422 | // cal3.clear(); |
| 423 | // cal3.set(cal3.YEAR, 1990); |
| 424 | // cal3.set(cal3.MONTH, Calendar.JANUARY); |
| 425 | // cal3.set(cal3.DATE, 1); |
| 426 | // cal3.add(cal3.DATE, -1); |
| 427 | // astro.setDate(cal3.getTime()); |
| 428 | // astro.foo(); |
| 429 | |
| 430 | ASSERT_OK(status); |
| 431 | closeAstro(status); |
| 432 | ASSERT_OK(status); |
| 433 | |
| 434 | } |
| 435 | |
| 436 | void AstroTest::TestMoonAge(void){ |
| 437 | UErrorCode status = U_ZERO_ERROR; |
| 438 | initAstro(status); |
| 439 | ASSERT_OK(status); |
| 440 | |
| 441 | // more testcases are around the date 05/20/2012 |
| 442 | //ticket#3785 UDate ud0 = 1337557623000.0; |
| 443 | static const double testcase[][10] = {{2012, 5, 20 , 16 , 48, 59}, |
| 444 | {2012, 5, 20 , 16 , 47, 34}, |
| 445 | {2012, 5, 21, 00, 00, 00}, |
| 446 | {2012, 5, 20, 14, 55, 59}, |
| 447 | {2012, 5, 21, 7, 40, 40}, |
| 448 | {2023, 9, 25, 10,00, 00}, |
| 449 | {2008, 7, 7, 15, 00, 33}, |
| 450 | {1832, 9, 24, 2, 33, 41 }, |
| 451 | {2016, 1, 31, 23, 59, 59}, |
| 452 | {2099, 5, 20, 14, 55, 59} |
| 453 | }; |
| 454 | // Moon phase angle - Got from http://www.moonsystem.to/checkupe.htm |
| 455 | static const double angle[] = {356.8493418421329, 356.8386760059673, 0.09625415252237701, 355.9986960782416, 3.5714026601303317, 124.26906744384183, 59.80247650195558, |
| 456 | 357.54163205513123, 268.41779281511094, 4.82340276581624}; |
| 457 | static const double precision = CalendarAstronomer::PI/32; |
| 458 | for (int32_t i = 0; i < UPRV_LENGTHOF(testcase); i++) { |
| 459 | gc->clear(); |
| 460 | logln((UnicodeString)"CASE["+i+"]: Year "+(int32_t)testcase[i][0]+" Month "+(int32_t)testcase[i][1]+" Day "+ |
| 461 | (int32_t)testcase[i][2]+" Hour "+(int32_t)testcase[i][3]+" Minutes "+(int32_t)testcase[i][4]+ |
| 462 | " Seconds "+(int32_t)testcase[i][5]); |
| 463 | gc->set((int32_t)testcase[i][0], (int32_t)testcase[i][1]-1, (int32_t)testcase[i][2], (int32_t)testcase[i][3], (int32_t)testcase[i][4], (int32_t)testcase[i][5]); |
| 464 | astro->setDate(gc->getTime(status)); |
| 465 | double expectedAge = (angle[i]*CalendarAstronomer::PI)/180; |
| 466 | double got = astro->getMoonAge(); |
| 467 | //logln(testString); |
| 468 | if(!(got>expectedAge-precision && got<expectedAge+precision)){ |
| 469 | errln((UnicodeString)"FAIL: expected " + expectedAge + |
| 470 | " got " + got); |
| 471 | }else{ |
| 472 | logln((UnicodeString)"PASS: expected " + expectedAge + |
| 473 | " got " + got); |
| 474 | } |
| 475 | } |
| 476 | closeAstro(status); |
| 477 | ASSERT_OK(status); |
| 478 | } |
| 479 | |
| 480 | |
| 481 | // TODO: try finding next new moon after 07/28/1984 16:00 GMT |
| 482 | |
| 483 | |
| 484 | #endif |
| 485 | |
| 486 | |
| 487 | |