libkholidays

lunarphase.cpp
1 /*
2  This file is part of libkholidays.
3  Copyright (c) 2004 Allen Winter <winter@kde.org>
4 
5  Copyright (c) 1989, 1993
6  The Regents of the University of California. All rights reserved.
7 
8  This library is free software; you can redistribute it and/or
9  modify it under the terms of the GNU General Public License as
10  published by the Free Software Foundation; either version 2 of the
11  License, or (at your option) any later version.
12 
13  This library is distributed in the hope that it will be useful,
14  but WITHOUT ANY WARRANTY; without even the implied warranty of
15  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16  General Public License for more details.
17 
18  You should have received a copy of the GNU General Public License
19  along with this program; if not, write to the Free Software
20  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
21 
22  In addition, as a special exception, the copyright holders give
23  permission to link the code of this program with any edition of
24  the TQt library by Trolltech AS, Norway (or with modified versions
25  of TQt that use the same license as TQt), and distribute linked
26  combinations including the two. You must obey the GNU General
27  Public License in all respects for all of the code used other than
28  TQt. If you modify this file, you may extend this exception to
29  your version of the file, but you are not obligated to do so. If
30  you do not wish to do so, delete this exception statement from
31  your version.
32 */
33 
34 #include "config.h"
35 
36 #include <tdeglobal.h>
37 #include <tdelocale.h>
38 #include <kdebug.h>
39 
40 #include "lunarphase.h"
41 
42 LunarPhase::LunarPhase( Hemisphere hemisphere )
43 {
44  mHemisphere = hemisphere;
45 }
46 
47 LunarPhase::~LunarPhase()
48 {
49 }
50 
51 void LunarPhase::setHemisphere( Hemisphere hemisphere )
52 {
53  mHemisphere = hemisphere;
54 }
55 
56 LunarPhase::Hemisphere LunarPhase::hemisphere() const
57 {
58  return( mHemisphere );
59 }
60 
61 TQString LunarPhase::hemisphereStr() const
62 {
63  return hemisphereName( mHemisphere );
64 }
65 
66 TQString LunarPhase::hemisphereName( LunarPhase::Hemisphere hemisphere )
67 {
68  switch( hemisphere ) {
69  case Northern:
70  default:
71  return( i18n( "Northern" ) );
72  break;
73  case Southern:
74  return( i18n( "Southern" ) );
75  break;
76  }
77 }
78 
79 TQString LunarPhase::phaseStr( const TQDate &date ) const
80 {
81  return phaseName( phase( date ) );
82 }
83 
84 TQString LunarPhase::phaseName( LunarPhase::Phase phase )
85 {
86  switch ( phase ) {
87  case New:
88  return( i18n( "New Moon" ) );
89  break;
90  case Full:
91  return( i18n( "Full Moon" ) );
92  break;
93  case FirstQ:
94  return( i18n( "First Quarter Moon" ) );
95  break;
96  case LastQ:
97  return( i18n( "Last Quarter Moon" ) );
98  break;
99  default:
100  case None:
101  return( TQString() );
102  break;
103  }
104 }
105 
106 LunarPhase::Phase LunarPhase::phase( const TQDate &date ) const
107 {
108  Phase retPhase = None;
109 
110  // compute percent-full for the middle of today and yesterday.
111  TQTime noontime( 12, 0, 0 );
112  TQDateTime today( date, noontime );
113  double todayPer = percentFull( today.toTime_t() );
114  TQDateTime yesterday( date.addDays(-1), noontime );
115  double yesterdayPer = percentFull( yesterday.toTime_t() );
116 
117  if ( ( todayPer < 0.50 ) && ( yesterdayPer > 0.50 ) ) {
118  retPhase = New;
119  } else if ( ( todayPer > 99.50 ) && ( yesterdayPer < 99.50 ) ) {
120  retPhase = Full;
121  } else {
122  // compute percent-full for the start of today.
123  TQTime sqt( 0, 0, 0 );
124  TQDateTime start( date, sqt );
125  double startPer = percentFull( start.toTime_t() );
126  // compute percent-full for the end of today.
127  TQTime eqt( 23, 59, 59 );
128  TQDateTime end( date, eqt );
129  double endPer = percentFull( end.toTime_t() );
130 
131  if ( ( startPer <= 50 ) && ( endPer > 50 ) ) {
132  if ( mHemisphere == Northern ) {
133  retPhase = FirstQ;
134  } else {
135  retPhase = LastQ;
136  }
137  }
138  if ( ( endPer <= 50 ) && ( startPer > 50 ) ) {
139  if ( mHemisphere == Northern ) {
140  retPhase = LastQ;
141  } else {
142  retPhase = FirstQ;
143  }
144  }
145  // Note: if you want to support crescent and gibbous phases then please
146  // read the source for the original BSD 'pom' program.
147  }
148  return( retPhase );
149 }
150 
151 /*
152  * Copyright (c) 1989, 1993
153  * The Regents of the University of California. All rights reserved.
154  *
155  * This code is derived from software posted to USENET.
156  *
157  * Redistribution and use in source and binary forms, with or without
158  * modification, are permitted provided that the following conditions
159  * are met:
160  * 1. Redistributions of source code must retain the above copyright
161  * notice, this list of conditions and the following disclaimer.
162  * 2. Redistributions in binary form must reproduce the above copyright
163  * notice, this list of conditions and the following disclaimer in the
164  * documentation and/or other materials provided with the distribution.
165  * 3. All advertising materials mentioning features or use of this software
166  * must display the following acknowledgement:
167  * This product includes software developed by the University of
168  * California, Berkeley and its contributors.
169  * 4. Neither the name of the University nor the names of its contributors
170  * may be used to endorse or promote products derived from this software
171  * without specific prior written permission.
172  *
173  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
174  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
175  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
176  * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
177  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
178  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
179  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
180  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
181  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
182  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
183  * SUCH DAMAGE.
184  */
185 
186 #if HAVE_SYS_CDEFS_H
187 #include <sys/cdefs.h>
188 #endif
189 
190 /*
191  * Phase of the Moon. Calculates the current phase of the moon.
192  * Based on routines from `Practical Astronomy with Your Calculator',
193  * by Duffett-Smith. Comments give the section from the book that
194  * particular piece of code was adapted from.
195  *
196  * -- Keith E. Brandt VIII 1984
197  *
198  * Updated to the Third Edition of Duffett-Smith's book, Paul Janzen, IX 1998
199  *
200  */
201 
202 
203 #include <ctype.h>
204 #if HAVE_ERR_H
205 #include <err.h>
206 #endif
207 #include <math.h>
208 #include <string.h>
209 #include <stdlib.h>
210 #include <time.h>
211 #include <unistd.h>
212 
213 #ifndef PI
214 #define PI 3.14159265358979323846
215 #endif
216 
217 /*
218  * The EPOCH in the third edition of the book is 1990 Jan 0.0 TDT.
219  * In this program, we do not bother to correct for the differences
220  * between UTC (as shown by the UNIX clock) and TDT. (TDT = TAI + 32.184s;
221  * TAI-UTC = 32s in Jan 1999.)
222  */
223 #define EPOCH_MINUS_1970 (20 * 365 + 5 - 1) /* 20 years, 5 leaps, back 1 day to Jan 0 */
224 #define EPSILONg 279.403303 /* solar ecliptic long at EPOCH */
225 #define RHOg 282.768422 /* solar ecliptic long of perigee at EPOCH */
226 #define ECCEN 0.016713 /* solar orbit eccentricity */
227 #define lzero 318.351648 /* lunar mean long at EPOCH */
228 #define Pzero 36.340410 /* lunar mean long of perigee at EPOCH */
229 #define Nzero 318.510107 /* lunar mean long of node at EPOCH */
230 
231 /*
232  * percentFull --
233  * return phase of the moon as a percentage of full
234  */
235 double LunarPhase::percentFull( uint tmpt ) const
236 {
237  double N, Msol, Ec, LambdaSol, l, Mm, Ev, Ac, A3, Mmprime;
238  double A4, lprime, V, ldprime, D, Nm;
239 
240  double days;
241  days = ( tmpt - EPOCH_MINUS_1970 * 86400 ) / 86400.0;
242 
243  N = 360 * days / 365.242191; /* sec 46 #3 */
244  adj360(&N);
245  Msol = N + EPSILONg - RHOg; /* sec 46 #4 */
246  adj360(&Msol);
247  Ec = 360 / PI * ECCEN * sin(degreesToRadians(Msol)); /* sec 46 #5 */
248  LambdaSol = N + Ec + EPSILONg; /* sec 46 #6 */
249  adj360(&LambdaSol);
250  l = 13.1763966 * days + lzero; /* sec 65 #4 */
251  adj360(&l);
252  Mm = l - (0.1114041 * days) - Pzero; /* sec 65 #5 */
253  adj360(&Mm);
254  Nm = Nzero - (0.0529539 * days); /* sec 65 #6 */
255  adj360(&Nm);
256  Ev = 1.2739 * sin(degreesToRadians(2*(l - LambdaSol) - Mm)); /* sec 65 #7 */
257  Ac = 0.1858 * sin(degreesToRadians(Msol)); /* sec 65 #8 */
258  A3 = 0.37 * sin(degreesToRadians(Msol));
259  Mmprime = Mm + Ev - Ac - A3; /* sec 65 #9 */
260  Ec = 6.2886 * sin(degreesToRadians(Mmprime)); /* sec 65 #10 */
261  A4 = 0.214 * sin(degreesToRadians(2 * Mmprime)); /* sec 65 #11 */
262  lprime = l + Ev + Ec - Ac + A4; /* sec 65 #12 */
263  V = 0.6583 * sin(degreesToRadians(2 * (lprime - LambdaSol))); /* sec 65 #13 */
264  ldprime = lprime + V; /* sec 65 #14 */
265  D = ldprime - LambdaSol; /* sec 67 #2 */
266  return(50.0 * (1 - cos(degreesToRadians(D)))); /* sec 67 #3 */
267 }
268 
269 /*
270  * degreesToRadians --
271  * convert degrees to radians
272  */
273 double LunarPhase::degreesToRadians( double degree ) const
274 {
275  return( degree * PI / 180 );
276 }
277 
278 /*
279  * adj360 --
280  * adjust value so 0 <= degree <= 360
281  */
282 void LunarPhase::adj360( double *degree ) const
283 {
284  for( ;; )
285  if( *degree < 0 )
286  *degree += 360;
287  else if( *degree > 360 )
288  *degree -= 360;
289  else
290  break;
291 }
Phase phase(const TQDate &date) const
Return the lunar phase for the specified Gregorian date.
Definition: lunarphase.cpp:106
TQString hemisphereStr() const
Return hemisphere as a clear text string.
Definition: lunarphase.cpp:61
Hemisphere hemisphere() const
Return the hemisphere.
Definition: lunarphase.cpp:56
void setHemisphere(Hemisphere hemisphere=Northern)
Set the hemisphere.
Definition: lunarphase.cpp:51
static TQString phaseName(Phase phase)
Return the string representation of phase.
Definition: lunarphase.cpp:84
static TQString hemisphereName(Hemisphere hemisphere)
Return the string representation of hemisphere.
Definition: lunarphase.cpp:66
TQString phaseStr(const TQDate &date) const
Return the lunar phase as a text string for the specified date.
Definition: lunarphase.cpp:79