/*
* Copyright 2015. Appsi Mobile
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.appsimobile.appsii.module.home;
/**
* File: MoonCalculation.java
* Author: Angus McIntyre <angus@pobox.com>
* Date: 31.05.96
* Updated: 01.06.96
* <p/>
* Java class to calculate the phase of the moon, given a date. The
* 'moonPhase' method is a Java port of some public domain C source which
* was apparently originally part of the Decus C distribution (whatever
* that was). Details of the algorithm are given below.
* <p/>
* To use this in a program, create an object of class 'MoonCalculation'.
* <p/>
* I'm not convinced that the algorithm is entirely accurate, but I don't
* know enough to confirm whether it is or not.
* <p/>
* HISTORY
* -------
* <p/>
* 31.05.96 SLAM Converted from C
* 01.06.96 SLAM Added 'phaseName' to return the name of a phase.
* Fixed leap year test in 'daysInMonth'.
* <p/>
* LEGAL
* -----
* <p/>
* This software is free. It can be used and modified in any way you
* choose. The author assumes no liability for any loss or damage you
* may incur through use of or inability to use this software. This
* disclaimer must appear on any modified or unmodified version of
* the software in which the name of the author also appears.
*/
// MoonCalculation
//
// Class to calculate information about the phases of the moon.
public class MoonCalculation {
// day_year - gives the day of the year for the first day of each
// month -1. i.e. 1st January is the 0th day of the year, 1st
// February is the 31st etc. Used by 'moonPhase'.
private static final int day_year[] = {-1, -1, 30, 58, 89, 119,
150, 180, 211, 241, 272,
303, 333};
// moon_phase_name - the English name for the different phases.
// Change this if you need to localise the software.
private static final String moon_phase_name[] = {
"New",
"Waxing crescent",
"First quarter",
"Waxing gibbous",
"Full",
"Waning gibbous",
"Third quarter",
"Waning crescent"};
// MoonPhase
//
// Output the phase of the moon for the given year, month, day.
// The routine calculates the year's epact (the age of the moon on Jan 1.),
// adds this to the number of days in the year, and calculates the phase
// of the moon for this date.
//
// In the algorithm:
//
// diy Is the day of the year - 1 (i.e., Jan 1 is day 0).
//
// golden Is the number of the year in the Mentonic cycle, used to
// determine the position of the calender moon.
//
// epact Is the age of the calender moon (in days) at the beginning
// of the year. To calculate epact, two century-based
// corrections are applied:
// Gregorian: (3 * cent)/4 - 12
// is the number of years such as 1700, 1800 when
// leap year was not held.
// Clavian: (((8 * cent) + 5) / 25) - 5
// is a correction to the Mentonic cycle of about
// 8 days every 2500 years. Note that this will
// overflow 16 bits in the year 409600. Beware.
//
// The algorithm is accurate for the Gregorian calender only.
//
// The magic numbers used in the phase calculation are as follows:
// 29.5 The moon's period in days.
// 177 29.5 scaled by 6
// 22 (29.5 / 8) scaled by 6 (this gets the phase)
// 11 ((29.5 / 8) / 2) scaled by 6
//
// Theoretically, this should yield a number in the range 0 .. 7. However,
// two days per year, things don't work out too well.
//
// Epact is calculated by the algorithm given in Knuth vol. 1 (calculation
// of Easter). See also the article on Calenders in the Encyclopaedia
// Britannica and Knuth's algorithm in CACM April 1962, page 209.
//
// Arguments to the function are:
//
// int year 1978 = 1978
// int month Jan = 1
// int day 1 = 1
public int moonPhase(int year, int month, int day) {
int phase; // Moon phase
int cent; // Century number (1979 = 20)
int epact; // Age of the moon on Jan. 1
int diy; // Day in the year
int golden; // Moon's golden number
if (month < 0 || month > 12) month = 0; // Just in case
diy = day + day_year[month]; // Day in the year
if ((month > 2) && this.isLeapYearP(year)) {
diy++; // Leapyear fixup
}
cent = (year / 100) + 1; // Century number
golden = (year % 19) + 1; // Golden number
epact = ((11 * golden) + 20 // Golden number
+ (((8 * cent) + 5) / 25) - 5 // 400 year cycle
- (((3 * cent) / 4) - 12)) % 30; //Leap year correction
if (epact <= 0) {
epact += 30; // Age range is 1 .. 30
}
if ((epact == 25 && golden > 11) ||
epact == 24) {
epact++;
}
// Calculate the phase, using the magic numbers defined above.
// Note that (phase and 7) is equivalent to (phase mod 8) and
// is needed on two days per year (when the algorithm yields 8).
phase = (((((diy + epact) * 6) + 11) % 177) / 22) & 7;
return (phase);
}
// isLeapYearP
//
// Return true if the year is a leapyear
public boolean isLeapYearP(int year) {
return ((year % 4 == 0) &&
((year % 400 == 0) || (year % 100 != 0)));
}
// daysInMonth
//
// Returns the number of days in a month given the month and the year.
int daysInMonth(int month, int year) {
int result = 31;
switch (month) {
case 4:
case 6:
case 9:
case 11:
result = 30;
break;
case 2:
result = (this.isLeapYearP(year) ? 29 : 28);
}
return result;
}
// phaseName
//
// Return the name of a given phase
String phaseName(int phase) {
return moon_phase_name[phase];
}
}