1ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/************************************************************************ 285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho * Copyright (C) 1996-2008, International Business Machines Corporation * 3ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * and others. All Rights Reserved. * 4ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru ************************************************************************ 5ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * 2003-nov-07 srl Port from Java 6ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru */ 7ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 8ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#include "astro.h" 9ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 10ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#if !UCONFIG_NO_FORMATTING 11ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 12ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#include "unicode/calendar.h" 13ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#include <math.h> 14ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#include <float.h> 15ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#include "unicode/putil.h" 16ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#include "uhash.h" 17ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#include "umutex.h" 18ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#include "ucln_in.h" 19ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#include "putilimp.h" 20ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#include <stdio.h> // for toString() 21ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 2285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho#if defined (PI) 2385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho#undef PI 2485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho#endif 2585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho 26ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#ifdef U_DEBUG_ASTRO 27ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru# include "uresimp.h" // for debugging 28ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 29ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querustatic void debug_astro_loc(const char *f, int32_t l) 30ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{ 31ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru fprintf(stderr, "%s:%d: ", f, l); 32ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru} 33ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 34ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querustatic void debug_astro_msg(const char *pat, ...) 35ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{ 36ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru va_list ap; 37ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru va_start(ap, pat); 38ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru vfprintf(stderr, pat, ap); 39ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru fflush(stderr); 40ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru} 41ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#include "unicode/datefmt.h" 42ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#include "unicode/ustring.h" 43ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querustatic const char * debug_astro_date(UDate d) { 44ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru static char gStrBuf[1024]; 45ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru static DateFormat *df = NULL; 46ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if(df == NULL) { 47ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru df = DateFormat::createDateTimeInstance(DateFormat::MEDIUM, DateFormat::MEDIUM, Locale::getUS()); 48ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru df->adoptTimeZone(TimeZone::getGMT()->clone()); 49ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 50ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru UnicodeString str; 51ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru df->format(d,str); 52ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru u_austrncpy(gStrBuf,str.getTerminatedBuffer(),sizeof(gStrBuf)-1); 53ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru return gStrBuf; 54ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru} 55ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 56ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// must use double parens, i.e.: U_DEBUG_ASTRO_MSG(("four is: %d",4)); 57ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#define U_DEBUG_ASTRO_MSG(x) {debug_astro_loc(__FILE__,__LINE__);debug_astro_msg x;} 58ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#else 59ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#define U_DEBUG_ASTRO_MSG(x) 60ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#endif 61ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 62ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querustatic inline UBool isINVALID(double d) { 63ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru return(uprv_isNaN(d)); 64ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru} 65ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 66ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querustatic UMTX ccLock = NULL; 67ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 68ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruU_CDECL_BEGIN 69ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querustatic UBool calendar_astro_cleanup(void) { 70ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru umtx_destroy(&ccLock); 71ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru return TRUE; 72ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru} 73ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruU_CDECL_END 74ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 75ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruU_NAMESPACE_BEGIN 76ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 77ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/** 78ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * The number of standard hours in one sidereal day. 79ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * Approximately 24.93. 80ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * @internal 81ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * @deprecated ICU 2.4. This class may be removed or modified. 82ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru */ 83ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#define SIDEREAL_DAY (23.93446960027) 84ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 85ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/** 86ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * The number of sidereal hours in one mean solar day. 87ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * Approximately 24.07. 88ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * @internal 89ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * @deprecated ICU 2.4. This class may be removed or modified. 90ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru */ 91ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#define SOLAR_DAY (24.065709816) 92ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 93ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/** 94ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * The average number of solar days from one new moon to the next. This is the time 95ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * it takes for the moon to return the same ecliptic longitude as the sun. 96ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * It is longer than the sidereal month because the sun's longitude increases 97ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * during the year due to the revolution of the earth around the sun. 98ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * Approximately 29.53. 99ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * 100ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * @see #SIDEREAL_MONTH 101ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * @internal 102ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * @deprecated ICU 2.4. This class may be removed or modified. 103ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru */ 104ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruconst double CalendarAstronomer::SYNODIC_MONTH = 29.530588853; 105ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 106ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/** 107ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * The average number of days it takes 108ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * for the moon to return to the same ecliptic longitude relative to the 109ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * stellar background. This is referred to as the sidereal month. 110ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * It is shorter than the synodic month due to 111ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * the revolution of the earth around the sun. 112ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * Approximately 27.32. 113ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * 114ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * @see #SYNODIC_MONTH 115ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * @internal 116ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * @deprecated ICU 2.4. This class may be removed or modified. 117ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru */ 118ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#define SIDEREAL_MONTH 27.32166 119ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 120ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/** 121ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * The average number number of days between successive vernal equinoxes. 122ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * Due to the precession of the earth's 123ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * axis, this is not precisely the same as the sidereal year. 124ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * Approximately 365.24 125ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * 126ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * @see #SIDEREAL_YEAR 127ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * @internal 128ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * @deprecated ICU 2.4. This class may be removed or modified. 129ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru */ 130ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#define TROPICAL_YEAR 365.242191 131ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 132ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/** 133ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * The average number of days it takes 134ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * for the sun to return to the same position against the fixed stellar 135ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * background. This is the duration of one orbit of the earth about the sun 136ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * as it would appear to an outside observer. 137ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * Due to the precession of the earth's 138ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * axis, this is not precisely the same as the tropical year. 139ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * Approximately 365.25. 140ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * 141ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * @see #TROPICAL_YEAR 142ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * @internal 143ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * @deprecated ICU 2.4. This class may be removed or modified. 144ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru */ 145ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#define SIDEREAL_YEAR 365.25636 146ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 147ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru//------------------------------------------------------------------------- 148ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// Time-related constants 149ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru//------------------------------------------------------------------------- 150ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 151ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/** 152ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * The number of milliseconds in one second. 153ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * @internal 154ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * @deprecated ICU 2.4. This class may be removed or modified. 155ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru */ 156ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#define SECOND_MS U_MILLIS_PER_SECOND 157ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 158ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/** 159ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * The number of milliseconds in one minute. 160ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * @internal 161ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * @deprecated ICU 2.4. This class may be removed or modified. 162ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru */ 163ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#define MINUTE_MS U_MILLIS_PER_MINUTE 164ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 165ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/** 166ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * The number of milliseconds in one hour. 167ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * @internal 168ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * @deprecated ICU 2.4. This class may be removed or modified. 169ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru */ 170ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#define HOUR_MS U_MILLIS_PER_HOUR 171ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 172ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/** 173ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * The number of milliseconds in one day. 174ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * @internal 175ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * @deprecated ICU 2.4. This class may be removed or modified. 176ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru */ 177ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#define DAY_MS U_MILLIS_PER_DAY 178ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 179ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/** 180ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * The start of the julian day numbering scheme used by astronomers, which 181ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * is 1/1/4713 BC (Julian), 12:00 GMT. This is given as the number of milliseconds 182ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * since 1/1/1970 AD (Gregorian), a negative number. 183ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * Note that julian day numbers and 184ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * the Julian calendar are <em>not</em> the same thing. Also note that 185ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * julian days start at <em>noon</em>, not midnight. 186ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * @internal 187ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * @deprecated ICU 2.4. This class may be removed or modified. 188ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru */ 189ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#define JULIAN_EPOCH_MS -210866760000000.0 190ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 191ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 192ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/** 193ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * Milliseconds value for 0.0 January 2000 AD. 194ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru */ 195ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#define EPOCH_2000_MS 946598400000.0 196ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 197ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru//------------------------------------------------------------------------- 198ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// Assorted private data used for conversions 199ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru//------------------------------------------------------------------------- 200ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 201ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// My own copies of these so compilers are more likely to optimize them away 202ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruconst double CalendarAstronomer::PI = 3.14159265358979323846; 203ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 204ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#define CalendarAstronomer_PI2 (CalendarAstronomer::PI*2.0) 205ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#define RAD_HOUR ( 12 / CalendarAstronomer::PI ) // radians -> hours 206ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#define DEG_RAD ( CalendarAstronomer::PI / 180 ) // degrees -> radians 207ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#define RAD_DEG ( 180 / CalendarAstronomer::PI ) // radians -> degrees 208ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 20985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho/*** 21085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho * Given 'value', add or subtract 'range' until 0 <= 'value' < range. 21185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho * The modulus operator. 21285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho */ 21385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Hoinline static double normalize(double value, double range) { 21485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho return value - range * ClockMath::floorDivide(value, range); 21585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho} 21685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho 21785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho/** 21885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho * Normalize an angle so that it's in the range 0 - 2pi. 21985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho * For positive angles this is just (angle % 2pi), but the Java 22085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho * mod operator doesn't work that way for negative numbers.... 22185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho */ 22285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Hoinline static double norm2PI(double angle) { 22385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho return normalize(angle, CalendarAstronomer::PI * 2.0); 22485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho} 22585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho 22685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho/** 22785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho * Normalize an angle into the range -PI - PI 22885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho */ 22985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Hoinline static double normPI(double angle) { 23085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho return normalize(angle + CalendarAstronomer::PI, CalendarAstronomer::PI * 2.0) - CalendarAstronomer::PI; 23185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho} 23285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho 233ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru//------------------------------------------------------------------------- 234ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// Constructors 235ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru//------------------------------------------------------------------------- 236ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 237ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/** 238ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * Construct a new <code>CalendarAstronomer</code> object that is initialized to 239ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * the current date and time. 240ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * @internal 241ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * @deprecated ICU 2.4. This class may be removed or modified. 242ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru */ 243ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruCalendarAstronomer::CalendarAstronomer(): 244ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru fTime(Calendar::getNow()), fLongitude(0.0), fLatitude(0.0), fGmtOffset(0.0), moonPosition(0,0), moonPositionSet(FALSE) { 245ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru clearCache(); 246ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru} 247ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 248ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/** 249ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * Construct a new <code>CalendarAstronomer</code> object that is initialized to 250ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * the specified date and time. 251ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * @internal 252ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * @deprecated ICU 2.4. This class may be removed or modified. 253ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru */ 254ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruCalendarAstronomer::CalendarAstronomer(UDate d): fTime(d), fLongitude(0.0), fLatitude(0.0), fGmtOffset(0.0), moonPosition(0,0), moonPositionSet(FALSE) { 255ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru clearCache(); 256ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru} 257ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 258ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/** 259ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * Construct a new <code>CalendarAstronomer</code> object with the given 260ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * latitude and longitude. The object's time is set to the current 261ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * date and time. 262ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * <p> 263ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * @param longitude The desired longitude, in <em>degrees</em> east of 264ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * the Greenwich meridian. 265ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * 266ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * @param latitude The desired latitude, in <em>degrees</em>. Positive 267ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * values signify North, negative South. 268ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * 269ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * @see java.util.Date#getTime() 270ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * @internal 271ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * @deprecated ICU 2.4. This class may be removed or modified. 272ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru */ 273ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruCalendarAstronomer::CalendarAstronomer(double longitude, double latitude) : 274ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru fTime(Calendar::getNow()), moonPosition(0,0), moonPositionSet(FALSE) { 275ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru fLongitude = normPI(longitude * (double)DEG_RAD); 276ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru fLatitude = normPI(latitude * (double)DEG_RAD); 277ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru fGmtOffset = (double)(fLongitude * 24. * (double)HOUR_MS / (double)CalendarAstronomer_PI2); 278ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru clearCache(); 279ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru} 280ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 281ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruCalendarAstronomer::~CalendarAstronomer() 282ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{ 283ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru} 284ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 285ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru//------------------------------------------------------------------------- 286ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// Time and date getters and setters 287ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru//------------------------------------------------------------------------- 288ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 289ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/** 290ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * Set the current date and time of this <code>CalendarAstronomer</code> object. All 291ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * astronomical calculations are performed based on this time setting. 292ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * 293ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * @param aTime the date and time, expressed as the number of milliseconds since 294ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * 1/1/1970 0:00 GMT (Gregorian). 295ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * 296ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * @see #setDate 297ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * @see #getTime 298ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * @internal 299ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * @deprecated ICU 2.4. This class may be removed or modified. 300ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru */ 301ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruvoid CalendarAstronomer::setTime(UDate aTime) { 30285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho fTime = aTime; 30385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho U_DEBUG_ASTRO_MSG(("setTime(%.1lf, %sL)\n", aTime, debug_astro_date(aTime+fGmtOffset))); 30485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho clearCache(); 305ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru} 306ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 307ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/** 308ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * Set the current date and time of this <code>CalendarAstronomer</code> object. All 309ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * astronomical calculations are performed based on this time setting. 310ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * 311ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * @param jdn the desired time, expressed as a "julian day number", 312ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * which is the number of elapsed days since 313ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * 1/1/4713 BC (Julian), 12:00 GMT. Note that julian day 314ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * numbers start at <em>noon</em>. To get the jdn for 315ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * the corresponding midnight, subtract 0.5. 316ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * 317ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * @see #getJulianDay 318ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * @see #JULIAN_EPOCH_MS 319ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * @internal 320ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * @deprecated ICU 2.4. This class may be removed or modified. 321ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru */ 322ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruvoid CalendarAstronomer::setJulianDay(double jdn) { 32385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho fTime = (double)(jdn * DAY_MS) + JULIAN_EPOCH_MS; 32485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho clearCache(); 32585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho julianDay = jdn; 326ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru} 327ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 328ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/** 329ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * Get the current time of this <code>CalendarAstronomer</code> object, 330ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * represented as the number of milliseconds since 331ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * 1/1/1970 AD 0:00 GMT (Gregorian). 332ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * 333ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * @see #setTime 334ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * @see #getDate 335ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * @internal 336ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * @deprecated ICU 2.4. This class may be removed or modified. 337ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru */ 338ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruUDate CalendarAstronomer::getTime() { 33985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho return fTime; 340ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru} 341ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 342ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/** 343ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * Get the current time of this <code>CalendarAstronomer</code> object, 344ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * expressed as a "julian day number", which is the number of elapsed 345ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * days since 1/1/4713 BC (Julian), 12:00 GMT. 346ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * 347ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * @see #setJulianDay 348ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * @see #JULIAN_EPOCH_MS 349ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * @internal 350ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * @deprecated ICU 2.4. This class may be removed or modified. 351ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru */ 352ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querudouble CalendarAstronomer::getJulianDay() { 35385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho if (isINVALID(julianDay)) { 35485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho julianDay = (fTime - (double)JULIAN_EPOCH_MS) / (double)DAY_MS; 35585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho } 35685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho return julianDay; 357ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru} 358ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 359ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/** 360ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * Return this object's time expressed in julian centuries: 361ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * the number of centuries after 1/1/1900 AD, 12:00 GMT 362ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * 363ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * @see #getJulianDay 364ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * @internal 365ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * @deprecated ICU 2.4. This class may be removed or modified. 366ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru */ 367ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querudouble CalendarAstronomer::getJulianCentury() { 36885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho if (isINVALID(julianCentury)) { 36985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho julianCentury = (getJulianDay() - 2415020.0) / 36525.0; 37085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho } 37185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho return julianCentury; 372ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru} 373ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 374ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/** 375ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * Returns the current Greenwich sidereal time, measured in hours 376ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * @internal 377ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * @deprecated ICU 2.4. This class may be removed or modified. 378ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru */ 379ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querudouble CalendarAstronomer::getGreenwichSidereal() { 38085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho if (isINVALID(siderealTime)) { 38185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho // See page 86 of "Practial Astronomy with your Calculator", 38285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho // by Peter Duffet-Smith, for details on the algorithm. 383ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 38485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho double UT = normalize(fTime/(double)HOUR_MS, 24.); 385ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 38685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho siderealTime = normalize(getSiderealOffset() + UT*1.002737909, 24.); 38785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho } 38885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho return siderealTime; 389ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru} 390ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 391ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querudouble CalendarAstronomer::getSiderealOffset() { 39285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho if (isINVALID(siderealT0)) { 39385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho double JD = uprv_floor(getJulianDay() - 0.5) + 0.5; 39485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho double S = JD - 2451545.0; 39585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho double T = S / 36525.0; 39685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho siderealT0 = normalize(6.697374558 + 2400.051336*T + 0.000025862*T*T, 24); 39785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho } 39885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho return siderealT0; 399ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru} 400ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 401ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/** 402ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * Returns the current local sidereal time, measured in hours 403ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * @internal 404ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * @deprecated ICU 2.4. This class may be removed or modified. 405ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru */ 406ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querudouble CalendarAstronomer::getLocalSidereal() { 40785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho return normalize(getGreenwichSidereal() + (fGmtOffset/(double)HOUR_MS), 24.); 408ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru} 409ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 410ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/** 411ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * Converts local sidereal time to Universal Time. 412ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * 413ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * @param lst The Local Sidereal Time, in hours since sidereal midnight 414ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * on this object's current date. 415ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * 416ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * @return The corresponding Universal Time, in milliseconds since 417ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * 1 Jan 1970, GMT. 418ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru */ 419ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querudouble CalendarAstronomer::lstToUT(double lst) { 42085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho // Convert to local mean time 42185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho double lt = normalize((lst - getSiderealOffset()) * 0.9972695663, 24); 422ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 42385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho // Then find local midnight on this day 42485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho double base = (DAY_MS * ClockMath::floorDivide(fTime + fGmtOffset,(double)DAY_MS)) - fGmtOffset; 425ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 42685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho //out(" lt =" + lt + " hours"); 42785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho //out(" base=" + new Date(base)); 428ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 42985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho return base + (long)(lt * HOUR_MS); 430ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru} 431ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 432ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 433ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru//------------------------------------------------------------------------- 434ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// Coordinate transformations, all based on the current time of this object 435ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru//------------------------------------------------------------------------- 436ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 437ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/** 438ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * Convert from ecliptic to equatorial coordinates. 439ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * 440ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * @param ecliptic A point in the sky in ecliptic coordinates. 441ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * @return The corresponding point in equatorial coordinates. 442ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * @internal 443ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * @deprecated ICU 2.4. This class may be removed or modified. 444ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru */ 445ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruCalendarAstronomer::Equatorial& CalendarAstronomer::eclipticToEquatorial(CalendarAstronomer::Equatorial& result, const CalendarAstronomer::Ecliptic& ecliptic) 446ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{ 44785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho return eclipticToEquatorial(result, ecliptic.longitude, ecliptic.latitude); 448ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru} 449ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 450ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/** 451ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * Convert from ecliptic to equatorial coordinates. 452ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * 453ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * @param eclipLong The ecliptic longitude 454ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * @param eclipLat The ecliptic latitude 455ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * 456ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * @return The corresponding point in equatorial coordinates. 457ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * @internal 458ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * @deprecated ICU 2.4. This class may be removed or modified. 459ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru */ 460ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruCalendarAstronomer::Equatorial& CalendarAstronomer::eclipticToEquatorial(CalendarAstronomer::Equatorial& result, double eclipLong, double eclipLat) 461ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{ 46285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho // See page 42 of "Practial Astronomy with your Calculator", 46385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho // by Peter Duffet-Smith, for details on the algorithm. 464ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 46585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho double obliq = eclipticObliquity(); 46685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho double sinE = ::sin(obliq); 46785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho double cosE = cos(obliq); 468ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 46985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho double sinL = ::sin(eclipLong); 47085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho double cosL = cos(eclipLong); 471ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 47285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho double sinB = ::sin(eclipLat); 47385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho double cosB = cos(eclipLat); 47485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho double tanB = tan(eclipLat); 475ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 47685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho result.set(atan2(sinL*cosE - tanB*sinE, cosL), 47785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho asin(sinB*cosE + cosB*sinE*sinL) ); 47885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho return result; 479ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru} 480ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 481ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/** 482ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * Convert from ecliptic longitude to equatorial coordinates. 483ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * 484ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * @param eclipLong The ecliptic longitude 485ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * 486ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * @return The corresponding point in equatorial coordinates. 487ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * @internal 488ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * @deprecated ICU 2.4. This class may be removed or modified. 489ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru */ 490ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruCalendarAstronomer::Equatorial& CalendarAstronomer::eclipticToEquatorial(CalendarAstronomer::Equatorial& result, double eclipLong) 491ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{ 49285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho return eclipticToEquatorial(result, eclipLong, 0); // TODO: optimize 493ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru} 494ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 495ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/** 496ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * @internal 497ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * @deprecated ICU 2.4. This class may be removed or modified. 498ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru */ 499ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruCalendarAstronomer::Horizon& CalendarAstronomer::eclipticToHorizon(CalendarAstronomer::Horizon& result, double eclipLong) 500ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{ 50185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho Equatorial equatorial; 50285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho eclipticToEquatorial(equatorial, eclipLong); 503ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 50485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho double H = getLocalSidereal()*CalendarAstronomer::PI/12 - equatorial.ascension; // Hour-angle 505ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 50685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho double sinH = ::sin(H); 50785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho double cosH = cos(H); 50885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho double sinD = ::sin(equatorial.declination); 50985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho double cosD = cos(equatorial.declination); 51085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho double sinL = ::sin(fLatitude); 51185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho double cosL = cos(fLatitude); 512ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 51385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho double altitude = asin(sinD*sinL + cosD*cosL*cosH); 51485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho double azimuth = atan2(-cosD*cosL*sinH, sinD - sinL * ::sin(altitude)); 515ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 51685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho result.set(azimuth, altitude); 51785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho return result; 518ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru} 519ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 520ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 521ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru//------------------------------------------------------------------------- 522ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// The Sun 523ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru//------------------------------------------------------------------------- 524ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 525ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// 526ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// Parameters of the Sun's orbit as of the epoch Jan 0.0 1990 527ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// Angles are in radians (after multiplying by CalendarAstronomer::PI/180) 528ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// 529ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#define JD_EPOCH 2447891.5 // Julian day of epoch 530ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 531ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#define SUN_ETA_G (279.403303 * CalendarAstronomer::PI/180) // Ecliptic longitude at epoch 532ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#define SUN_OMEGA_G (282.768422 * CalendarAstronomer::PI/180) // Ecliptic longitude of perigee 533ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#define SUN_E 0.016713 // Eccentricity of orbit 534ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru//double sunR0 1.495585e8 // Semi-major axis in KM 535ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru//double sunTheta0 (0.533128 * CalendarAstronomer::PI/180) // Angular diameter at R0 536ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 537ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// The following three methods, which compute the sun parameters 538ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// given above for an arbitrary epoch (whatever time the object is 539ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// set to), make only a small difference as compared to using the 540ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// above constants. E.g., Sunset times might differ by ~12 541ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// seconds. Furthermore, the eta-g computation is befuddled by 542ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// Duffet-Smith's incorrect coefficients (p.86). I've corrected 543ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// the first-order coefficient but the others may be off too - no 544ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// way of knowing without consulting another source. 545ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 546ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// /** 547ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// * Return the sun's ecliptic longitude at perigee for the current time. 548ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// * See Duffett-Smith, p. 86. 549ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// * @return radians 550ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// */ 551ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// private double getSunOmegaG() { 552ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// double T = getJulianCentury(); 553ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// return (281.2208444 + (1.719175 + 0.000452778*T)*T) * DEG_RAD; 554ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// } 555ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 556ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// /** 557ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// * Return the sun's ecliptic longitude for the current time. 558ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// * See Duffett-Smith, p. 86. 559ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// * @return radians 560ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// */ 561ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// private double getSunEtaG() { 562ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// double T = getJulianCentury(); 563ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// //return (279.6966778 + (36000.76892 + 0.0003025*T)*T) * DEG_RAD; 564ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// // 565ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// // The above line is from Duffett-Smith, and yields manifestly wrong 566ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// // results. The below constant is derived empirically to match the 567ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// // constant he gives for the 1990 EPOCH. 568ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// // 569ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// return (279.6966778 + (-0.3262541582718024 + 0.0003025*T)*T) * DEG_RAD; 570ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// } 571ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 572ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// /** 573ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// * Return the sun's eccentricity of orbit for the current time. 574ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// * See Duffett-Smith, p. 86. 575ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// * @return double 576ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// */ 577ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// private double getSunE() { 578ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// double T = getJulianCentury(); 579ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// return 0.01675104 - (0.0000418 + 0.000000126*T)*T; 580ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// } 581ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 582ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/** 58385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho * Find the "true anomaly" (longitude) of an object from 58485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho * its mean anomaly and the eccentricity of its orbit. This uses 58585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho * an iterative solution to Kepler's equation. 58685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho * 58785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho * @param meanAnomaly The object's longitude calculated as if it were in 58885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho * a regular, circular orbit, measured in radians 58985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho * from the point of perigee. 59085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho * 59185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho * @param eccentricity The eccentricity of the orbit 59285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho * 59385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho * @return The true anomaly (longitude) measured in radians 59485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho */ 59585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Hostatic double trueAnomaly(double meanAnomaly, double eccentricity) 59685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho{ 59785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho // First, solve Kepler's equation iteratively 59885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho // Duffett-Smith, p.90 59985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho double delta; 60085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho double E = meanAnomaly; 60185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho do { 60285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho delta = E - eccentricity * ::sin(E) - meanAnomaly; 60385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho E = E - delta / (1 - eccentricity * ::cos(E)); 60485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho } 60585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho while (uprv_fabs(delta) > 1e-5); // epsilon = 1e-5 rad 60685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho 60785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho return 2.0 * ::atan( ::tan(E/2) * ::sqrt( (1+eccentricity) 60885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho /(1-eccentricity) ) ); 60985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho} 61085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho 61185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho/** 612ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * The longitude of the sun at the time specified by this object. 613ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * The longitude is measured in radians along the ecliptic 614ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * from the "first point of Aries," the point at which the ecliptic 615ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * crosses the earth's equatorial plane at the vernal equinox. 616ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * <p> 617ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * Currently, this method uses an approximation of the two-body Kepler's 618ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * equation for the earth and the sun. It does not take into account the 619ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * perturbations caused by the other planets, the moon, etc. 620ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * @internal 621ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * @deprecated ICU 2.4. This class may be removed or modified. 622ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru */ 623ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querudouble CalendarAstronomer::getSunLongitude() 624ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{ 62585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho // See page 86 of "Practial Astronomy with your Calculator", 62685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho // by Peter Duffet-Smith, for details on the algorithm. 627ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 62885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho if (isINVALID(sunLongitude)) { 62985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho getSunLongitude(getJulianDay(), sunLongitude, meanAnomalySun); 63085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho } 63185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho return sunLongitude; 632ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru} 633ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 634ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/** 635ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * TODO Make this public when the entire class is package-private. 636ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru */ 637ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/*public*/ void CalendarAstronomer::getSunLongitude(double jDay, double &longitude, double &meanAnomaly) 638ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{ 63985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho // See page 86 of "Practial Astronomy with your Calculator", 64085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho // by Peter Duffet-Smith, for details on the algorithm. 641ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 64285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho double day = jDay - JD_EPOCH; // Days since epoch 643ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 64485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho // Find the angular distance the sun in a fictitious 64585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho // circular orbit has travelled since the epoch. 64685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho double epochAngle = norm2PI(CalendarAstronomer_PI2/TROPICAL_YEAR*day); 647ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 64885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho // The epoch wasn't at the sun's perigee; find the angular distance 64985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho // since perigee, which is called the "mean anomaly" 65085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho meanAnomaly = norm2PI(epochAngle + SUN_ETA_G - SUN_OMEGA_G); 651ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 65285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho // Now find the "true anomaly", e.g. the real solar longitude 65385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho // by solving Kepler's equation for an elliptical orbit 65485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho // NOTE: The 3rd ed. of the book lists omega_g and eta_g in different 65585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho // equations; omega_g is to be correct. 65685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho longitude = norm2PI(trueAnomaly(meanAnomaly, SUN_E) + SUN_OMEGA_G); 657ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru} 658ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 659ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/** 660ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * The position of the sun at this object's current date and time, 661ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * in equatorial coordinates. 662ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * @internal 663ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * @deprecated ICU 2.4. This class may be removed or modified. 664ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru */ 665ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruCalendarAstronomer::Equatorial& CalendarAstronomer::getSunPosition(CalendarAstronomer::Equatorial& result) { 66685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho return eclipticToEquatorial(result, getSunLongitude(), 0); 667ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru} 668ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 669ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 670ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/** 671ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * Constant representing the vernal equinox. 672ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * For use with {@link #getSunTime getSunTime}. 673ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * Note: In this case, "vernal" refers to the northern hemisphere's seasons. 674ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * @internal 675ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * @deprecated ICU 2.4. This class may be removed or modified. 676ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru */ 677ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/*double CalendarAstronomer::VERNAL_EQUINOX() { 678ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru return 0; 679ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}*/ 680ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 681ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/** 682ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * Constant representing the summer solstice. 683ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * For use with {@link #getSunTime getSunTime}. 684ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * Note: In this case, "summer" refers to the northern hemisphere's seasons. 685ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * @internal 686ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * @deprecated ICU 2.4. This class may be removed or modified. 687ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru */ 688ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querudouble CalendarAstronomer::SUMMER_SOLSTICE() { 68985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho return (CalendarAstronomer::PI/2); 690ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru} 691ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 692ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/** 693ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * Constant representing the autumnal equinox. 694ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * For use with {@link #getSunTime getSunTime}. 695ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * Note: In this case, "autumn" refers to the northern hemisphere's seasons. 696ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * @internal 697ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * @deprecated ICU 2.4. This class may be removed or modified. 698ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru */ 699ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/*double CalendarAstronomer::AUTUMN_EQUINOX() { 700ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru return (CalendarAstronomer::PI); 701ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}*/ 702ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 703ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/** 704ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * Constant representing the winter solstice. 705ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * For use with {@link #getSunTime getSunTime}. 706ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * Note: In this case, "winter" refers to the northern hemisphere's seasons. 707ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * @internal 708ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * @deprecated ICU 2.4. This class may be removed or modified. 709ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru */ 71085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Hodouble CalendarAstronomer::WINTER_SOLSTICE() { 71185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho return ((CalendarAstronomer::PI*3)/2); 71285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho} 713ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 714ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruCalendarAstronomer::AngleFunc::~AngleFunc() {} 715ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 716ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/** 717ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * Find the next time at which the sun's ecliptic longitude will have 718ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * the desired value. 719ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * @internal 720ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * @deprecated ICU 2.4. This class may be removed or modified. 721ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru */ 722ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruclass SunTimeAngleFunc : public CalendarAstronomer::AngleFunc { 723ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querupublic: 72485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho virtual double eval(CalendarAstronomer& a) { return a.getSunLongitude(); } 725ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}; 726ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 727ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruUDate CalendarAstronomer::getSunTime(double desired, UBool next) 728ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{ 72985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho SunTimeAngleFunc func; 73085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho return timeOfAngle( func, 73185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho desired, 73285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho TROPICAL_YEAR, 73385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho MINUTE_MS, 73485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho next); 735ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru} 736ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 737ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruCalendarAstronomer::CoordFunc::~CoordFunc() {} 738ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 739ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruclass RiseSetCoordFunc : public CalendarAstronomer::CoordFunc { 740ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querupublic: 74185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho virtual void eval(CalendarAstronomer::Equatorial& result, CalendarAstronomer&a) { a.getSunPosition(result); } 742ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}; 743ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 744ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruUDate CalendarAstronomer::getSunRiseSet(UBool rise) 745ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{ 74685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho UDate t0 = fTime; 747ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 74885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho // Make a rough guess: 6am or 6pm local time on the current day 74985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho double noon = ClockMath::floorDivide(fTime + fGmtOffset, (double)DAY_MS)*DAY_MS - fGmtOffset + (12*HOUR_MS); 750ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 75185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho U_DEBUG_ASTRO_MSG(("Noon=%.2lf, %sL, gmtoff %.2lf\n", noon, debug_astro_date(noon+fGmtOffset), fGmtOffset)); 75285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho setTime(noon + ((rise ? -6 : 6) * HOUR_MS)); 75385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho U_DEBUG_ASTRO_MSG(("added %.2lf ms as a guess,\n", ((rise ? -6. : 6.) * HOUR_MS))); 754ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 75585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho RiseSetCoordFunc func; 75685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho double t = riseOrSet(func, 75785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho rise, 75885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho .533 * DEG_RAD, // Angular Diameter 75985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho 34. /60.0 * DEG_RAD, // Refraction correction 76085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho MINUTE_MS / 12.); // Desired accuracy 761ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 76285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho setTime(t0); 76385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho return t; 764ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru} 765ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 766ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// Commented out - currently unused. ICU 2.6, Alan 767ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// //------------------------------------------------------------------------- 768ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// // Alternate Sun Rise/Set 769ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// // See Duffett-Smith p.93 770ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// //------------------------------------------------------------------------- 771ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// 772ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// // This yields worse results (as compared to USNO data) than getSunRiseSet(). 773ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// /** 774ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// * TODO Make this when the entire class is package-private. 775ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// */ 776ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// /*public*/ long getSunRiseSet2(boolean rise) { 777ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// // 1. Calculate coordinates of the sun's center for midnight 778ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// double jd = uprv_floor(getJulianDay() - 0.5) + 0.5; 779ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// double[] sl = getSunLongitude(jd);// double lambda1 = sl[0]; 780ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// Equatorial pos1 = eclipticToEquatorial(lambda1, 0); 781ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// 782ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// // 2. Add ... to lambda to get position 24 hours later 783ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// double lambda2 = lambda1 + 0.985647*DEG_RAD; 784ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// Equatorial pos2 = eclipticToEquatorial(lambda2, 0); 785ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// 786ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// // 3. Calculate LSTs of rising and setting for these two positions 787ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// double tanL = ::tan(fLatitude); 788ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// double H = ::acos(-tanL * ::tan(pos1.declination)); 789ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// double lst1r = (CalendarAstronomer_PI2 + pos1.ascension - H) * 24 / CalendarAstronomer_PI2; 790ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// double lst1s = (pos1.ascension + H) * 24 / CalendarAstronomer_PI2; 791ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// H = ::acos(-tanL * ::tan(pos2.declination)); 792ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// double lst2r = (CalendarAstronomer_PI2-H + pos2.ascension ) * 24 / CalendarAstronomer_PI2; 793ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// double lst2s = (H + pos2.ascension ) * 24 / CalendarAstronomer_PI2; 794ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// if (lst1r > 24) lst1r -= 24; 795ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// if (lst1s > 24) lst1s -= 24; 796ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// if (lst2r > 24) lst2r -= 24; 797ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// if (lst2s > 24) lst2s -= 24; 798ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// 799ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// // 4. Convert LSTs to GSTs. If GST1 > GST2, add 24 to GST2. 800ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// double gst1r = lstToGst(lst1r); 801ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// double gst1s = lstToGst(lst1s); 802ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// double gst2r = lstToGst(lst2r); 803ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// double gst2s = lstToGst(lst2s); 804ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// if (gst1r > gst2r) gst2r += 24; 805ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// if (gst1s > gst2s) gst2s += 24; 806ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// 807ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// // 5. Calculate GST at 0h UT of this date 808ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// double t00 = utToGst(0); 809ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// 810ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// // 6. Calculate GST at 0h on the observer's longitude 811ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// double offset = ::round(fLongitude*12/PI); // p.95 step 6; he _rounds_ to nearest 15 deg. 812ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// double t00p = t00 - offset*1.002737909; 813ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// if (t00p < 0) t00p += 24; // do NOT normalize 814ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// 815ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// // 7. Adjust 816ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// if (gst1r < t00p) { 817ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// gst1r += 24; 818ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// gst2r += 24; 819ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// } 820ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// if (gst1s < t00p) { 821ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// gst1s += 24; 822ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// gst2s += 24; 823ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// } 824ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// 825ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// // 8. 826ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// double gstr = (24.07*gst1r-t00*(gst2r-gst1r))/(24.07+gst1r-gst2r); 827ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// double gsts = (24.07*gst1s-t00*(gst2s-gst1s))/(24.07+gst1s-gst2s); 828ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// 829ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// // 9. Correct for parallax, refraction, and sun's diameter 830ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// double dec = (pos1.declination + pos2.declination) / 2; 831ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// double psi = ::acos(sin(fLatitude) / cos(dec)); 832ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// double x = 0.830725 * DEG_RAD; // parallax+refraction+diameter 833ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// double y = ::asin(sin(x) / ::sin(psi)) * RAD_DEG; 834ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// double delta_t = 240 * y / cos(dec) / 3600; // hours 835ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// 836ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// // 10. Add correction to GSTs, subtract from GSTr 837ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// gstr -= delta_t; 838ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// gsts += delta_t; 839ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// 840ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// // 11. Convert GST to UT and then to local civil time 841ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// double ut = gstToUt(rise ? gstr : gsts); 842ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// //System.out.println((rise?"rise=":"set=") + ut + ", delta_t=" + delta_t); 843ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// long midnight = DAY_MS * (time / DAY_MS); // Find UT midnight on this day 844ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// return midnight + (long) (ut * 3600000); 845ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// } 846ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 847ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// Commented out - currently unused. ICU 2.6, Alan 848ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// /** 849ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// * Convert local sidereal time to Greenwich sidereal time. 850ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// * Section 15. Duffett-Smith p.21 851ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// * @param lst in hours (0..24) 852ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// * @return GST in hours (0..24) 853ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// */ 854ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// double lstToGst(double lst) { 855ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// double delta = fLongitude * 24 / CalendarAstronomer_PI2; 856ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// return normalize(lst - delta, 24); 857ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// } 858ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 859ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// Commented out - currently unused. ICU 2.6, Alan 860ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// /** 861ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// * Convert UT to GST on this date. 862ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// * Section 12. Duffett-Smith p.17 863ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// * @param ut in hours 864ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// * @return GST in hours 865ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// */ 866ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// double utToGst(double ut) { 867ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// return normalize(getT0() + ut*1.002737909, 24); 868ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// } 869ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 870ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// Commented out - currently unused. ICU 2.6, Alan 871ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// /** 872ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// * Convert GST to UT on this date. 873ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// * Section 13. Duffett-Smith p.18 874ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// * @param gst in hours 875ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// * @return UT in hours 876ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// */ 877ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// double gstToUt(double gst) { 878ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// return normalize(gst - getT0(), 24) * 0.9972695663; 879ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// } 880ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 881ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// Commented out - currently unused. ICU 2.6, Alan 882ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// double getT0() { 883ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// // Common computation for UT <=> GST 884ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// 885ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// // Find JD for 0h UT 886ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// double jd = uprv_floor(getJulianDay() - 0.5) + 0.5; 887ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// 888ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// double s = jd - 2451545.0; 889ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// double t = s / 36525.0; 890ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// double t0 = 6.697374558 + (2400.051336 + 0.000025862*t)*t; 891ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// return t0; 892ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// } 893ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 894ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// Commented out - currently unused. ICU 2.6, Alan 895ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// //------------------------------------------------------------------------- 896ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// // Alternate Sun Rise/Set 897ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// // See sci.astro FAQ 898ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// // http://www.faqs.org/faqs/astronomy/faq/part3/section-5.html 899ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// //------------------------------------------------------------------------- 900ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// 901ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// // Note: This method appears to produce inferior accuracy as 902ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// // compared to getSunRiseSet(). 903ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// 904ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// /** 905ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// * TODO Make this when the entire class is package-private. 906ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// */ 907ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// /*public*/ long getSunRiseSet3(boolean rise) { 908ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// 909ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// // Compute day number for 0.0 Jan 2000 epoch 910ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// double d = (double)(time - EPOCH_2000_MS) / DAY_MS; 911ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// 912ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// // Now compute the Local Sidereal Time, LST: 913ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// // 914ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// double LST = 98.9818 + 0.985647352 * d + /*UT*15 + long*/ 915ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// fLongitude*RAD_DEG; 916ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// // 917ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// // (east long. positive). Note that LST is here expressed in degrees, 918ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// // where 15 degrees corresponds to one hour. Since LST really is an angle, 919ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// // it's convenient to use one unit---degrees---throughout. 920ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// 921ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// // COMPUTING THE SUN'S POSITION 922ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// // ---------------------------- 923ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// // 924ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// // To be able to compute the Sun's rise/set times, you need to be able to 925ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// // compute the Sun's position at any time. First compute the "day 926ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// // number" d as outlined above, for the desired moment. Next compute: 927ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// // 928ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// double oblecl = 23.4393 - 3.563E-7 * d; 929ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// // 930ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// double w = 282.9404 + 4.70935E-5 * d; 931ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// double M = 356.0470 + 0.9856002585 * d; 932ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// double e = 0.016709 - 1.151E-9 * d; 933ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// // 934ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// // This is the obliquity of the ecliptic, plus some of the elements of 935ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// // the Sun's apparent orbit (i.e., really the Earth's orbit): w = 936ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// // argument of perihelion, M = mean anomaly, e = eccentricity. 937ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// // Semi-major axis is here assumed to be exactly 1.0 (while not strictly 938ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// // true, this is still an accurate approximation). Next compute E, the 939ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// // eccentric anomaly: 940ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// // 941ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// double E = M + e*(180/PI) * ::sin(M*DEG_RAD) * ( 1.0 + e*cos(M*DEG_RAD) ); 942ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// // 943ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// // where E and M are in degrees. This is it---no further iterations are 944ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// // needed because we know e has a sufficiently small value. Next compute 945ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// // the true anomaly, v, and the distance, r: 946ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// // 947ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// /* r * cos(v) = */ double A = cos(E*DEG_RAD) - e; 948ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// /* r * ::sin(v) = */ double B = ::sqrt(1 - e*e) * ::sin(E*DEG_RAD); 949ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// // 950ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// // and 951ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// // 952ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// // r = sqrt( A*A + B*B ) 953ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// double v = ::atan2( B, A )*RAD_DEG; 954ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// // 955ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// // The Sun's true longitude, slon, can now be computed: 956ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// // 957ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// double slon = v + w; 958ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// // 959ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// // Since the Sun is always at the ecliptic (or at least very very close to 960ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// // it), we can use simplified formulae to convert slon (the Sun's ecliptic 961ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// // longitude) to sRA and sDec (the Sun's RA and Dec): 962ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// // 963ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// // ::sin(slon) * cos(oblecl) 964ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// // tan(sRA) = ------------------------- 965ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// // cos(slon) 966ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// // 967ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// // ::sin(sDec) = ::sin(oblecl) * ::sin(slon) 968ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// // 969ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// // As was the case when computing az, the Azimuth, if possible use an 970ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// // atan2() function to compute sRA. 971ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// 972ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// double sRA = ::atan2(sin(slon*DEG_RAD) * cos(oblecl*DEG_RAD), cos(slon*DEG_RAD))*RAD_DEG; 973ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// 974ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// double sin_sDec = ::sin(oblecl*DEG_RAD) * ::sin(slon*DEG_RAD); 975ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// double sDec = ::asin(sin_sDec)*RAD_DEG; 976ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// 977ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// // COMPUTING RISE AND SET TIMES 978ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// // ---------------------------- 979ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// // 980ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// // To compute when an object rises or sets, you must compute when it 981ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// // passes the meridian and the HA of rise/set. Then the rise time is 982ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// // the meridian time minus HA for rise/set, and the set time is the 983ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// // meridian time plus the HA for rise/set. 984ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// // 985ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// // To find the meridian time, compute the Local Sidereal Time at 0h local 986ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// // time (or 0h UT if you prefer to work in UT) as outlined above---name 987ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// // that quantity LST0. The Meridian Time, MT, will now be: 988ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// // 989ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// // MT = RA - LST0 990ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// double MT = normalize(sRA - LST, 360); 991ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// // 992ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// // where "RA" is the object's Right Ascension (in degrees!). If negative, 993ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// // add 360 deg to MT. If the object is the Sun, leave the time as it is, 994ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// // but if it's stellar, multiply MT by 365.2422/366.2422, to convert from 995ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// // sidereal to solar time. Now, compute HA for rise/set, name that 996ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// // quantity HA0: 997ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// // 998ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// // ::sin(h0) - ::sin(lat) * ::sin(Dec) 999ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// // cos(HA0) = --------------------------------- 1000ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// // cos(lat) * cos(Dec) 1001ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// // 1002ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// // where h0 is the altitude selected to represent rise/set. For a purely 1003ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// // mathematical horizon, set h0 = 0 and simplify to: 1004ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// // 1005ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// // cos(HA0) = - tan(lat) * tan(Dec) 1006ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// // 1007ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// // If you want to account for refraction on the atmosphere, set h0 = -35/60 1008ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// // degrees (-35 arc minutes), and if you want to compute the rise/set times 1009ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// // for the Sun's upper limb, set h0 = -50/60 (-50 arc minutes). 1010ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// // 1011ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// double h0 = -50/60 * DEG_RAD; 1012ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// 1013ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// double HA0 = ::acos( 1014ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// (sin(h0) - ::sin(fLatitude) * sin_sDec) / 1015ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// (cos(fLatitude) * cos(sDec*DEG_RAD)))*RAD_DEG; 1016ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// 1017ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// // When HA0 has been computed, leave it as it is for the Sun but multiply 1018ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// // by 365.2422/366.2422 for stellar objects, to convert from sidereal to 1019ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// // solar time. Finally compute: 1020ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// // 1021ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// // Rise time = MT - HA0 1022ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// // Set time = MT + HA0 1023ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// // 1024ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// // convert the times from degrees to hours by dividing by 15. 1025ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// // 1026ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// // If you'd like to check that your calculations are accurate or just 1027ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// // need a quick result, check the USNO's Sun or Moon Rise/Set Table, 1028ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// // <URL:http://aa.usno.navy.mil/AA/data/docs/RS_OneYear.html>. 1029ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// 1030ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// double result = MT + (rise ? -HA0 : HA0); // in degrees 1031ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// 1032ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// // Find UT midnight on this day 1033ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// long midnight = DAY_MS * (time / DAY_MS); 1034ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// 1035ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// return midnight + (long) (result * 3600000 / 15); 1036ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// } 1037ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 1038ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru//------------------------------------------------------------------------- 1039ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// The Moon 1040ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru//------------------------------------------------------------------------- 1041ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 1042ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#define moonL0 (318.351648 * CalendarAstronomer::PI/180 ) // Mean long. at epoch 1043ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#define moonP0 ( 36.340410 * CalendarAstronomer::PI/180 ) // Mean long. of perigee 1044ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#define moonN0 ( 318.510107 * CalendarAstronomer::PI/180 ) // Mean long. of node 1045ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#define moonI ( 5.145366 * CalendarAstronomer::PI/180 ) // Inclination of orbit 1046ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#define moonE ( 0.054900 ) // Eccentricity of orbit 1047ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 1048ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// These aren't used right now 1049ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#define moonA ( 3.84401e5 ) // semi-major axis (km) 1050ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#define moonT0 ( 0.5181 * CalendarAstronomer::PI/180 ) // Angular size at distance A 1051ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#define moonPi ( 0.9507 * CalendarAstronomer::PI/180 ) // Parallax at distance A 1052ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 1053ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/** 1054ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * The position of the moon at the time set on this 1055ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * object, in equatorial coordinates. 1056ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * @internal 1057ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * @deprecated ICU 2.4. This class may be removed or modified. 1058ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru */ 1059ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruconst CalendarAstronomer::Equatorial& CalendarAstronomer::getMoonPosition() 1060ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{ 1061ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru // 106285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho // See page 142 of "Practial Astronomy with your Calculator", 106385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho // by Peter Duffet-Smith, for details on the algorithm. 1064ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru // 106585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho if (moonPositionSet == FALSE) { 106685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho // Calculate the solar longitude. Has the side effect of 106785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho // filling in "meanAnomalySun" as well. 106885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho getSunLongitude(); 106985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho 107085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho // 107185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho // Find the # of days since the epoch of our orbital parameters. 107285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho // TODO: Convert the time of day portion into ephemeris time 107385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho // 107485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho double day = getJulianDay() - JD_EPOCH; // Days since epoch 107585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho 107685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho // Calculate the mean longitude and anomaly of the moon, based on 107785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho // a circular orbit. Similar to the corresponding solar calculation. 107885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho double meanLongitude = norm2PI(13.1763966*PI/180*day + moonL0); 107985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho meanAnomalyMoon = norm2PI(meanLongitude - 0.1114041*PI/180 * day - moonP0); 108085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho 108185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho // 108285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho // Calculate the following corrections: 108385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho // Evection: the sun's gravity affects the moon's eccentricity 108485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho // Annual Eqn: variation in the effect due to earth-sun distance 108585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho // A3: correction factor (for ???) 108685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho // 108785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho double evection = 1.2739*PI/180 * ::sin(2 * (meanLongitude - sunLongitude) 108885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho - meanAnomalyMoon); 108985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho double annual = 0.1858*PI/180 * ::sin(meanAnomalySun); 109085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho double a3 = 0.3700*PI/180 * ::sin(meanAnomalySun); 109185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho 109285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho meanAnomalyMoon += evection - annual - a3; 109385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho 109485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho // 109585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho // More correction factors: 109685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho // center equation of the center correction 109785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho // a4 yet another error correction (???) 109885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho // 109985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho // TODO: Skip the equation of the center correction and solve Kepler's eqn? 110085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho // 110185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho double center = 6.2886*PI/180 * ::sin(meanAnomalyMoon); 110285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho double a4 = 0.2140*PI/180 * ::sin(2 * meanAnomalyMoon); 110385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho 110485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho // Now find the moon's corrected longitude 110585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho moonLongitude = meanLongitude + evection + center - annual + a4; 110685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho 110785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho // 110885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho // And finally, find the variation, caused by the fact that the sun's 110985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho // gravitational pull on the moon varies depending on which side of 111085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho // the earth the moon is on 111185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho // 111285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho double variation = 0.6583*CalendarAstronomer::PI/180 * ::sin(2*(moonLongitude - sunLongitude)); 111385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho 111485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho moonLongitude += variation; 111585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho 111685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho // 111785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho // What we've calculated so far is the moon's longitude in the plane 111885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho // of its own orbit. Now map to the ecliptic to get the latitude 111985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho // and longitude. First we need to find the longitude of the ascending 112085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho // node, the position on the ecliptic where it is crossed by the moon's 112185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho // orbit as it crosses from the southern to the northern hemisphere. 112285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho // 112385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho double nodeLongitude = norm2PI(moonN0 - 0.0529539*PI/180 * day); 112485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho 112585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho nodeLongitude -= 0.16*PI/180 * ::sin(meanAnomalySun); 112685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho 112785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho double y = ::sin(moonLongitude - nodeLongitude); 112885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho double x = cos(moonLongitude - nodeLongitude); 112985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho 113085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho moonEclipLong = ::atan2(y*cos(moonI), x) + nodeLongitude; 113185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho double moonEclipLat = ::asin(y * ::sin(moonI)); 113285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho 113385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho eclipticToEquatorial(moonPosition, moonEclipLong, moonEclipLat); 113485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho moonPositionSet = TRUE; 113585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho } 113685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho return moonPosition; 1137ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru} 1138ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 1139ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/** 1140ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * The "age" of the moon at the time specified in this object. 1141ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * This is really the angle between the 1142ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * current ecliptic longitudes of the sun and the moon, 1143ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * measured in radians. 1144ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * 1145ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * @see #getMoonPhase 1146ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * @internal 1147ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * @deprecated ICU 2.4. This class may be removed or modified. 1148ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru */ 1149ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querudouble CalendarAstronomer::getMoonAge() { 115085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho // See page 147 of "Practial Astronomy with your Calculator", 115185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho // by Peter Duffet-Smith, for details on the algorithm. 115285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho // 115385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho // Force the moon's position to be calculated. We're going to use 115485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho // some the intermediate results cached during that calculation. 115585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho // 115685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho getMoonPosition(); 115785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho 115885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho return norm2PI(moonEclipLong - sunLongitude); 1159ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru} 1160ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 1161ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/** 1162ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * Calculate the phase of the moon at the time set in this object. 1163ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * The returned phase is a <code>double</code> in the range 1164ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * <code>0 <= phase < 1</code>, interpreted as follows: 1165ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * <ul> 1166ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * <li>0.00: New moon 1167ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * <li>0.25: First quarter 1168ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * <li>0.50: Full moon 1169ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * <li>0.75: Last quarter 1170ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * </ul> 1171ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * 1172ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * @see #getMoonAge 1173ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * @internal 1174ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * @deprecated ICU 2.4. This class may be removed or modified. 1175ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru */ 1176ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querudouble CalendarAstronomer::getMoonPhase() { 117785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho // See page 147 of "Practial Astronomy with your Calculator", 117885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho // by Peter Duffet-Smith, for details on the algorithm. 117985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho return 0.5 * (1 - cos(getMoonAge())); 1180ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru} 1181ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 1182ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/** 1183ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * Constant representing a new moon. 1184ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * For use with {@link #getMoonTime getMoonTime} 1185ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * @internal 1186ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * @deprecated ICU 2.4. This class may be removed or modified. 1187ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru */ 118885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Hoconst CalendarAstronomer::MoonAge CalendarAstronomer::NEW_MOON() { 118985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho return CalendarAstronomer::MoonAge(0); 119085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho} 1191ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 1192ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/** 1193ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * Constant representing the moon's first quarter. 1194ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * For use with {@link #getMoonTime getMoonTime} 1195ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * @internal 1196ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * @deprecated ICU 2.4. This class may be removed or modified. 1197ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru */ 1198ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/*const CalendarAstronomer::MoonAge CalendarAstronomer::FIRST_QUARTER() { 1199ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru return CalendarAstronomer::MoonAge(CalendarAstronomer::PI/2); 1200ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}*/ 1201ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 1202ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/** 1203ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * Constant representing a full moon. 1204ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * For use with {@link #getMoonTime getMoonTime} 1205ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * @internal 1206ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * @deprecated ICU 2.4. This class may be removed or modified. 1207ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru */ 1208ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruconst CalendarAstronomer::MoonAge CalendarAstronomer::FULL_MOON() { 120985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho return CalendarAstronomer::MoonAge(CalendarAstronomer::PI); 1210ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru} 1211ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/** 1212ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * Constant representing the moon's last quarter. 1213ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * For use with {@link #getMoonTime getMoonTime} 1214ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * @internal 1215ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * @deprecated ICU 2.4. This class may be removed or modified. 1216ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru */ 1217ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 1218ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruclass MoonTimeAngleFunc : public CalendarAstronomer::AngleFunc { 1219ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querupublic: 122085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho virtual double eval(CalendarAstronomer&a) { return a.getMoonAge(); } 1221ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}; 1222ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 1223ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/*const CalendarAstronomer::MoonAge CalendarAstronomer::LAST_QUARTER() { 1224ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru return CalendarAstronomer::MoonAge((CalendarAstronomer::PI*3)/2); 1225ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}*/ 1226ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 1227ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/** 1228ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * Find the next or previous time at which the Moon's ecliptic 1229ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * longitude will have the desired value. 1230ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * <p> 1231ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * @param desired The desired longitude. 1232ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * @param next <tt>true</tt> if the next occurrance of the phase 1233ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * is desired, <tt>false</tt> for the previous occurrance. 1234ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * @internal 1235ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * @deprecated ICU 2.4. This class may be removed or modified. 1236ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru */ 1237ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruUDate CalendarAstronomer::getMoonTime(double desired, UBool next) 1238ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{ 123985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho MoonTimeAngleFunc func; 124085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho return timeOfAngle( func, 124185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho desired, 124285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho SYNODIC_MONTH, 124385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho MINUTE_MS, 124485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho next); 1245ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru} 1246ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 1247ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/** 1248ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * Find the next or previous time at which the moon will be in the 1249ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * desired phase. 1250ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * <p> 1251ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * @param desired The desired phase of the moon. 1252ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * @param next <tt>true</tt> if the next occurrance of the phase 1253ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * is desired, <tt>false</tt> for the previous occurrance. 1254ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * @internal 1255ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * @deprecated ICU 2.4. This class may be removed or modified. 1256ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru */ 1257ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruUDate CalendarAstronomer::getMoonTime(const CalendarAstronomer::MoonAge& desired, UBool next) { 125885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho return getMoonTime(desired.value, next); 1259ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru} 1260ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 1261ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruclass MoonRiseSetCoordFunc : public CalendarAstronomer::CoordFunc { 1262ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querupublic: 126385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho virtual void eval(CalendarAstronomer::Equatorial& result, CalendarAstronomer&a) { result = a.getMoonPosition(); } 1264ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}; 1265ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 1266ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/** 1267ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * Returns the time (GMT) of sunrise or sunset on the local date to which 1268ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * this calendar is currently set. 1269ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * @internal 1270ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * @deprecated ICU 2.4. This class may be removed or modified. 1271ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru */ 1272ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruUDate CalendarAstronomer::getMoonRiseSet(UBool rise) 1273ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{ 127485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho MoonRiseSetCoordFunc func; 127585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho return riseOrSet(func, 127685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho rise, 127785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho .533 * DEG_RAD, // Angular Diameter 127885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho 34 /60.0 * DEG_RAD, // Refraction correction 127985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho MINUTE_MS); // Desired accuracy 1280ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru} 1281ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 1282ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru//------------------------------------------------------------------------- 1283ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// Interpolation methods for finding the time at which a given event occurs 1284ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru//------------------------------------------------------------------------- 1285ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 1286ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruUDate CalendarAstronomer::timeOfAngle(AngleFunc& func, double desired, 1287ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru double periodDays, double epsilon, UBool next) 1288ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{ 128985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho // Find the value of the function at the current time 129085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho double lastAngle = func.eval(*this); 1291ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 129285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho // Find out how far we are from the desired angle 129385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho double deltaAngle = norm2PI(desired - lastAngle) ; 1294ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 129585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho // Using the average period, estimate the next (or previous) time at 129685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho // which the desired angle occurs. 129785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho double deltaT = (deltaAngle + (next ? 0.0 : - CalendarAstronomer_PI2 )) * (periodDays*DAY_MS) / CalendarAstronomer_PI2; 1298ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 129985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho double lastDeltaT = deltaT; // Liu 130085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho UDate startTime = fTime; // Liu 1301ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 130285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho setTime(fTime + uprv_ceil(deltaT)); 1303ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 130485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho // Now iterate until we get the error below epsilon. Throughout 130585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho // this loop we use normPI to get values in the range -Pi to Pi, 130685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho // since we're using them as correction factors rather than absolute angles. 130785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho do { 130885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho // Evaluate the function at the time we've estimated 130985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho double angle = func.eval(*this); 131085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho 131185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho // Find the # of milliseconds per radian at this point on the curve 131285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho double factor = uprv_fabs(deltaT / normPI(angle-lastAngle)); 131385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho 131485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho // Correct the time estimate based on how far off the angle is 131585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho deltaT = normPI(desired - angle) * factor; 131685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho 131785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho // HACK: 131885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho // 131985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho // If abs(deltaT) begins to diverge we need to quit this loop. 132085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho // This only appears to happen when attempting to locate, for 132185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho // example, a new moon on the day of the new moon. E.g.: 132285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho // 132385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho // This result is correct: 132485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho // newMoon(7508(Mon Jul 23 00:00:00 CST 1990,false))= 132585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho // Sun Jul 22 10:57:41 CST 1990 132685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho // 132785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho // But attempting to make the same call a day earlier causes deltaT 132885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho // to diverge: 132985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho // CalendarAstronomer.timeOfAngle() diverging: 1.348508727575625E9 -> 133085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho // 1.3649828540224032E9 133185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho // newMoon(7507(Sun Jul 22 00:00:00 CST 1990,false))= 133285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho // Sun Jul 08 13:56:15 CST 1990 133385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho // 133485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho // As a temporary solution, we catch this specific condition and 133585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho // adjust our start time by one eighth period days (either forward 133685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho // or backward) and try again. 133785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho // Liu 11/9/00 133885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho if (uprv_fabs(deltaT) > uprv_fabs(lastDeltaT)) { 133985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho double delta = uprv_ceil (periodDays * DAY_MS / 8.0); 134085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho setTime(startTime + (next ? delta : -delta)); 134185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho return timeOfAngle(func, desired, periodDays, epsilon, next); 134285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho } 134385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho 134485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho lastDeltaT = deltaT; 134585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho lastAngle = angle; 134685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho 134785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho setTime(fTime + uprv_ceil(deltaT)); 1348ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 134985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho while (uprv_fabs(deltaT) > epsilon); 1350ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 135185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho return fTime; 1352ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru} 1353ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 1354ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruUDate CalendarAstronomer::riseOrSet(CoordFunc& func, UBool rise, 1355ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru double diameter, double refraction, 1356ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru double epsilon) 1357ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{ 135885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho Equatorial pos; 135985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho double tanL = ::tan(fLatitude); 136085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho double deltaT = 0; 136185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho int32_t count = 0; 1362ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 136385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho // 136485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho // Calculate the object's position at the current time, then use that 136585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho // position to calculate the time of rising or setting. The position 136685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho // will be different at that time, so iterate until the error is allowable. 136785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho // 136885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho U_DEBUG_ASTRO_MSG(("setup rise=%s, dia=%.3lf, ref=%.3lf, eps=%.3lf\n", 136985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho rise?"T":"F", diameter, refraction, epsilon)); 137085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho do { 137185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho // See "Practical Astronomy With Your Calculator, section 33. 137285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho func.eval(pos, *this); 137385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho double angle = ::acos(-tanL * ::tan(pos.declination)); 137485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho double lst = ((rise ? CalendarAstronomer_PI2-angle : angle) + pos.ascension ) * 24 / CalendarAstronomer_PI2; 137585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho 137685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho // Convert from LST to Universal Time. 137785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho UDate newTime = lstToUT( lst ); 137885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho 137985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho deltaT = newTime - fTime; 138085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho setTime(newTime); 138185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho U_DEBUG_ASTRO_MSG(("%d] dT=%.3lf, angle=%.3lf, lst=%.3lf, A=%.3lf/D=%.3lf\n", 138285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho count, deltaT, angle, lst, pos.ascension, pos.declination)); 138385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho } 138485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho while (++ count < 5 && uprv_fabs(deltaT) > epsilon); 1385ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 138685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho // Calculate the correction due to refraction and the object's angular diameter 138785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho double cosD = ::cos(pos.declination); 138885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho double psi = ::acos(sin(fLatitude) / cosD); 138985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho double x = diameter / 2 + refraction; 139085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho double y = ::asin(sin(x) / ::sin(psi)); 139185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho long delta = (long)((240 * y * RAD_DEG / cosD)*SECOND_MS); 1392ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 139385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho return fTime + (rise ? -delta : delta); 1394ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru} 139585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho /** 1396ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * Return the obliquity of the ecliptic (the angle between the ecliptic 1397ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * and the earth's equator) at the current time. This varies due to 1398ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * the precession of the earth's axis. 1399ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * 1400ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * @return the obliquity of the ecliptic relative to the equator, 1401ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * measured in radians. 1402ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru */ 1403ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querudouble CalendarAstronomer::eclipticObliquity() { 140485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho if (isINVALID(eclipObliquity)) { 140585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho const double epoch = 2451545.0; // 2000 AD, January 1.5 1406ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 140785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho double T = (getJulianDay() - epoch) / 36525; 1408ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 140985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho eclipObliquity = 23.439292 141085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho - 46.815/3600 * T 141185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho - 0.0006/3600 * T*T 141285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho + 0.00181/3600 * T*T*T; 1413ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 141485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho eclipObliquity *= DEG_RAD; 141585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho } 141685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho return eclipObliquity; 1417ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru} 1418ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 1419ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 1420ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru//------------------------------------------------------------------------- 1421ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// Private data 1422ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru//------------------------------------------------------------------------- 1423ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruvoid CalendarAstronomer::clearCache() { 142485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho const double INVALID = uprv_getNaN(); 142585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho 142685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho julianDay = INVALID; 142785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho julianCentury = INVALID; 142885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho sunLongitude = INVALID; 142985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho meanAnomalySun = INVALID; 143085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho moonLongitude = INVALID; 143185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho moonEclipLong = INVALID; 143285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho meanAnomalyMoon = INVALID; 143385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho eclipObliquity = INVALID; 143485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho siderealTime = INVALID; 143585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho siderealT0 = INVALID; 143685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho moonPositionSet = FALSE; 1437ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru} 1438ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 1439ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru//private static void out(String s) { 1440ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// System.out.println(s); 1441ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru//} 1442ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 1443ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru//private static String deg(double rad) { 1444ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// return Double.toString(rad * RAD_DEG); 1445ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru//} 1446ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 1447ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru//private static String hours(long ms) { 1448ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// return Double.toString((double)ms / HOUR_MS) + " hours"; 1449ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru//} 1450ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 1451ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/** 1452ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * @internal 1453ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * @deprecated ICU 2.4. This class may be removed or modified. 1454ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru */ 1455ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/*UDate CalendarAstronomer::local(UDate localMillis) { 1456ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru // TODO - srl ? 1457ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru TimeZone *tz = TimeZone::createDefault(); 1458ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru int32_t rawOffset; 1459ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru int32_t dstOffset; 1460ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru UErrorCode status = U_ZERO_ERROR; 1461ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru tz->getOffset(localMillis, TRUE, rawOffset, dstOffset, status); 1462ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru delete tz; 1463ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru return localMillis - rawOffset; 1464ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}*/ 1465ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 1466ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// Debugging functions 1467ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruUnicodeString CalendarAstronomer::Ecliptic::toString() const 1468ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{ 1469ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#ifdef U_DEBUG_ASTRO 147085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho char tmp[800]; 147185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho sprintf(tmp, "[%.5f,%.5f]", longitude*RAD_DEG, latitude*RAD_DEG); 147285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho return UnicodeString(tmp, ""); 1473ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#else 147485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho return UnicodeString(); 1475ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#endif 1476ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru} 1477ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 1478ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruUnicodeString CalendarAstronomer::Equatorial::toString() const 1479ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{ 1480ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#ifdef U_DEBUG_ASTRO 148185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho char tmp[400]; 148285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho sprintf(tmp, "%f,%f", 148385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho (ascension*RAD_DEG), (declination*RAD_DEG)); 148485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho return UnicodeString(tmp, ""); 1485ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#else 148685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho return UnicodeString(); 1487ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#endif 1488ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru} 1489ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 1490ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruUnicodeString CalendarAstronomer::Horizon::toString() const 1491ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{ 1492ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#ifdef U_DEBUG_ASTRO 149385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho char tmp[800]; 149485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho sprintf(tmp, "[%.5f,%.5f]", altitude*RAD_DEG, azimuth*RAD_DEG); 149585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho return UnicodeString(tmp, ""); 1496ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#else 149785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho return UnicodeString(); 1498ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#endif 1499ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru} 1500ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 1501ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 1502ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// static private String radToHms(double angle) { 1503ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// int hrs = (int) (angle*RAD_HOUR); 1504ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// int min = (int)((angle*RAD_HOUR - hrs) * 60); 1505ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// int sec = (int)((angle*RAD_HOUR - hrs - min/60.0) * 3600); 1506ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 1507ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// return Integer.toString(hrs) + "h" + min + "m" + sec + "s"; 1508ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// } 1509ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 1510ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// static private String radToDms(double angle) { 1511ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// int deg = (int) (angle*RAD_DEG); 1512ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// int min = (int)((angle*RAD_DEG - deg) * 60); 1513ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// int sec = (int)((angle*RAD_DEG - deg - min/60.0) * 3600); 1514ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 1515ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// return Integer.toString(deg) + "\u00b0" + min + "'" + sec + "\""; 1516ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// } 1517ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 1518ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// =============== Calendar Cache ================ 1519ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 1520ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruvoid CalendarCache::createCache(CalendarCache** cache, UErrorCode& status) { 152185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho ucln_i18n_registerCleanup(UCLN_I18N_ASTRO_CALENDAR, calendar_astro_cleanup); 152285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho if(cache == NULL) { 152385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho status = U_MEMORY_ALLOCATION_ERROR; 152485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho } else { 152585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho *cache = new CalendarCache(32, status); 152685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho if(U_FAILURE(status)) { 152785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho delete *cache; 152885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho *cache = NULL; 152985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho } 1530ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 1531ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru} 1532ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 1533ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruint32_t CalendarCache::get(CalendarCache** cache, int32_t key, UErrorCode &status) { 153485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho int32_t res; 1535ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 1536ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if(U_FAILURE(status)) { 153785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho return 0; 153885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho } 153985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho umtx_lock(&ccLock); 154085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho 154185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho if(*cache == NULL) { 154285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho createCache(cache, status); 154385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho if(U_FAILURE(status)) { 154485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho umtx_unlock(&ccLock); 154585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho return 0; 154685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho } 1547ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 1548ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 154985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho res = uhash_igeti((*cache)->fTable, key); 155085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho U_DEBUG_ASTRO_MSG(("%p: GET: [%d] == %d\n", (*cache)->fTable, key, res)); 1551ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 155285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho umtx_unlock(&ccLock); 155385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho return res; 1554ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru} 1555ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 1556ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruvoid CalendarCache::put(CalendarCache** cache, int32_t key, int32_t value, UErrorCode &status) { 1557ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if(U_FAILURE(status)) { 155885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho return; 155985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho } 156085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho umtx_lock(&ccLock); 156185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho 156285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho if(*cache == NULL) { 156385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho createCache(cache, status); 156485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho if(U_FAILURE(status)) { 156585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho umtx_unlock(&ccLock); 156685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho return; 156785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho } 1568ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 1569ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 157085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho uhash_iputi((*cache)->fTable, key, value, &status); 157185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho U_DEBUG_ASTRO_MSG(("%p: PUT: [%d] := %d\n", (*cache)->fTable, key, value)); 1572ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 157385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho umtx_unlock(&ccLock); 1574ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru} 1575ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 1576ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruCalendarCache::CalendarCache(int32_t size, UErrorCode &status) { 157785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho fTable = uhash_openSize(uhash_hashLong, uhash_compareLong, NULL, size, &status); 157885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho U_DEBUG_ASTRO_MSG(("%p: Opening.\n", fTable)); 1579ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru} 1580ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 1581ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruCalendarCache::~CalendarCache() { 158285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho if(fTable != NULL) { 158385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho U_DEBUG_ASTRO_MSG(("%p: Closing.\n", fTable)); 158485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho uhash_close(fTable); 158585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho } 1586ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru} 1587ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 1588ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruU_NAMESPACE_END 1589ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 1590ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#endif // !UCONFIG_NO_FORMATTING 1591