Skip to content

Instantly share code, notes, and snippets.

@thiagovespa
Created April 5, 2018 14:43
Show Gist options
  • Save thiagovespa/608288853516d460baf4f9cd11f086b0 to your computer and use it in GitHub Desktop.
Save thiagovespa/608288853516d460baf4f9cd11f086b0 to your computer and use it in GitHub Desktop.
Cálculo das fases da Lua
import java.time.Duration;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.Month;
import java.time.ZoneOffset;
import java.time.format.DateTimeFormatter;
import java.time.format.FormatStyle;
import java.time.temporal.ChronoUnit;
import java.time.temporal.TemporalField;
import java.util.Locale;
import java.util.stream.Stream;
/**
* https://thiagovespa.com.br/blog/2018/04/04/calculo-do-dia-lunar-e-fases-da-lua-com-java-10/
* https://thiagovespa.com.br/blog/2018/04/05/como-saber-a-fase-da-lua-de-cabeca/
*/
public class MoonUtils {
public static final long SYNODIC_PERIOD = 2551442877L; //29.530588854 days
public static final LocalDateTime KNOWN_NEW_MOON = LocalDate.of(1970, Month.JANUARY, 7).atStartOfDay();
static enum MoonPhase {
NEW_MOON, // Nova
WAXING_CRESCENT, // Crescente
FIRST_QUARTER, // Quarto crescente
WAXING_GIBBOUS, // Crescente gibosa
FULL_MOON, // Cheia
WANING_GIBBOUS, // Minguante gibosa
THIRD_QUARTER, // Quarto minguante
WANING_CRESCENT; // Minguante
}
public static int getLunarDay(LocalDateTime day) {
var lunarDay = (int) Duration.ofMillis(Duration.between(KNOWN_NEW_MOON, day).toMillis() % SYNODIC_PERIOD).toDays();
return lunarDay;
}
public static MoonPhase getMoonPhase(int lunarDay) {
var phaseNum = (int)Math.floor(lunarDay/3.7);
return MoonPhase.values()[phaseNum];
}
public static MoonPhase getMoonPhaseConway(int lunarDay) {
if(lunarDay<=28) {
if(lunarDay>=24) {
return MoonPhase.WANING_CRESCENT;
}
if(lunarDay>=22) {
return MoonPhase.THIRD_QUARTER;
}
if(lunarDay>=17) {
return MoonPhase.WANING_GIBBOUS;
}
if(lunarDay>=14) {
return MoonPhase.FULL_MOON;
}
if(lunarDay>=9) {
return MoonPhase.WAXING_GIBBOUS;
}
if(lunarDay>=7) {
return MoonPhase.FIRST_QUARTER;
}
if(lunarDay>=2) {
return MoonPhase.WAXING_CRESCENT;
}
}
return MoonPhase.NEW_MOON; //0,1,29
}
/**
* Based on https://www.cs.williams.edu/~bailey/cs135/lectures/Lecture02.pdf and http://www.faqs.org/faqs/astronomy/faq/part3/section-15.html
* Only works on 20th and 21th century
*/
public static int getLunarDayConway(LocalDateTime ldt) {
var year = ldt.getYear();
var month = ldt.getMonthValue();
var day = ldt.getDayOfMonth();
if(year < 1900 || year >= 2100) throw new RuntimeException("Date must be greater than 1900 and less than 2100");
var centS = -4.0;
if(year > 2000) {
centS = -8.3;
}
var lastTwoDigits = year%100.0;
double vl = lastTwoDigits % 19;
if(vl > 9) {
vl-=19.0;
}
vl*=11.0;
vl%=30;
vl+=centS;
vl+=month+day;
if(month<3) {
vl+=2;
}
vl = Math.round(vl)%30;
return (int)((vl < 0) ? vl+30 : vl);
}
public static void main(String[] args) {
var now = LocalDateTime.now();
var end = now.plusMonths(1);
Stream.iterate(now, date -> date.plusDays(1))
.limit(ChronoUnit.DAYS.between(now, end))
.forEach(MoonUtils::printLunarAnalysis);
}
private static void printLunarAnalysis(LocalDateTime ldt) {
var df = DateTimeFormatter
.ofLocalizedDate(FormatStyle.SHORT)
.withLocale(new Locale("pt", "br"));
var lunarDay = getLunarDay(ldt);
var lunarDayConway = getLunarDayConway(ldt);
var moonPhase = getMoonPhase(lunarDay);
var moonPhaseConway = getMoonPhase(lunarDayConway);
System.out.println("Data: " + ldt.format(df));
System.out.println("Dia lunar: " + lunarDay);
System.out.println("Dia lunar Conway: " + lunarDayConway);
System.out.println("Fase da lua (provável): " + moonPhase);
System.out.println("Fase da lua (provável) Conway: " + moonPhaseConway);
System.out.println();
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment