libkholidays
lunarphase.cpp
Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025 #include "lunarphase.h"
00026 #include <config-libkholidays.h>
00027
00028 #include <QDateTime>
00029 #include <KLocale>
00030 #include <KGlobal>
00031
00032 using namespace LibKHolidays;
00033
00034 LunarPhase::LunarPhase()
00035 {
00036 }
00037
00038 LunarPhase::~LunarPhase()
00039 {
00040 }
00041
00042 QString LunarPhase::phaseStr( const QDate &date ) const
00043 {
00044 return phaseName( phase( date ) );
00045 }
00046
00047 QString LunarPhase::phaseName( LunarPhase::Phase phase )
00048 {
00049 switch ( phase ) {
00050 case NewMoon:
00051 return( i18n( "New Moon" ) );
00052 case FullMoon:
00053 return( i18n( "Full Moon" ) );
00054 case FirstQuarter:
00055 return( i18n( "First Quarter Moon" ) );
00056 case LastQuarter:
00057 return( i18n( "Last Quarter Moon" ) );
00058 default:
00059 case None:
00060 return QString();
00061 }
00062 }
00063
00064 LunarPhase::Phase LunarPhase::phase( const QDate &date ) const
00065 {
00066 Phase retPhase = None;
00067
00068
00069 QTime noontime( 12, 0, 0 );
00070 QDateTime today( date, noontime );
00071 double todayPer = percentFull( today.toTime_t() );
00072 QDateTime yesterday( date.addDays(-1), noontime );
00073 double yesterdayPer = percentFull( yesterday.toTime_t() );
00074
00075 if ( ( todayPer < 0.50 ) && ( yesterdayPer > 0.50 ) ) {
00076 retPhase = NewMoon;
00077 } else if ( ( todayPer > 99.50 ) && ( yesterdayPer < 99.50 ) ) {
00078 retPhase = FullMoon;
00079 } else {
00080
00081 QTime sqt( 0, 0, 0 );
00082 QDateTime start( date, sqt );
00083 double startPer = percentFull( start.toTime_t() );
00084
00085 QTime eqt( 23, 59, 59 );
00086 QDateTime end( date, eqt );
00087 double endPer = percentFull( end.toTime_t() );
00088
00089 if ( ( startPer <= 50 ) && ( endPer > 50 ) ) {
00090 retPhase = FirstQuarter;
00091 }
00092 if ( ( endPer <= 50 ) && ( startPer > 50 ) ) {
00093 retPhase = LastQuarter;
00094 }
00095
00096
00097 }
00098 return( retPhase );
00099 }
00100
00101
00102
00103
00104
00105
00106
00107
00108
00109
00110
00111
00112
00113
00114
00115
00116
00117
00118
00119
00120
00121
00122
00123
00124
00125
00126
00127
00128
00129
00130
00131
00132
00133
00134
00135
00136 #ifdef HAVE_SYS_CDEFS_H
00137 #include <sys/cdefs.h>
00138 #endif
00139
00140
00141
00142
00143
00144
00145
00146
00147
00148
00149
00150
00151
00152 #include <ctype.h>
00153 #ifdef HAVE_ERR_H
00154 #include <err.h>
00155 #endif
00156 #include <math.h>
00157 #include <string.h>
00158 #include <stdlib.h>
00159 #include <time.h>
00160 #include <unistd.h>
00161
00162 #ifndef PI
00163 #define PI 3.14159265358979323846
00164 #endif
00165
00166
00167
00168
00169
00170
00171
00172 #define EPOCH_MINUS_1970 (20 * 365 + 5 - 1)
00173 #define EPSILONg 279.403303
00174 #define RHOg 282.768422
00175 #define ECCEN 0.016713
00176 #define lzero 318.351648
00177 #define Pzero 36.340410
00178 #define Nzero 318.510107
00179
00180
00181
00182
00183
00184 double LunarPhase::percentFull( uint tmpt ) const
00185 {
00186 double N, Msol, Ec, LambdaSol, l, Mm, Ev, Ac, A3, Mmprime;
00187 double A4, lprime, V, ldprime, D, Nm;
00188
00189 double days;
00190 days = ( tmpt - EPOCH_MINUS_1970 * 86400 ) / 86400.0;
00191
00192 N = 360 * days / 365.242191;
00193 adj360( &N );
00194 Msol = N + EPSILONg - RHOg;
00195 adj360( &Msol );
00196 Ec = 360 / PI * ECCEN * sin( degreesToRadians( Msol ) );
00197 LambdaSol = N + Ec + EPSILONg;
00198 adj360( &LambdaSol );
00199 l = 13.1763966 * days + lzero;
00200 adj360( &l );
00201 Mm = l - ( 0.1114041 * days ) - Pzero;
00202 adj360( &Mm );
00203 Nm = Nzero - ( 0.0529539 * days );
00204 adj360( &Nm );
00205 Ev = 1.2739 * sin( degreesToRadians( 2 * ( l - LambdaSol ) - Mm ) );
00206 Ac = 0.1858 * sin( degreesToRadians( Msol ) );
00207 A3 = 0.37 * sin( degreesToRadians( Msol ) );
00208 Mmprime = Mm + Ev - Ac - A3;
00209 Ec = 6.2886 * sin( degreesToRadians( Mmprime ) );
00210 A4 = 0.214 * sin( degreesToRadians( 2 * Mmprime ) );
00211 lprime = l + Ev + Ec - Ac + A4;
00212 V = 0.6583 * sin( degreesToRadians( 2 * ( lprime - LambdaSol ) ) );
00213 ldprime = lprime + V;
00214 D = ldprime - LambdaSol;
00215 D = 50.0 * ( 1 - cos( degreesToRadians( D ) ) );
00216 return D;
00217 }
00218
00219
00220
00221
00222
00223 double LunarPhase::degreesToRadians( double degree ) const
00224 {
00225 return( degree * PI / 180 );
00226 }
00227
00228
00229
00230
00231
00232 void LunarPhase::adj360( double *degree ) const
00233 {
00234 for ( ;; ) {
00235 if ( *degree < 0 ) {
00236 *degree += 360;
00237 } else if ( *degree > 360 ) {
00238 *degree -= 360;
00239 } else {
00240 break;
00241 }
00242 }
00243 }