1ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/************************************************************************ 254dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius * Copyright (C) 1996-2012, International Business Machines Corporation 3103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius * 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 6654dcd9b6a06071f647dac967e9e267abb9410720Craig Corneliusstatic UMutex ccLock = U_MUTEX_INITIALIZER; 67ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 68ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruU_CDECL_BEGIN 69ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querustatic UBool calendar_astro_cleanup(void) { 70ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru return TRUE; 71ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru} 72ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruU_CDECL_END 73ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 74ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruU_NAMESPACE_BEGIN 75ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 76ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/** 77ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * The number of standard hours in one sidereal day. 78ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * Approximately 24.93. 79ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * @internal 80ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * @deprecated ICU 2.4. This class may be removed or modified. 81ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru */ 82ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#define SIDEREAL_DAY (23.93446960027) 83ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 84ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/** 85ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * The number of sidereal hours in one mean solar day. 86ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * Approximately 24.07. 87ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * @internal 88ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * @deprecated ICU 2.4. This class may be removed or modified. 89ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru */ 90ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#define SOLAR_DAY (24.065709816) 91ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 92ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/** 93ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * The average number of solar days from one new moon to the next. This is the time 94ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * it takes for the moon to return the same ecliptic longitude as the sun. 95ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * It is longer than the sidereal month because the sun's longitude increases 96ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * during the year due to the revolution of the earth around the sun. 97ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * Approximately 29.53. 98ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * 99ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * @see #SIDEREAL_MONTH 100ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * @internal 101ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * @deprecated ICU 2.4. This class may be removed or modified. 102ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru */ 103ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruconst double CalendarAstronomer::SYNODIC_MONTH = 29.530588853; 104ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 105ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/** 106ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * The average number of days it takes 107ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * for the moon to return to the same ecliptic longitude relative to the 108ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * stellar background. This is referred to as the sidereal month. 109ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * It is shorter than the synodic month due to 110ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * the revolution of the earth around the sun. 111ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * Approximately 27.32. 112ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * 113ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * @see #SYNODIC_MONTH 114ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * @internal 115ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * @deprecated ICU 2.4. This class may be removed or modified. 116ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru */ 117ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#define SIDEREAL_MONTH 27.32166 118ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 119ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/** 120ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * The average number number of days between successive vernal equinoxes. 121ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * Due to the precession of the earth's 122ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * axis, this is not precisely the same as the sidereal year. 123ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * Approximately 365.24 124ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * 125ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * @see #SIDEREAL_YEAR 126ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * @internal 127ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * @deprecated ICU 2.4. This class may be removed or modified. 128ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru */ 129ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#define TROPICAL_YEAR 365.242191 130ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 131ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/** 132ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * The average number of days it takes 133ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * for the sun to return to the same position against the fixed stellar 134ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * background. This is the duration of one orbit of the earth about the sun 135ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * as it would appear to an outside observer. 136ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * Due to the precession of the earth's 137ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * axis, this is not precisely the same as the tropical year. 138ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * Approximately 365.25. 139ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * 140ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * @see #TROPICAL_YEAR 141ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * @internal 142ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * @deprecated ICU 2.4. This class may be removed or modified. 143ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru */ 144ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#define SIDEREAL_YEAR 365.25636 145ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 146ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru//------------------------------------------------------------------------- 147ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// Time-related constants 148ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru//------------------------------------------------------------------------- 149ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 150ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/** 151ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * The number of milliseconds in one second. 152ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * @internal 153ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * @deprecated ICU 2.4. This class may be removed or modified. 154ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru */ 155ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#define SECOND_MS U_MILLIS_PER_SECOND 156ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 157ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/** 158ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * The number of milliseconds in one minute. 159ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * @internal 160ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * @deprecated ICU 2.4. This class may be removed or modified. 161ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru */ 162ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#define MINUTE_MS U_MILLIS_PER_MINUTE 163ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 164ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/** 165ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * The number of milliseconds in one hour. 166ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * @internal 167ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * @deprecated ICU 2.4. This class may be removed or modified. 168ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru */ 169ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#define HOUR_MS U_MILLIS_PER_HOUR 170ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 171ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/** 172ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * The number of milliseconds in one day. 173ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * @internal 174ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * @deprecated ICU 2.4. This class may be removed or modified. 175ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru */ 176ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#define DAY_MS U_MILLIS_PER_DAY 177ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 178ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/** 179ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * The start of the julian day numbering scheme used by astronomers, which 180ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * is 1/1/4713 BC (Julian), 12:00 GMT. This is given as the number of milliseconds 181ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * since 1/1/1970 AD (Gregorian), a negative number. 182ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * Note that julian day numbers and 183ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * the Julian calendar are <em>not</em> the same thing. Also note that 184ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * julian days start at <em>noon</em>, not midnight. 185ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * @internal 186ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * @deprecated ICU 2.4. This class may be removed or modified. 187ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru */ 188ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#define JULIAN_EPOCH_MS -210866760000000.0 189ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 190ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 191ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/** 192ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * Milliseconds value for 0.0 January 2000 AD. 193ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru */ 194ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#define EPOCH_2000_MS 946598400000.0 195ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 196ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru//------------------------------------------------------------------------- 197ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// Assorted private data used for conversions 198ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru//------------------------------------------------------------------------- 199ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 200ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// My own copies of these so compilers are more likely to optimize them away 201ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruconst double CalendarAstronomer::PI = 3.14159265358979323846; 202ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 203ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#define CalendarAstronomer_PI2 (CalendarAstronomer::PI*2.0) 204ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#define RAD_HOUR ( 12 / CalendarAstronomer::PI ) // radians -> hours 205ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#define DEG_RAD ( CalendarAstronomer::PI / 180 ) // degrees -> radians 206ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#define RAD_DEG ( 180 / CalendarAstronomer::PI ) // radians -> degrees 207ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 20885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho/*** 20985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho * Given 'value', add or subtract 'range' until 0 <= 'value' < range. 21085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho * The modulus operator. 21185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho */ 21285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Hoinline static double normalize(double value, double range) { 21385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho return value - range * ClockMath::floorDivide(value, range); 21485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho} 21585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho 21685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho/** 21785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho * Normalize an angle so that it's in the range 0 - 2pi. 21885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho * For positive angles this is just (angle % 2pi), but the Java 21985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho * mod operator doesn't work that way for negative numbers.... 22085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho */ 22185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Hoinline static double norm2PI(double angle) { 22285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho return normalize(angle, CalendarAstronomer::PI * 2.0); 22385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho} 22485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho 22585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho/** 22685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho * Normalize an angle into the range -PI - PI 22785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho */ 22885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Hoinline static double normPI(double angle) { 22985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho return normalize(angle + CalendarAstronomer::PI, CalendarAstronomer::PI * 2.0) - CalendarAstronomer::PI; 23085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho} 23185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho 232ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru//------------------------------------------------------------------------- 233ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// Constructors 234ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru//------------------------------------------------------------------------- 235ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 236ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/** 237ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * Construct a new <code>CalendarAstronomer</code> object that is initialized to 238ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * the current date and time. 239ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * @internal 240ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * @deprecated ICU 2.4. This class may be removed or modified. 241ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru */ 242ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruCalendarAstronomer::CalendarAstronomer(): 243ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru fTime(Calendar::getNow()), fLongitude(0.0), fLatitude(0.0), fGmtOffset(0.0), moonPosition(0,0), moonPositionSet(FALSE) { 244ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru clearCache(); 245ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru} 246ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 247ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/** 248ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * Construct a new <code>CalendarAstronomer</code> object that is initialized to 249ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * the specified date and time. 250ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * @internal 251ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * @deprecated ICU 2.4. This class may be removed or modified. 252ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru */ 253ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruCalendarAstronomer::CalendarAstronomer(UDate d): fTime(d), fLongitude(0.0), fLatitude(0.0), fGmtOffset(0.0), moonPosition(0,0), moonPositionSet(FALSE) { 254ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru clearCache(); 255ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru} 256ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 257ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/** 258ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * Construct a new <code>CalendarAstronomer</code> object with the given 259ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * latitude and longitude. The object's time is set to the current 260ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * date and time. 261ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * <p> 262ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * @param longitude The desired longitude, in <em>degrees</em> east of 263ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * the Greenwich meridian. 264ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * 265ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * @param latitude The desired latitude, in <em>degrees</em>. Positive 266ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * values signify North, negative South. 267ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * 268ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * @see java.util.Date#getTime() 269ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * @internal 270ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * @deprecated ICU 2.4. This class may be removed or modified. 271ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru */ 272ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruCalendarAstronomer::CalendarAstronomer(double longitude, double latitude) : 273ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru fTime(Calendar::getNow()), moonPosition(0,0), moonPositionSet(FALSE) { 274ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru fLongitude = normPI(longitude * (double)DEG_RAD); 275ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru fLatitude = normPI(latitude * (double)DEG_RAD); 276ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru fGmtOffset = (double)(fLongitude * 24. * (double)HOUR_MS / (double)CalendarAstronomer_PI2); 277ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru clearCache(); 278ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru} 279ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 280ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruCalendarAstronomer::~CalendarAstronomer() 281ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{ 282ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru} 283ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 284ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru//------------------------------------------------------------------------- 285ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// Time and date getters and setters 286ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru//------------------------------------------------------------------------- 287ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 288ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/** 289ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * Set the current date and time of this <code>CalendarAstronomer</code> object. All 290ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * astronomical calculations are performed based on this time setting. 291ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * 292ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * @param aTime the date and time, expressed as the number of milliseconds since 293ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * 1/1/1970 0:00 GMT (Gregorian). 294ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * 295ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * @see #setDate 296ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * @see #getTime 297ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * @internal 298ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * @deprecated ICU 2.4. This class may be removed or modified. 299ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru */ 300ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruvoid CalendarAstronomer::setTime(UDate aTime) { 30185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho fTime = aTime; 30285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho U_DEBUG_ASTRO_MSG(("setTime(%.1lf, %sL)\n", aTime, debug_astro_date(aTime+fGmtOffset))); 30385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho clearCache(); 304ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru} 305ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 306ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/** 307ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * Set the current date and time of this <code>CalendarAstronomer</code> object. All 308ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * astronomical calculations are performed based on this time setting. 309ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * 310ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * @param jdn the desired time, expressed as a "julian day number", 311ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * which is the number of elapsed days since 312ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * 1/1/4713 BC (Julian), 12:00 GMT. Note that julian day 313ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * numbers start at <em>noon</em>. To get the jdn for 314ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * the corresponding midnight, subtract 0.5. 315ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * 316ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * @see #getJulianDay 317ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * @see #JULIAN_EPOCH_MS 318ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * @internal 319ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * @deprecated ICU 2.4. This class may be removed or modified. 320ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru */ 321ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruvoid CalendarAstronomer::setJulianDay(double jdn) { 32285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho fTime = (double)(jdn * DAY_MS) + JULIAN_EPOCH_MS; 32385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho clearCache(); 32485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho julianDay = jdn; 325ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru} 326ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 327ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/** 328ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * Get the current time of this <code>CalendarAstronomer</code> object, 329ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * represented as the number of milliseconds since 330ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * 1/1/1970 AD 0:00 GMT (Gregorian). 331ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * 332ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * @see #setTime 333ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * @see #getDate 334ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * @internal 335ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * @deprecated ICU 2.4. This class may be removed or modified. 336ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru */ 337ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruUDate CalendarAstronomer::getTime() { 33885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho return fTime; 339ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru} 340ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 341ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/** 342ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * Get the current time of this <code>CalendarAstronomer</code> object, 343ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * expressed as a "julian day number", which is the number of elapsed 344ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * days since 1/1/4713 BC (Julian), 12:00 GMT. 345ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * 346ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * @see #setJulianDay 347ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * @see #JULIAN_EPOCH_MS 348ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * @internal 349ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * @deprecated ICU 2.4. This class may be removed or modified. 350ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru */ 351ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querudouble CalendarAstronomer::getJulianDay() { 35285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho if (isINVALID(julianDay)) { 35385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho julianDay = (fTime - (double)JULIAN_EPOCH_MS) / (double)DAY_MS; 35485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho } 35585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho return julianDay; 356ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru} 357ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 358ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/** 359ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * Return this object's time expressed in julian centuries: 360ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * the number of centuries after 1/1/1900 AD, 12:00 GMT 361ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * 362ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * @see #getJulianDay 363ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * @internal 364ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * @deprecated ICU 2.4. This class may be removed or modified. 365ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru */ 366ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querudouble CalendarAstronomer::getJulianCentury() { 36785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho if (isINVALID(julianCentury)) { 36885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho julianCentury = (getJulianDay() - 2415020.0) / 36525.0; 36985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho } 37085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho return julianCentury; 371ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru} 372ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 373ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/** 374ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * Returns the current Greenwich sidereal time, measured in hours 375ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * @internal 376ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * @deprecated ICU 2.4. This class may be removed or modified. 377ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru */ 378ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querudouble CalendarAstronomer::getGreenwichSidereal() { 37985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho if (isINVALID(siderealTime)) { 38085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho // See page 86 of "Practial Astronomy with your Calculator", 38185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho // by Peter Duffet-Smith, for details on the algorithm. 382ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 38385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho double UT = normalize(fTime/(double)HOUR_MS, 24.); 384ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 38585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho siderealTime = normalize(getSiderealOffset() + UT*1.002737909, 24.); 38685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho } 38785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho return siderealTime; 388ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru} 389ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 390ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querudouble CalendarAstronomer::getSiderealOffset() { 39185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho if (isINVALID(siderealT0)) { 39285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho double JD = uprv_floor(getJulianDay() - 0.5) + 0.5; 39385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho double S = JD - 2451545.0; 39485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho double T = S / 36525.0; 39585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho siderealT0 = normalize(6.697374558 + 2400.051336*T + 0.000025862*T*T, 24); 39685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho } 39785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho return siderealT0; 398ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru} 399ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 400ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/** 401ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * Returns the current local sidereal time, measured in hours 402ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * @internal 403ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * @deprecated ICU 2.4. This class may be removed or modified. 404ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru */ 405ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querudouble CalendarAstronomer::getLocalSidereal() { 40685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho return normalize(getGreenwichSidereal() + (fGmtOffset/(double)HOUR_MS), 24.); 407ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru} 408ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 409ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/** 410ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * Converts local sidereal time to Universal Time. 411ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * 412ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * @param lst The Local Sidereal Time, in hours since sidereal midnight 413ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * on this object's current date. 414ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * 415ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * @return The corresponding Universal Time, in milliseconds since 416ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * 1 Jan 1970, GMT. 417ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru */ 418ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querudouble CalendarAstronomer::lstToUT(double lst) { 41985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho // Convert to local mean time 42085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho double lt = normalize((lst - getSiderealOffset()) * 0.9972695663, 24); 421ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 42285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho // Then find local midnight on this day 42385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho double base = (DAY_MS * ClockMath::floorDivide(fTime + fGmtOffset,(double)DAY_MS)) - fGmtOffset; 424ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 42585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho //out(" lt =" + lt + " hours"); 42685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho //out(" base=" + new Date(base)); 427ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 42885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho return base + (long)(lt * HOUR_MS); 429ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru} 430ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 431ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 432ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru//------------------------------------------------------------------------- 433ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// Coordinate transformations, all based on the current time of this object 434ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru//------------------------------------------------------------------------- 435ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 436ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/** 437ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * Convert from ecliptic to equatorial coordinates. 438ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * 439ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * @param ecliptic A point in the sky in ecliptic coordinates. 440ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * @return The corresponding point in equatorial coordinates. 441ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * @internal 442ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * @deprecated ICU 2.4. This class may be removed or modified. 443ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru */ 444ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruCalendarAstronomer::Equatorial& CalendarAstronomer::eclipticToEquatorial(CalendarAstronomer::Equatorial& result, const CalendarAstronomer::Ecliptic& ecliptic) 445ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{ 44685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho return eclipticToEquatorial(result, ecliptic.longitude, ecliptic.latitude); 447ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru} 448ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 449ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/** 450ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * Convert from ecliptic to equatorial coordinates. 451ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * 452ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * @param eclipLong The ecliptic longitude 453ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * @param eclipLat The ecliptic latitude 454ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * 455ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * @return The corresponding point in equatorial coordinates. 456ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * @internal 457ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * @deprecated ICU 2.4. This class may be removed or modified. 458ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru */ 459ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruCalendarAstronomer::Equatorial& CalendarAstronomer::eclipticToEquatorial(CalendarAstronomer::Equatorial& result, double eclipLong, double eclipLat) 460ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{ 46185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho // See page 42 of "Practial Astronomy with your Calculator", 46285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho // by Peter Duffet-Smith, for details on the algorithm. 463ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 46485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho double obliq = eclipticObliquity(); 46585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho double sinE = ::sin(obliq); 46685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho double cosE = cos(obliq); 467ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 46885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho double sinL = ::sin(eclipLong); 46985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho double cosL = cos(eclipLong); 470ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 47185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho double sinB = ::sin(eclipLat); 47285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho double cosB = cos(eclipLat); 47385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho double tanB = tan(eclipLat); 474ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 47585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho result.set(atan2(sinL*cosE - tanB*sinE, cosL), 47685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho asin(sinB*cosE + cosB*sinE*sinL) ); 47785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho return result; 478ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru} 479ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 480ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/** 481ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * Convert from ecliptic longitude to equatorial coordinates. 482ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * 483ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * @param eclipLong The ecliptic longitude 484ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * 485ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * @return The corresponding point in equatorial coordinates. 486ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * @internal 487ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * @deprecated ICU 2.4. This class may be removed or modified. 488ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru */ 489ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruCalendarAstronomer::Equatorial& CalendarAstronomer::eclipticToEquatorial(CalendarAstronomer::Equatorial& result, double eclipLong) 490ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{ 49185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho return eclipticToEquatorial(result, eclipLong, 0); // TODO: optimize 492ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru} 493ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 494ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/** 495ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * @internal 496ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * @deprecated ICU 2.4. This class may be removed or modified. 497ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru */ 498ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruCalendarAstronomer::Horizon& CalendarAstronomer::eclipticToHorizon(CalendarAstronomer::Horizon& result, double eclipLong) 499ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{ 50085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho Equatorial equatorial; 50185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho eclipticToEquatorial(equatorial, eclipLong); 502ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 50385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho double H = getLocalSidereal()*CalendarAstronomer::PI/12 - equatorial.ascension; // Hour-angle 504ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 50585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho double sinH = ::sin(H); 50685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho double cosH = cos(H); 50785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho double sinD = ::sin(equatorial.declination); 50885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho double cosD = cos(equatorial.declination); 50985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho double sinL = ::sin(fLatitude); 51085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho double cosL = cos(fLatitude); 511ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 51285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho double altitude = asin(sinD*sinL + cosD*cosL*cosH); 51385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho double azimuth = atan2(-cosD*cosL*sinH, sinD - sinL * ::sin(altitude)); 514ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 51585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho result.set(azimuth, altitude); 51685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho return result; 517ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru} 518ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 519ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 520ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru//------------------------------------------------------------------------- 521ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// The Sun 522ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru//------------------------------------------------------------------------- 523ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 524ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// 525ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// Parameters of the Sun's orbit as of the epoch Jan 0.0 1990 526ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// Angles are in radians (after multiplying by CalendarAstronomer::PI/180) 527ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// 528ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#define JD_EPOCH 2447891.5 // Julian day of epoch 529ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 530ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#define SUN_ETA_G (279.403303 * CalendarAstronomer::PI/180) // Ecliptic longitude at epoch 531ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#define SUN_OMEGA_G (282.768422 * CalendarAstronomer::PI/180) // Ecliptic longitude of perigee 532ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#define SUN_E 0.016713 // Eccentricity of orbit 533ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru//double sunR0 1.495585e8 // Semi-major axis in KM 534ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru//double sunTheta0 (0.533128 * CalendarAstronomer::PI/180) // Angular diameter at R0 535ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 536ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// The following three methods, which compute the sun parameters 537ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// given above for an arbitrary epoch (whatever time the object is 538ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// set to), make only a small difference as compared to using the 539ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// above constants. E.g., Sunset times might differ by ~12 540ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// seconds. Furthermore, the eta-g computation is befuddled by 541ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// Duffet-Smith's incorrect coefficients (p.86). I've corrected 542ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// the first-order coefficient but the others may be off too - no 543ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// way of knowing without consulting another source. 544ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 545ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// /** 546ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// * Return the sun's ecliptic longitude at perigee for the current time. 547ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// * See Duffett-Smith, p. 86. 548ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// * @return radians 549ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// */ 550ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// private double getSunOmegaG() { 551ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// double T = getJulianCentury(); 552ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// return (281.2208444 + (1.719175 + 0.000452778*T)*T) * DEG_RAD; 553ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// } 554ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 555ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// /** 556ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// * Return the sun's ecliptic longitude for the current time. 557ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// * See Duffett-Smith, p. 86. 558ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// * @return radians 559ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// */ 560ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// private double getSunEtaG() { 561ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// double T = getJulianCentury(); 562ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// //return (279.6966778 + (36000.76892 + 0.0003025*T)*T) * DEG_RAD; 563ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// // 564ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// // The above line is from Duffett-Smith, and yields manifestly wrong 565ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// // results. The below constant is derived empirically to match the 566ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// // constant he gives for the 1990 EPOCH. 567ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// // 568ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// return (279.6966778 + (-0.3262541582718024 + 0.0003025*T)*T) * DEG_RAD; 569ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// } 570ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 571ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// /** 572ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// * Return the sun's eccentricity of orbit for the current time. 573ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// * See Duffett-Smith, p. 86. 574ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// * @return double 575ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// */ 576ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// private double getSunE() { 577ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// double T = getJulianCentury(); 578ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// return 0.01675104 - (0.0000418 + 0.000000126*T)*T; 579ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// } 580ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 581ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/** 58285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho * Find the "true anomaly" (longitude) of an object from 58385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho * its mean anomaly and the eccentricity of its orbit. This uses 58485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho * an iterative solution to Kepler's equation. 58585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho * 58685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho * @param meanAnomaly The object's longitude calculated as if it were in 58785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho * a regular, circular orbit, measured in radians 58885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho * from the point of perigee. 58985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho * 59085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho * @param eccentricity The eccentricity of the orbit 59185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho * 59285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho * @return The true anomaly (longitude) measured in radians 59385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho */ 59485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Hostatic double trueAnomaly(double meanAnomaly, double eccentricity) 59585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho{ 59685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho // First, solve Kepler's equation iteratively 59785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho // Duffett-Smith, p.90 59885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho double delta; 59985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho double E = meanAnomaly; 60085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho do { 60185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho delta = E - eccentricity * ::sin(E) - meanAnomaly; 60285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho E = E - delta / (1 - eccentricity * ::cos(E)); 60385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho } 60485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho while (uprv_fabs(delta) > 1e-5); // epsilon = 1e-5 rad 60585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho 60685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho return 2.0 * ::atan( ::tan(E/2) * ::sqrt( (1+eccentricity) 60785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho /(1-eccentricity) ) ); 60885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho} 60985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho 61085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho/** 611ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * The longitude of the sun at the time specified by this object. 612ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * The longitude is measured in radians along the ecliptic 613ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * from the "first point of Aries," the point at which the ecliptic 614ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * crosses the earth's equatorial plane at the vernal equinox. 615ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * <p> 616ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * Currently, this method uses an approximation of the two-body Kepler's 617ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * equation for the earth and the sun. It does not take into account the 618ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * perturbations caused by the other planets, the moon, etc. 619ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * @internal 620ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * @deprecated ICU 2.4. This class may be removed or modified. 621ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru */ 622ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querudouble CalendarAstronomer::getSunLongitude() 623ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{ 62485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho // See page 86 of "Practial Astronomy with your Calculator", 62585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho // by Peter Duffet-Smith, for details on the algorithm. 626ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 62785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho if (isINVALID(sunLongitude)) { 62885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho getSunLongitude(getJulianDay(), sunLongitude, meanAnomalySun); 62985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho } 63085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho return sunLongitude; 631ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru} 632ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 633ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/** 634ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * TODO Make this public when the entire class is package-private. 635ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru */ 636ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/*public*/ void CalendarAstronomer::getSunLongitude(double jDay, double &longitude, double &meanAnomaly) 637ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{ 63885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho // See page 86 of "Practial Astronomy with your Calculator", 63985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho // by Peter Duffet-Smith, for details on the algorithm. 640ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 64185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho double day = jDay - JD_EPOCH; // Days since epoch 642ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 64385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho // Find the angular distance the sun in a fictitious 64485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho // circular orbit has travelled since the epoch. 64585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho double epochAngle = norm2PI(CalendarAstronomer_PI2/TROPICAL_YEAR*day); 646ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 64785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho // The epoch wasn't at the sun's perigee; find the angular distance 64885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho // since perigee, which is called the "mean anomaly" 64985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho meanAnomaly = norm2PI(epochAngle + SUN_ETA_G - SUN_OMEGA_G); 650ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 65185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho // Now find the "true anomaly", e.g. the real solar longitude 65285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho // by solving Kepler's equation for an elliptical orbit 65385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho // NOTE: The 3rd ed. of the book lists omega_g and eta_g in different 65485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho // equations; omega_g is to be correct. 65585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho longitude = norm2PI(trueAnomaly(meanAnomaly, SUN_E) + SUN_OMEGA_G); 656ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru} 657ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 658ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/** 659ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * The position of the sun at this object's current date and time, 660ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * in equatorial coordinates. 661ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * @internal 662ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * @deprecated ICU 2.4. This class may be removed or modified. 663ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru */ 664ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruCalendarAstronomer::Equatorial& CalendarAstronomer::getSunPosition(CalendarAstronomer::Equatorial& result) { 66585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho return eclipticToEquatorial(result, getSunLongitude(), 0); 666ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru} 667ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 668ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 669ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/** 670ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * Constant representing the vernal equinox. 671ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * For use with {@link #getSunTime getSunTime}. 672ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * Note: In this case, "vernal" refers to the northern hemisphere's seasons. 673ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * @internal 674ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * @deprecated ICU 2.4. This class may be removed or modified. 675ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru */ 676ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/*double CalendarAstronomer::VERNAL_EQUINOX() { 677ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru return 0; 678ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}*/ 679ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 680ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/** 681ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * Constant representing the summer solstice. 682ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * For use with {@link #getSunTime getSunTime}. 683ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * Note: In this case, "summer" refers to the northern hemisphere's seasons. 684ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * @internal 685ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * @deprecated ICU 2.4. This class may be removed or modified. 686ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru */ 687ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querudouble CalendarAstronomer::SUMMER_SOLSTICE() { 68885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho return (CalendarAstronomer::PI/2); 689ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru} 690ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 691ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/** 692ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * Constant representing the autumnal equinox. 693ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * For use with {@link #getSunTime getSunTime}. 694ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * Note: In this case, "autumn" refers to the northern hemisphere's seasons. 695ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * @internal 696ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * @deprecated ICU 2.4. This class may be removed or modified. 697ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru */ 698ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/*double CalendarAstronomer::AUTUMN_EQUINOX() { 699ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru return (CalendarAstronomer::PI); 700ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}*/ 701ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 702ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/** 703ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * Constant representing the winter solstice. 704ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * For use with {@link #getSunTime getSunTime}. 705ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * Note: In this case, "winter" refers to the northern hemisphere's seasons. 706ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * @internal 707ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * @deprecated ICU 2.4. This class may be removed or modified. 708ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru */ 70985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Hodouble CalendarAstronomer::WINTER_SOLSTICE() { 71085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho return ((CalendarAstronomer::PI*3)/2); 71185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho} 712ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 713ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruCalendarAstronomer::AngleFunc::~AngleFunc() {} 714ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 715ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/** 716ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * Find the next time at which the sun's ecliptic longitude will have 717ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * the desired value. 718ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * @internal 719ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * @deprecated ICU 2.4. This class may be removed or modified. 720ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru */ 721ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruclass SunTimeAngleFunc : public CalendarAstronomer::AngleFunc { 722ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querupublic: 723103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius virtual ~SunTimeAngleFunc(); 72485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho virtual double eval(CalendarAstronomer& a) { return a.getSunLongitude(); } 725ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}; 726ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 727103e9ffba2cba345d0078eb8b8db33249f81840aCraig CorneliusSunTimeAngleFunc::~SunTimeAngleFunc() {} 728103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius 729ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruUDate CalendarAstronomer::getSunTime(double desired, UBool next) 730ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{ 73185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho SunTimeAngleFunc func; 73285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho return timeOfAngle( func, 73385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho desired, 73485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho TROPICAL_YEAR, 73585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho MINUTE_MS, 73685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho next); 737ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru} 738ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 739ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruCalendarAstronomer::CoordFunc::~CoordFunc() {} 740ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 741ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruclass RiseSetCoordFunc : public CalendarAstronomer::CoordFunc { 742ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querupublic: 743103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius virtual ~RiseSetCoordFunc(); 74485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho virtual void eval(CalendarAstronomer::Equatorial& result, CalendarAstronomer&a) { a.getSunPosition(result); } 745ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}; 746ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 747103e9ffba2cba345d0078eb8b8db33249f81840aCraig CorneliusRiseSetCoordFunc::~RiseSetCoordFunc() {} 748103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius 749ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruUDate CalendarAstronomer::getSunRiseSet(UBool rise) 750ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{ 75185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho UDate t0 = fTime; 752ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 75385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho // Make a rough guess: 6am or 6pm local time on the current day 75485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho double noon = ClockMath::floorDivide(fTime + fGmtOffset, (double)DAY_MS)*DAY_MS - fGmtOffset + (12*HOUR_MS); 755ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 75685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho U_DEBUG_ASTRO_MSG(("Noon=%.2lf, %sL, gmtoff %.2lf\n", noon, debug_astro_date(noon+fGmtOffset), fGmtOffset)); 75785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho setTime(noon + ((rise ? -6 : 6) * HOUR_MS)); 75885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho U_DEBUG_ASTRO_MSG(("added %.2lf ms as a guess,\n", ((rise ? -6. : 6.) * HOUR_MS))); 759ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 76085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho RiseSetCoordFunc func; 76185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho double t = riseOrSet(func, 76285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho rise, 76385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho .533 * DEG_RAD, // Angular Diameter 76485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho 34. /60.0 * DEG_RAD, // Refraction correction 76585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho MINUTE_MS / 12.); // Desired accuracy 766ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 76785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho setTime(t0); 76885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho return t; 769ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru} 770ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 771ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// Commented out - currently unused. ICU 2.6, Alan 772ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// //------------------------------------------------------------------------- 773ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// // Alternate Sun Rise/Set 774ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// // See Duffett-Smith p.93 775ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// //------------------------------------------------------------------------- 776ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// 777ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// // This yields worse results (as compared to USNO data) than getSunRiseSet(). 778ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// /** 779ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// * TODO Make this when the entire class is package-private. 780ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// */ 781ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// /*public*/ long getSunRiseSet2(boolean rise) { 782ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// // 1. Calculate coordinates of the sun's center for midnight 783ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// double jd = uprv_floor(getJulianDay() - 0.5) + 0.5; 784ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// double[] sl = getSunLongitude(jd);// double lambda1 = sl[0]; 785ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// Equatorial pos1 = eclipticToEquatorial(lambda1, 0); 786ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// 787ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// // 2. Add ... to lambda to get position 24 hours later 788ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// double lambda2 = lambda1 + 0.985647*DEG_RAD; 789ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// Equatorial pos2 = eclipticToEquatorial(lambda2, 0); 790ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// 791ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// // 3. Calculate LSTs of rising and setting for these two positions 792ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// double tanL = ::tan(fLatitude); 793ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// double H = ::acos(-tanL * ::tan(pos1.declination)); 794ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// double lst1r = (CalendarAstronomer_PI2 + pos1.ascension - H) * 24 / CalendarAstronomer_PI2; 795ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// double lst1s = (pos1.ascension + H) * 24 / CalendarAstronomer_PI2; 796ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// H = ::acos(-tanL * ::tan(pos2.declination)); 797ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// double lst2r = (CalendarAstronomer_PI2-H + pos2.ascension ) * 24 / CalendarAstronomer_PI2; 798ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// double lst2s = (H + pos2.ascension ) * 24 / CalendarAstronomer_PI2; 799ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// if (lst1r > 24) lst1r -= 24; 800ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// if (lst1s > 24) lst1s -= 24; 801ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// if (lst2r > 24) lst2r -= 24; 802ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// if (lst2s > 24) lst2s -= 24; 803ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// 804ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// // 4. Convert LSTs to GSTs. If GST1 > GST2, add 24 to GST2. 805ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// double gst1r = lstToGst(lst1r); 806ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// double gst1s = lstToGst(lst1s); 807ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// double gst2r = lstToGst(lst2r); 808ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// double gst2s = lstToGst(lst2s); 809ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// if (gst1r > gst2r) gst2r += 24; 810ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// if (gst1s > gst2s) gst2s += 24; 811ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// 812ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// // 5. Calculate GST at 0h UT of this date 813ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// double t00 = utToGst(0); 814ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// 815ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// // 6. Calculate GST at 0h on the observer's longitude 816ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// double offset = ::round(fLongitude*12/PI); // p.95 step 6; he _rounds_ to nearest 15 deg. 817ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// double t00p = t00 - offset*1.002737909; 818ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// if (t00p < 0) t00p += 24; // do NOT normalize 819ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// 820ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// // 7. Adjust 821ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// if (gst1r < t00p) { 822ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// gst1r += 24; 823ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// gst2r += 24; 824ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// } 825ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// if (gst1s < t00p) { 826ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// gst1s += 24; 827ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// gst2s += 24; 828ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// } 829ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// 830ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// // 8. 831ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// double gstr = (24.07*gst1r-t00*(gst2r-gst1r))/(24.07+gst1r-gst2r); 832ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// double gsts = (24.07*gst1s-t00*(gst2s-gst1s))/(24.07+gst1s-gst2s); 833ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// 834ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// // 9. Correct for parallax, refraction, and sun's diameter 835ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// double dec = (pos1.declination + pos2.declination) / 2; 836ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// double psi = ::acos(sin(fLatitude) / cos(dec)); 837ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// double x = 0.830725 * DEG_RAD; // parallax+refraction+diameter 838ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// double y = ::asin(sin(x) / ::sin(psi)) * RAD_DEG; 839ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// double delta_t = 240 * y / cos(dec) / 3600; // hours 840ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// 841ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// // 10. Add correction to GSTs, subtract from GSTr 842ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// gstr -= delta_t; 843ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// gsts += delta_t; 844ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// 845ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// // 11. Convert GST to UT and then to local civil time 846ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// double ut = gstToUt(rise ? gstr : gsts); 847ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// //System.out.println((rise?"rise=":"set=") + ut + ", delta_t=" + delta_t); 848ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// long midnight = DAY_MS * (time / DAY_MS); // Find UT midnight on this day 849ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// return midnight + (long) (ut * 3600000); 850ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// } 851ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 852ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// Commented out - currently unused. ICU 2.6, Alan 853ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// /** 854ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// * Convert local sidereal time to Greenwich sidereal time. 855ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// * Section 15. Duffett-Smith p.21 856ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// * @param lst in hours (0..24) 857ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// * @return GST in hours (0..24) 858ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// */ 859ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// double lstToGst(double lst) { 860ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// double delta = fLongitude * 24 / CalendarAstronomer_PI2; 861ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// return normalize(lst - delta, 24); 862ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// } 863ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 864ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// Commented out - currently unused. ICU 2.6, Alan 865ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// /** 866ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// * Convert UT to GST on this date. 867ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// * Section 12. Duffett-Smith p.17 868ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// * @param ut in hours 869ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// * @return GST in hours 870ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// */ 871ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// double utToGst(double ut) { 872ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// return normalize(getT0() + ut*1.002737909, 24); 873ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// } 874ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 875ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// Commented out - currently unused. ICU 2.6, Alan 876ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// /** 877ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// * Convert GST to UT on this date. 878ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// * Section 13. Duffett-Smith p.18 879ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// * @param gst in hours 880ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// * @return UT in hours 881ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// */ 882ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// double gstToUt(double gst) { 883ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// return normalize(gst - getT0(), 24) * 0.9972695663; 884ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// } 885ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 886ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// Commented out - currently unused. ICU 2.6, Alan 887ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// double getT0() { 888ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// // Common computation for UT <=> GST 889ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// 890ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// // Find JD for 0h UT 891ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// double jd = uprv_floor(getJulianDay() - 0.5) + 0.5; 892ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// 893ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// double s = jd - 2451545.0; 894ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// double t = s / 36525.0; 895ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// double t0 = 6.697374558 + (2400.051336 + 0.000025862*t)*t; 896ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// return t0; 897ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// } 898ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 899ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// Commented out - currently unused. ICU 2.6, Alan 900ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// //------------------------------------------------------------------------- 901ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// // Alternate Sun Rise/Set 902ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// // See sci.astro FAQ 903ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// // http://www.faqs.org/faqs/astronomy/faq/part3/section-5.html 904ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// //------------------------------------------------------------------------- 905ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// 906ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// // Note: This method appears to produce inferior accuracy as 907ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// // compared to getSunRiseSet(). 908ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// 909ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// /** 910ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// * TODO Make this when the entire class is package-private. 911ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// */ 912ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// /*public*/ long getSunRiseSet3(boolean rise) { 913ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// 914ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// // Compute day number for 0.0 Jan 2000 epoch 915ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// double d = (double)(time - EPOCH_2000_MS) / DAY_MS; 916ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// 917ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// // Now compute the Local Sidereal Time, LST: 918ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// // 919ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// double LST = 98.9818 + 0.985647352 * d + /*UT*15 + long*/ 920ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// fLongitude*RAD_DEG; 921ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// // 922ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// // (east long. positive). Note that LST is here expressed in degrees, 923ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// // where 15 degrees corresponds to one hour. Since LST really is an angle, 924ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// // it's convenient to use one unit---degrees---throughout. 925ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// 926ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// // COMPUTING THE SUN'S POSITION 927ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// // ---------------------------- 928ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// // 929ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// // To be able to compute the Sun's rise/set times, you need to be able to 930ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// // compute the Sun's position at any time. First compute the "day 931ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// // number" d as outlined above, for the desired moment. Next compute: 932ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// // 933ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// double oblecl = 23.4393 - 3.563E-7 * d; 934ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// // 935ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// double w = 282.9404 + 4.70935E-5 * d; 936ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// double M = 356.0470 + 0.9856002585 * d; 937ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// double e = 0.016709 - 1.151E-9 * d; 938ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// // 939ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// // This is the obliquity of the ecliptic, plus some of the elements of 940ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// // the Sun's apparent orbit (i.e., really the Earth's orbit): w = 941ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// // argument of perihelion, M = mean anomaly, e = eccentricity. 942ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// // Semi-major axis is here assumed to be exactly 1.0 (while not strictly 943ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// // true, this is still an accurate approximation). Next compute E, the 944ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// // eccentric anomaly: 945ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// // 946ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// double E = M + e*(180/PI) * ::sin(M*DEG_RAD) * ( 1.0 + e*cos(M*DEG_RAD) ); 947ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// // 948ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// // where E and M are in degrees. This is it---no further iterations are 949ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// // needed because we know e has a sufficiently small value. Next compute 950ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// // the true anomaly, v, and the distance, r: 951ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// // 952ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// /* r * cos(v) = */ double A = cos(E*DEG_RAD) - e; 953ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// /* r * ::sin(v) = */ double B = ::sqrt(1 - e*e) * ::sin(E*DEG_RAD); 954ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// // 955ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// // and 956ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// // 957ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// // r = sqrt( A*A + B*B ) 958ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// double v = ::atan2( B, A )*RAD_DEG; 959ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// // 960ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// // The Sun's true longitude, slon, can now be computed: 961ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// // 962ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// double slon = v + w; 963ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// // 964ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// // Since the Sun is always at the ecliptic (or at least very very close to 965ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// // it), we can use simplified formulae to convert slon (the Sun's ecliptic 966ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// // longitude) to sRA and sDec (the Sun's RA and Dec): 967ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// // 968ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// // ::sin(slon) * cos(oblecl) 969ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// // tan(sRA) = ------------------------- 970ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// // cos(slon) 971ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// // 972ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// // ::sin(sDec) = ::sin(oblecl) * ::sin(slon) 973ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// // 974ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// // As was the case when computing az, the Azimuth, if possible use an 975ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// // atan2() function to compute sRA. 976ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// 977ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// double sRA = ::atan2(sin(slon*DEG_RAD) * cos(oblecl*DEG_RAD), cos(slon*DEG_RAD))*RAD_DEG; 978ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// 979ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// double sin_sDec = ::sin(oblecl*DEG_RAD) * ::sin(slon*DEG_RAD); 980ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// double sDec = ::asin(sin_sDec)*RAD_DEG; 981ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// 982ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// // COMPUTING RISE AND SET TIMES 983ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// // ---------------------------- 984ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// // 985ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// // To compute when an object rises or sets, you must compute when it 986ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// // passes the meridian and the HA of rise/set. Then the rise time is 987ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// // the meridian time minus HA for rise/set, and the set time is the 988ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// // meridian time plus the HA for rise/set. 989ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// // 990ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// // To find the meridian time, compute the Local Sidereal Time at 0h local 991ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// // time (or 0h UT if you prefer to work in UT) as outlined above---name 992ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// // that quantity LST0. The Meridian Time, MT, will now be: 993ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// // 994ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// // MT = RA - LST0 995ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// double MT = normalize(sRA - LST, 360); 996ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// // 997ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// // where "RA" is the object's Right Ascension (in degrees!). If negative, 998ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// // add 360 deg to MT. If the object is the Sun, leave the time as it is, 999ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// // but if it's stellar, multiply MT by 365.2422/366.2422, to convert from 1000ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// // sidereal to solar time. Now, compute HA for rise/set, name that 1001ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// // quantity HA0: 1002ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// // 1003ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// // ::sin(h0) - ::sin(lat) * ::sin(Dec) 1004ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// // cos(HA0) = --------------------------------- 1005ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// // cos(lat) * cos(Dec) 1006ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// // 1007ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// // where h0 is the altitude selected to represent rise/set. For a purely 1008ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// // mathematical horizon, set h0 = 0 and simplify to: 1009ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// // 1010ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// // cos(HA0) = - tan(lat) * tan(Dec) 1011ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// // 1012ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// // If you want to account for refraction on the atmosphere, set h0 = -35/60 1013ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// // degrees (-35 arc minutes), and if you want to compute the rise/set times 1014ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// // for the Sun's upper limb, set h0 = -50/60 (-50 arc minutes). 1015ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// // 1016ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// double h0 = -50/60 * DEG_RAD; 1017ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// 1018ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// double HA0 = ::acos( 1019ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// (sin(h0) - ::sin(fLatitude) * sin_sDec) / 1020ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// (cos(fLatitude) * cos(sDec*DEG_RAD)))*RAD_DEG; 1021ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// 1022ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// // When HA0 has been computed, leave it as it is for the Sun but multiply 1023ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// // by 365.2422/366.2422 for stellar objects, to convert from sidereal to 1024ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// // solar time. Finally compute: 1025ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// // 1026ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// // Rise time = MT - HA0 1027ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// // Set time = MT + HA0 1028ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// // 1029ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// // convert the times from degrees to hours by dividing by 15. 1030ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// // 1031ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// // If you'd like to check that your calculations are accurate or just 1032ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// // need a quick result, check the USNO's Sun or Moon Rise/Set Table, 1033ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// // <URL:http://aa.usno.navy.mil/AA/data/docs/RS_OneYear.html>. 1034ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// 1035ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// double result = MT + (rise ? -HA0 : HA0); // in degrees 1036ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// 1037ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// // Find UT midnight on this day 1038ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// long midnight = DAY_MS * (time / DAY_MS); 1039ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// 1040ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// return midnight + (long) (result * 3600000 / 15); 1041ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// } 1042ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 1043ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru//------------------------------------------------------------------------- 1044ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// The Moon 1045ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru//------------------------------------------------------------------------- 1046ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 1047ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#define moonL0 (318.351648 * CalendarAstronomer::PI/180 ) // Mean long. at epoch 1048ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#define moonP0 ( 36.340410 * CalendarAstronomer::PI/180 ) // Mean long. of perigee 1049ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#define moonN0 ( 318.510107 * CalendarAstronomer::PI/180 ) // Mean long. of node 1050ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#define moonI ( 5.145366 * CalendarAstronomer::PI/180 ) // Inclination of orbit 1051ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#define moonE ( 0.054900 ) // Eccentricity of orbit 1052ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 1053ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// These aren't used right now 1054ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#define moonA ( 3.84401e5 ) // semi-major axis (km) 1055ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#define moonT0 ( 0.5181 * CalendarAstronomer::PI/180 ) // Angular size at distance A 1056ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#define moonPi ( 0.9507 * CalendarAstronomer::PI/180 ) // Parallax at distance A 1057ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 1058ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/** 1059ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * The position of the moon at the time set on this 1060ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * object, in equatorial coordinates. 1061ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * @internal 1062ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * @deprecated ICU 2.4. This class may be removed or modified. 1063ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru */ 1064ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruconst CalendarAstronomer::Equatorial& CalendarAstronomer::getMoonPosition() 1065ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{ 1066ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru // 106785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho // See page 142 of "Practial Astronomy with your Calculator", 106885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho // by Peter Duffet-Smith, for details on the algorithm. 1069ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru // 107085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho if (moonPositionSet == FALSE) { 107185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho // Calculate the solar longitude. Has the side effect of 107285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho // filling in "meanAnomalySun" as well. 107385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho getSunLongitude(); 107485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho 107585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho // 107685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho // Find the # of days since the epoch of our orbital parameters. 107785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho // TODO: Convert the time of day portion into ephemeris time 107885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho // 107985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho double day = getJulianDay() - JD_EPOCH; // Days since epoch 108085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho 108185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho // Calculate the mean longitude and anomaly of the moon, based on 108285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho // a circular orbit. Similar to the corresponding solar calculation. 108385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho double meanLongitude = norm2PI(13.1763966*PI/180*day + moonL0); 108485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho meanAnomalyMoon = norm2PI(meanLongitude - 0.1114041*PI/180 * day - moonP0); 108585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho 108685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho // 108785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho // Calculate the following corrections: 108885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho // Evection: the sun's gravity affects the moon's eccentricity 108985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho // Annual Eqn: variation in the effect due to earth-sun distance 109085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho // A3: correction factor (for ???) 109185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho // 109285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho double evection = 1.2739*PI/180 * ::sin(2 * (meanLongitude - sunLongitude) 109385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho - meanAnomalyMoon); 109485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho double annual = 0.1858*PI/180 * ::sin(meanAnomalySun); 109585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho double a3 = 0.3700*PI/180 * ::sin(meanAnomalySun); 109685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho 109785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho meanAnomalyMoon += evection - annual - a3; 109885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho 109985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho // 110085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho // More correction factors: 110185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho // center equation of the center correction 110285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho // a4 yet another error correction (???) 110385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho // 110485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho // TODO: Skip the equation of the center correction and solve Kepler's eqn? 110585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho // 110685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho double center = 6.2886*PI/180 * ::sin(meanAnomalyMoon); 110785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho double a4 = 0.2140*PI/180 * ::sin(2 * meanAnomalyMoon); 110885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho 110985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho // Now find the moon's corrected longitude 111085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho moonLongitude = meanLongitude + evection + center - annual + a4; 111185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho 111285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho // 111385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho // And finally, find the variation, caused by the fact that the sun's 111485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho // gravitational pull on the moon varies depending on which side of 111585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho // the earth the moon is on 111685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho // 111785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho double variation = 0.6583*CalendarAstronomer::PI/180 * ::sin(2*(moonLongitude - sunLongitude)); 111885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho 111985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho moonLongitude += variation; 112085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho 112185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho // 112285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho // What we've calculated so far is the moon's longitude in the plane 112385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho // of its own orbit. Now map to the ecliptic to get the latitude 112485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho // and longitude. First we need to find the longitude of the ascending 112585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho // node, the position on the ecliptic where it is crossed by the moon's 112685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho // orbit as it crosses from the southern to the northern hemisphere. 112785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho // 112885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho double nodeLongitude = norm2PI(moonN0 - 0.0529539*PI/180 * day); 112985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho 113085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho nodeLongitude -= 0.16*PI/180 * ::sin(meanAnomalySun); 113185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho 113285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho double y = ::sin(moonLongitude - nodeLongitude); 113385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho double x = cos(moonLongitude - nodeLongitude); 113485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho 113585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho moonEclipLong = ::atan2(y*cos(moonI), x) + nodeLongitude; 113685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho double moonEclipLat = ::asin(y * ::sin(moonI)); 113785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho 113885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho eclipticToEquatorial(moonPosition, moonEclipLong, moonEclipLat); 113985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho moonPositionSet = TRUE; 114085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho } 114185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho return moonPosition; 1142ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru} 1143ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 1144ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/** 1145ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * The "age" of the moon at the time specified in this object. 1146ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * This is really the angle between the 1147ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * current ecliptic longitudes of the sun and the moon, 1148ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * measured in radians. 1149ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * 1150ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * @see #getMoonPhase 1151ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * @internal 1152ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * @deprecated ICU 2.4. This class may be removed or modified. 1153ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru */ 1154ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querudouble CalendarAstronomer::getMoonAge() { 115585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho // See page 147 of "Practial Astronomy with your Calculator", 115685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho // by Peter Duffet-Smith, for details on the algorithm. 115785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho // 115885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho // Force the moon's position to be calculated. We're going to use 115985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho // some the intermediate results cached during that calculation. 116085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho // 116185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho getMoonPosition(); 116285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho 116385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho return norm2PI(moonEclipLong - sunLongitude); 1164ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru} 1165ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 1166ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/** 1167ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * Calculate the phase of the moon at the time set in this object. 1168ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * The returned phase is a <code>double</code> in the range 1169ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * <code>0 <= phase < 1</code>, interpreted as follows: 1170ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * <ul> 1171ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * <li>0.00: New moon 1172ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * <li>0.25: First quarter 1173ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * <li>0.50: Full moon 1174ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * <li>0.75: Last quarter 1175ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * </ul> 1176ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * 1177ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * @see #getMoonAge 1178ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * @internal 1179ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * @deprecated ICU 2.4. This class may be removed or modified. 1180ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru */ 1181ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querudouble CalendarAstronomer::getMoonPhase() { 118285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho // See page 147 of "Practial Astronomy with your Calculator", 118385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho // by Peter Duffet-Smith, for details on the algorithm. 118485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho return 0.5 * (1 - cos(getMoonAge())); 1185ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru} 1186ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 1187ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/** 1188ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * Constant representing a new moon. 1189ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * For use with {@link #getMoonTime getMoonTime} 1190ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * @internal 1191ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * @deprecated ICU 2.4. This class may be removed or modified. 1192ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru */ 119385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Hoconst CalendarAstronomer::MoonAge CalendarAstronomer::NEW_MOON() { 119485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho return CalendarAstronomer::MoonAge(0); 119585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho} 1196ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 1197ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/** 1198ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * Constant representing the moon's first quarter. 1199ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * For use with {@link #getMoonTime getMoonTime} 1200ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * @internal 1201ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * @deprecated ICU 2.4. This class may be removed or modified. 1202ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru */ 1203ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/*const CalendarAstronomer::MoonAge CalendarAstronomer::FIRST_QUARTER() { 1204ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru return CalendarAstronomer::MoonAge(CalendarAstronomer::PI/2); 1205ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}*/ 1206ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 1207ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/** 1208ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * Constant representing a full moon. 1209ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * For use with {@link #getMoonTime getMoonTime} 1210ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * @internal 1211ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * @deprecated ICU 2.4. This class may be removed or modified. 1212ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru */ 1213ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruconst CalendarAstronomer::MoonAge CalendarAstronomer::FULL_MOON() { 121485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho return CalendarAstronomer::MoonAge(CalendarAstronomer::PI); 1215ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru} 1216ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/** 1217ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * Constant representing the moon's last quarter. 1218ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * For use with {@link #getMoonTime getMoonTime} 1219ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * @internal 1220ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * @deprecated ICU 2.4. This class may be removed or modified. 1221ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru */ 1222ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 1223ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruclass MoonTimeAngleFunc : public CalendarAstronomer::AngleFunc { 1224ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querupublic: 1225103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius virtual ~MoonTimeAngleFunc(); 122685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho virtual double eval(CalendarAstronomer&a) { return a.getMoonAge(); } 1227ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}; 1228ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 1229103e9ffba2cba345d0078eb8b8db33249f81840aCraig CorneliusMoonTimeAngleFunc::~MoonTimeAngleFunc() {} 1230103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius 1231ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/*const CalendarAstronomer::MoonAge CalendarAstronomer::LAST_QUARTER() { 1232ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru return CalendarAstronomer::MoonAge((CalendarAstronomer::PI*3)/2); 1233ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}*/ 1234ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 1235ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/** 1236ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * Find the next or previous time at which the Moon's ecliptic 1237ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * longitude will have the desired value. 1238ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * <p> 1239ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * @param desired The desired longitude. 1240ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * @param next <tt>true</tt> if the next occurrance of the phase 1241ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * is desired, <tt>false</tt> for the previous occurrance. 1242ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * @internal 1243ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * @deprecated ICU 2.4. This class may be removed or modified. 1244ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru */ 1245ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruUDate CalendarAstronomer::getMoonTime(double desired, UBool next) 1246ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{ 124785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho MoonTimeAngleFunc func; 124885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho return timeOfAngle( func, 124985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho desired, 125085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho SYNODIC_MONTH, 125185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho MINUTE_MS, 125285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho next); 1253ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru} 1254ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 1255ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/** 1256ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * Find the next or previous time at which the moon will be in the 1257ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * desired phase. 1258ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * <p> 1259ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * @param desired The desired phase of the moon. 1260ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * @param next <tt>true</tt> if the next occurrance of the phase 1261ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * is desired, <tt>false</tt> for the previous occurrance. 1262ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * @internal 1263ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * @deprecated ICU 2.4. This class may be removed or modified. 1264ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru */ 1265ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruUDate CalendarAstronomer::getMoonTime(const CalendarAstronomer::MoonAge& desired, UBool next) { 126685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho return getMoonTime(desired.value, next); 1267ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru} 1268ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 1269ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruclass MoonRiseSetCoordFunc : public CalendarAstronomer::CoordFunc { 1270ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querupublic: 1271103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius virtual ~MoonRiseSetCoordFunc(); 127285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho virtual void eval(CalendarAstronomer::Equatorial& result, CalendarAstronomer&a) { result = a.getMoonPosition(); } 1273ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}; 1274ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 1275103e9ffba2cba345d0078eb8b8db33249f81840aCraig CorneliusMoonRiseSetCoordFunc::~MoonRiseSetCoordFunc() {} 1276103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius 1277ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/** 1278ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * Returns the time (GMT) of sunrise or sunset on the local date to which 1279ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * this calendar is currently set. 1280ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * @internal 1281ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * @deprecated ICU 2.4. This class may be removed or modified. 1282ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru */ 1283ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruUDate CalendarAstronomer::getMoonRiseSet(UBool rise) 1284ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{ 128585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho MoonRiseSetCoordFunc func; 128685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho return riseOrSet(func, 128785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho rise, 128885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho .533 * DEG_RAD, // Angular Diameter 128985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho 34 /60.0 * DEG_RAD, // Refraction correction 129085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho MINUTE_MS); // Desired accuracy 1291ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru} 1292ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 1293ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru//------------------------------------------------------------------------- 1294ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// Interpolation methods for finding the time at which a given event occurs 1295ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru//------------------------------------------------------------------------- 1296ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 1297ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruUDate CalendarAstronomer::timeOfAngle(AngleFunc& func, double desired, 1298ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru double periodDays, double epsilon, UBool next) 1299ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{ 130085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho // Find the value of the function at the current time 130185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho double lastAngle = func.eval(*this); 1302ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 130385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho // Find out how far we are from the desired angle 130485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho double deltaAngle = norm2PI(desired - lastAngle) ; 1305ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 130685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho // Using the average period, estimate the next (or previous) time at 130785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho // which the desired angle occurs. 130885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho double deltaT = (deltaAngle + (next ? 0.0 : - CalendarAstronomer_PI2 )) * (periodDays*DAY_MS) / CalendarAstronomer_PI2; 1309ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 131085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho double lastDeltaT = deltaT; // Liu 131185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho UDate startTime = fTime; // Liu 1312ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 131385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho setTime(fTime + uprv_ceil(deltaT)); 1314ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 131585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho // Now iterate until we get the error below epsilon. Throughout 131685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho // this loop we use normPI to get values in the range -Pi to Pi, 131785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho // since we're using them as correction factors rather than absolute angles. 131885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho do { 131985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho // Evaluate the function at the time we've estimated 132085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho double angle = func.eval(*this); 132185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho 132285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho // Find the # of milliseconds per radian at this point on the curve 132385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho double factor = uprv_fabs(deltaT / normPI(angle-lastAngle)); 132485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho 132585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho // Correct the time estimate based on how far off the angle is 132685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho deltaT = normPI(desired - angle) * factor; 132785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho 132885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho // HACK: 132985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho // 133085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho // If abs(deltaT) begins to diverge we need to quit this loop. 133185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho // This only appears to happen when attempting to locate, for 133285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho // example, a new moon on the day of the new moon. E.g.: 133385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho // 133485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho // This result is correct: 133585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho // newMoon(7508(Mon Jul 23 00:00:00 CST 1990,false))= 133685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho // Sun Jul 22 10:57:41 CST 1990 133785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho // 133885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho // But attempting to make the same call a day earlier causes deltaT 133985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho // to diverge: 134085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho // CalendarAstronomer.timeOfAngle() diverging: 1.348508727575625E9 -> 134185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho // 1.3649828540224032E9 134285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho // newMoon(7507(Sun Jul 22 00:00:00 CST 1990,false))= 134385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho // Sun Jul 08 13:56:15 CST 1990 134485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho // 134585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho // As a temporary solution, we catch this specific condition and 134685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho // adjust our start time by one eighth period days (either forward 134785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho // or backward) and try again. 134885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho // Liu 11/9/00 134985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho if (uprv_fabs(deltaT) > uprv_fabs(lastDeltaT)) { 135085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho double delta = uprv_ceil (periodDays * DAY_MS / 8.0); 135185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho setTime(startTime + (next ? delta : -delta)); 135285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho return timeOfAngle(func, desired, periodDays, epsilon, next); 135385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho } 135485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho 135585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho lastDeltaT = deltaT; 135685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho lastAngle = angle; 135785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho 135885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho setTime(fTime + uprv_ceil(deltaT)); 1359ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 136085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho while (uprv_fabs(deltaT) > epsilon); 1361ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 136285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho return fTime; 1363ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru} 1364ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 1365ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruUDate CalendarAstronomer::riseOrSet(CoordFunc& func, UBool rise, 1366ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru double diameter, double refraction, 1367ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru double epsilon) 1368ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{ 136985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho Equatorial pos; 137085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho double tanL = ::tan(fLatitude); 137185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho double deltaT = 0; 137285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho int32_t count = 0; 1373ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 137485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho // 137585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho // Calculate the object's position at the current time, then use that 137685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho // position to calculate the time of rising or setting. The position 137785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho // will be different at that time, so iterate until the error is allowable. 137885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho // 137985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho U_DEBUG_ASTRO_MSG(("setup rise=%s, dia=%.3lf, ref=%.3lf, eps=%.3lf\n", 138085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho rise?"T":"F", diameter, refraction, epsilon)); 138185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho do { 138285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho // See "Practical Astronomy With Your Calculator, section 33. 138385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho func.eval(pos, *this); 138485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho double angle = ::acos(-tanL * ::tan(pos.declination)); 138585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho double lst = ((rise ? CalendarAstronomer_PI2-angle : angle) + pos.ascension ) * 24 / CalendarAstronomer_PI2; 138685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho 138785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho // Convert from LST to Universal Time. 138885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho UDate newTime = lstToUT( lst ); 138985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho 139085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho deltaT = newTime - fTime; 139185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho setTime(newTime); 139285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho U_DEBUG_ASTRO_MSG(("%d] dT=%.3lf, angle=%.3lf, lst=%.3lf, A=%.3lf/D=%.3lf\n", 139385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho count, deltaT, angle, lst, pos.ascension, pos.declination)); 139485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho } 139585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho while (++ count < 5 && uprv_fabs(deltaT) > epsilon); 1396ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 139785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho // Calculate the correction due to refraction and the object's angular diameter 139885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho double cosD = ::cos(pos.declination); 139985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho double psi = ::acos(sin(fLatitude) / cosD); 140085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho double x = diameter / 2 + refraction; 140185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho double y = ::asin(sin(x) / ::sin(psi)); 140285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho long delta = (long)((240 * y * RAD_DEG / cosD)*SECOND_MS); 1403ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 140485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho return fTime + (rise ? -delta : delta); 1405ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru} 140685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho /** 1407ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * Return the obliquity of the ecliptic (the angle between the ecliptic 1408ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * and the earth's equator) at the current time. This varies due to 1409ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * the precession of the earth's axis. 1410ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * 1411ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * @return the obliquity of the ecliptic relative to the equator, 1412ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * measured in radians. 1413ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru */ 1414ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querudouble CalendarAstronomer::eclipticObliquity() { 141585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho if (isINVALID(eclipObliquity)) { 141685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho const double epoch = 2451545.0; // 2000 AD, January 1.5 1417ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 141885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho double T = (getJulianDay() - epoch) / 36525; 1419ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 142085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho eclipObliquity = 23.439292 142185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho - 46.815/3600 * T 142285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho - 0.0006/3600 * T*T 142385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho + 0.00181/3600 * T*T*T; 1424ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 142585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho eclipObliquity *= DEG_RAD; 142685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho } 142785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho return eclipObliquity; 1428ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru} 1429ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 1430ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 1431ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru//------------------------------------------------------------------------- 1432ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// Private data 1433ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru//------------------------------------------------------------------------- 1434ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruvoid CalendarAstronomer::clearCache() { 143585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho const double INVALID = uprv_getNaN(); 143685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho 143785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho julianDay = INVALID; 143885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho julianCentury = INVALID; 143985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho sunLongitude = INVALID; 144085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho meanAnomalySun = INVALID; 144185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho moonLongitude = INVALID; 144285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho moonEclipLong = INVALID; 144385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho meanAnomalyMoon = INVALID; 144485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho eclipObliquity = INVALID; 144585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho siderealTime = INVALID; 144685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho siderealT0 = INVALID; 144785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho moonPositionSet = FALSE; 1448ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru} 1449ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 1450ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru//private static void out(String s) { 1451ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// System.out.println(s); 1452ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru//} 1453ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 1454ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru//private static String deg(double rad) { 1455ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// return Double.toString(rad * RAD_DEG); 1456ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru//} 1457ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 1458ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru//private static String hours(long ms) { 1459ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// return Double.toString((double)ms / HOUR_MS) + " hours"; 1460ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru//} 1461ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 1462ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/** 1463ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * @internal 1464ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * @deprecated ICU 2.4. This class may be removed or modified. 1465ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru */ 1466ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/*UDate CalendarAstronomer::local(UDate localMillis) { 1467ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru // TODO - srl ? 1468ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru TimeZone *tz = TimeZone::createDefault(); 1469ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru int32_t rawOffset; 1470ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru int32_t dstOffset; 1471ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru UErrorCode status = U_ZERO_ERROR; 1472ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru tz->getOffset(localMillis, TRUE, rawOffset, dstOffset, status); 1473ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru delete tz; 1474ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru return localMillis - rawOffset; 1475ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}*/ 1476ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 1477ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// Debugging functions 1478ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruUnicodeString CalendarAstronomer::Ecliptic::toString() const 1479ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{ 1480ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#ifdef U_DEBUG_ASTRO 148185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho char tmp[800]; 148285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho sprintf(tmp, "[%.5f,%.5f]", longitude*RAD_DEG, latitude*RAD_DEG); 148385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho return UnicodeString(tmp, ""); 1484ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#else 148585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho return UnicodeString(); 1486ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#endif 1487ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru} 1488ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 1489ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruUnicodeString CalendarAstronomer::Equatorial::toString() const 1490ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{ 1491ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#ifdef U_DEBUG_ASTRO 149285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho char tmp[400]; 149385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho sprintf(tmp, "%f,%f", 149485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho (ascension*RAD_DEG), (declination*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 QueruUnicodeString CalendarAstronomer::Horizon::toString() const 1502ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{ 1503ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#ifdef U_DEBUG_ASTRO 150485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho char tmp[800]; 150585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho sprintf(tmp, "[%.5f,%.5f]", altitude*RAD_DEG, azimuth*RAD_DEG); 150685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho return UnicodeString(tmp, ""); 1507ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#else 150885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho return UnicodeString(); 1509ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#endif 1510ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru} 1511ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 1512ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 1513ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// static private String radToHms(double angle) { 1514ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// int hrs = (int) (angle*RAD_HOUR); 1515ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// int min = (int)((angle*RAD_HOUR - hrs) * 60); 1516ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// int sec = (int)((angle*RAD_HOUR - hrs - min/60.0) * 3600); 1517ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 1518ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// return Integer.toString(hrs) + "h" + min + "m" + sec + "s"; 1519ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// } 1520ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 1521ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// static private String radToDms(double angle) { 1522ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// int deg = (int) (angle*RAD_DEG); 1523ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// int min = (int)((angle*RAD_DEG - deg) * 60); 1524ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// int sec = (int)((angle*RAD_DEG - deg - min/60.0) * 3600); 1525ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 1526ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// return Integer.toString(deg) + "\u00b0" + min + "'" + sec + "\""; 1527ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// } 1528ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 1529ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// =============== Calendar Cache ================ 1530ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 1531ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruvoid CalendarCache::createCache(CalendarCache** cache, UErrorCode& status) { 153285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho ucln_i18n_registerCleanup(UCLN_I18N_ASTRO_CALENDAR, calendar_astro_cleanup); 153385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho if(cache == NULL) { 153485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho status = U_MEMORY_ALLOCATION_ERROR; 153585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho } else { 153685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho *cache = new CalendarCache(32, status); 153785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho if(U_FAILURE(status)) { 153885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho delete *cache; 153985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho *cache = NULL; 154085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho } 1541ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 1542ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru} 1543ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 1544ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruint32_t CalendarCache::get(CalendarCache** cache, int32_t key, UErrorCode &status) { 154585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho int32_t res; 1546ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 1547ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if(U_FAILURE(status)) { 154885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho return 0; 154985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho } 155085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho umtx_lock(&ccLock); 155185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho 155285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho if(*cache == NULL) { 155385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho createCache(cache, status); 155485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho if(U_FAILURE(status)) { 155585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho umtx_unlock(&ccLock); 155685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho return 0; 155785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho } 1558ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 1559ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 156085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho res = uhash_igeti((*cache)->fTable, key); 156185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho U_DEBUG_ASTRO_MSG(("%p: GET: [%d] == %d\n", (*cache)->fTable, key, res)); 1562ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 156385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho umtx_unlock(&ccLock); 156485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho return res; 1565ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru} 1566ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 1567ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruvoid CalendarCache::put(CalendarCache** cache, int32_t key, int32_t value, UErrorCode &status) { 1568ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if(U_FAILURE(status)) { 156985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho return; 157085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho } 157185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho umtx_lock(&ccLock); 157285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho 157385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho if(*cache == NULL) { 157485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho createCache(cache, status); 157585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho if(U_FAILURE(status)) { 157685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho umtx_unlock(&ccLock); 157785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho return; 157885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho } 1579ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 1580ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 158185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho uhash_iputi((*cache)->fTable, key, value, &status); 158285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho U_DEBUG_ASTRO_MSG(("%p: PUT: [%d] := %d\n", (*cache)->fTable, key, value)); 1583ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 158485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho umtx_unlock(&ccLock); 1585ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru} 1586ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 1587ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruCalendarCache::CalendarCache(int32_t size, UErrorCode &status) { 158885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho fTable = uhash_openSize(uhash_hashLong, uhash_compareLong, NULL, size, &status); 158985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho U_DEBUG_ASTRO_MSG(("%p: Opening.\n", fTable)); 1590ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru} 1591ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 1592ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruCalendarCache::~CalendarCache() { 159385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho if(fTable != NULL) { 159485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho U_DEBUG_ASTRO_MSG(("%p: Closing.\n", fTable)); 159585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho uhash_close(fTable); 159685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho } 1597ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru} 1598ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 1599ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruU_NAMESPACE_END 1600ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 1601ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#endif // !UCONFIG_NO_FORMATTING 1602