Compare commits

..

No commits in common. "9ecaefc708a5a41c244c08c5ef9f2fef0109f4a5" and "53e1f97b09495b06b98a6510ef57482ab819b214" have entirely different histories.

5 changed files with 41 additions and 93 deletions

View file

@ -2,15 +2,14 @@ package eu.m724.wtapi.object;
import java.time.Duration; import java.time.Duration;
import java.time.LocalDate; import java.time.LocalDate;
import java.time.LocalDateTime;
/** /**
* @param date The date this object contains times for * @param date The date this object contains times for
* @param sunrise Time of sunrise * @param sunrise Time of sunrise relative to UTC midnight of the date
* @param sunset Time of sunset * @param sunset Time of sunset relative to UTC midnight of the date
*/ */
public record Twilight(LocalDate date, LocalDateTime sunrise, LocalDateTime sunset) { public record Twilight(LocalDate date, Duration sunrise, Duration sunset) {
public Duration getDayLength() { public Duration getDayLength() {
return Duration.between(sunrise, sunset); return sunset.minus(sunrise);
} }
} }

View file

@ -4,6 +4,7 @@ import eu.m724.wtapi.object.Coordinates;
import eu.m724.wtapi.object.Twilight; import eu.m724.wtapi.object.Twilight;
import eu.m724.wtapi.provider.twilight.CacheableTwilightTimeProvider; import eu.m724.wtapi.provider.twilight.CacheableTwilightTimeProvider;
import java.time.Duration;
import java.time.LocalDate; import java.time.LocalDate;
import static java.lang.Math.*; import static java.lang.Math.*;
@ -21,22 +22,10 @@ public class ApproximateTwilightTimeProvider extends CacheableTwilightTimeProvid
double equationOfTime = cache.equationOfTime(); double equationOfTime = cache.equationOfTime();
double latRad = toRadians(coordinates.latitude); double latRad = toRadians(coordinates.latitude);
double hourAngle = hourAngle(latRad, declination); // 90.833 deg = 1.5853349194640094 rad
System.out.println(hourAngle); double n1 = cos(1.5853349194640094) / (cos(latRad) * cos(declination));
double n2 = tan(latRad) * tan(declination);
if (Double.isNaN(hourAngle)) { double hourAngle = acos(n1 - n2);
LocalDate sunriseDate = step(cache.date().minusDays(1), latRad, -1);
LocalDate sunsetDate = step(cache.date().plusDays(1), latRad, 1);
Twilight backwardTwilight = calculateTwilightTime(sunriseDate, coordinates);
Twilight forwardTwilight = calculateTwilightTime(sunsetDate, coordinates);
return new Twilight(
cache.date(),
backwardTwilight.sunrise(),
forwardTwilight.sunset()
);
}
double longitudeEffect = 4 * toDegrees(hourAngle); double longitudeEffect = 4 * toDegrees(hourAngle);
@ -48,64 +37,34 @@ public class ApproximateTwilightTimeProvider extends CacheableTwilightTimeProvid
return new Twilight( return new Twilight(
cache.date(), cache.date(),
cache.date().atStartOfDay().plusMinutes((long) sunrise), Duration.ofMillis((long) (sunrise * 60000)),
cache.date().atStartOfDay().plusMinutes((long) sunset) Duration.ofMillis((long) (sunset * 60000))
); );
} }
private LocalDate step(LocalDate date, double latRad, int direction) {
double declination = getDeclination(getFractionalYear(date));
System.out.println("Step date: " + date);
double hourAngle = hourAngle(latRad, declination);
if (Double.isNaN(hourAngle)) {
return step(date.plusDays(direction), latRad, direction);
}
System.out.println("this the one");
return date;
}
private double hourAngle(double latRad, double declination) {
// 90.833 deg = 1.5853349194640094 rad
double n1 = cos(1.5853349194640094) / (cos(latRad) * cos(declination));
double n2 = tan(latRad) * tan(declination);
System.out.println(n1 - n2);
return acos(n1 - n2);
}
@Override @Override
public ApproximateTwilightTimeCache initializeCache(LocalDate date) { public ApproximateTwilightTimeCache initializeCache(LocalDate date) {
double fractionalYear = getFractionalYear(date); int dayOfYear = date.getDayOfYear() - 1; // -1 because we have to start from zero
// 2 * PI / 365 = 0.01721420632103996
double fractionalYear = 0.01721420632103996 * dayOfYear;
double equationOfTime = 229.18 * (0.000075 double equationOfTime = 229.18 * (0.000075
+ 0.001868 * cos(fractionalYear) + 0.001868 * cos(fractionalYear)
- 0.032077 * sin(fractionalYear) - 0.032077 * sin(fractionalYear)
- 0.014615 * cos(2 * fractionalYear) - 0.014615 * cos(2 * fractionalYear)
- 0.040849 * sin(2 * fractionalYear)); - 0.040849 * sin(2 * fractionalYear));
double declination = 0.006918
return new ApproximateTwilightTimeCache(
date,
equationOfTime,
getDeclination(fractionalYear)
);
}
private double getFractionalYear(LocalDate date) {
return getFractionalYear(date.getDayOfYear() - 1); // -1 because we have to start from zero
}
private double getFractionalYear(int dayOfYear) {
return 0.01721420632103996 * dayOfYear;
}
private double getDeclination(double fractionalYear) {
return 0.006918
- 0.399912 * cos(fractionalYear) - 0.399912 * cos(fractionalYear)
+ 0.070257 * sin(fractionalYear) + 0.070257 * sin(fractionalYear)
- 0.006758 * cos(2 * fractionalYear) - 0.006758 * cos(2 * fractionalYear)
+ 0.000907 * sin(2 * fractionalYear) + 0.000907 * sin(2 * fractionalYear)
- 0.002697 * cos(3 * fractionalYear) - 0.002697 * cos(3 * fractionalYear)
+ 0.00148 * sin(3 * fractionalYear); + 0.00148 * sin(3 * fractionalYear);
return new ApproximateTwilightTimeCache(
date,
equationOfTime,
declination
);
} }
} }

View file

@ -6,48 +6,43 @@ import eu.m724.wtapi.provider.twilight.impl.approximate.ApproximateTwilightTimeP
import eu.m724.wtapi.provider.twilight.TwilightTimeProvider; import eu.m724.wtapi.provider.twilight.TwilightTimeProvider;
import org.junit.Test; import org.junit.Test;
import java.time.Duration;
import java.time.LocalDate; import java.time.LocalDate;
import java.time.LocalDateTime;
// TODO also test cached // TODO also test cached
public class ApproximateTwilightTimeTest { public class ApproximateTwilightTimeTest {
/** /**
* Acceptable discrepancy in seconds * Acceptable discrepancy in minutes
* 600 is 10 minutes
*/ */
public static int ACCEPTABLE_DIFFERENCE = 600; public static final int ACCEPTABLE_DIFFERENCE = 10;
@Test @Test
public void approximateTest() { public void approximateTest() {
TwilightTimeProvider provider = new ApproximateTwilightTimeProvider(); TwilightTimeProvider provider = new ApproximateTwilightTimeProvider();
// used https://gml.noaa.gov/grad/solcalc/index.html for reference values // used https://gml.noaa.gov/grad/solcalc/index.html for reference values
testLocation(provider, 26, 6, 2023, 53.123394, 23.0864867, LocalDateTime.of(2023, 6, 26, 2, 2), LocalDateTime.of(2023, 6, 26, 18, 59)); testLocation(provider, 26, 6, 2023, 53.123394, 23.0864867, 122, 1139);
testLocation(provider, 13, 11, 2040, 45.432427, -122.3899276, LocalDateTime.of(2040, 11, 13, 15, 7), LocalDateTime.of(2040, 11, 14, 0, 41)); testLocation(provider, 13, 11, 2040, 45.432427, -122.3899276, 907, 1481);
testLocation(provider, 23, 3, 2021, 55.5024161, 9.6801853, LocalDateTime.of(2021, 3, 23, 5, 15), LocalDateTime.of(2021, 3, 23, 17, 41)); testLocation(provider, 23, 3, 2021, 55.5024161, 9.6801853, 315, 1061);
testLocation(provider, 6, 8,1990, -72.012117, 2.5240873, LocalDateTime.of(1990, 8, 6, 10, 0), LocalDateTime.of(1990, 8, 6, 13, 52)); testLocation(provider, 6, 8,1990, -72.012117, 2.5240873, 600, 832);
// TODO this is broken (very inaccurate) so fix // TODO this is broken so fix
ACCEPTABLE_DIFFERENCE = 172800; // 2 days //testLocation(provider, 6, 9,2021, 82.498665, -62.3458366, 74, 1351); // date not on purpose as this was the first sunset in that location. first sunset since 5th april
testLocation(provider, 5, 9,2021, 82.498665, -62.3458366, LocalDateTime.of(2021, 4, 5, 20, 55), LocalDateTime.of(2021, 9, 6, 18, 22)); // the reference values might be incorrect
} }
private void testLocation(TwilightTimeProvider provider, int day, int month, int year, double latitude, double longitude, LocalDateTime actualSunrise, LocalDateTime actualSunset) { private void testLocation(TwilightTimeProvider provider, int day, int month, int year, double latitude, double longitude, int actualSunrise, int actualSunset) {
LocalDate date = LocalDate.of(year, month, day); LocalDate date = LocalDate.of(year, month, day);
Coordinates coordinates = new Coordinates(latitude, longitude); Coordinates coordinates = new Coordinates(latitude, longitude);
Twilight twilight = provider.calculateTwilightTime(date, coordinates); Twilight twilight = provider.calculateTwilightTime(date, coordinates);
System.out.println();
System.out.println(date); System.out.println(date);
System.out.println(coordinates.latitude + " " + coordinates.longitude); System.out.println(coordinates.latitude + " " + coordinates.longitude);
System.out.println("Calculated sunrise: " + twilight.sunrise()); System.out.println("Calculated sunrise: " + date.atStartOfDay().plus(twilight.sunrise()));
System.out.println("Actual sunrise: " + actualSunrise); System.out.println("Actual sunrise: " + date.atStartOfDay().plusMinutes(actualSunrise));
assert Duration.between(twilight.sunrise(), actualSunrise).abs().getSeconds() < ACCEPTABLE_DIFFERENCE; assert Math.abs(twilight.sunrise().toMinutes() - actualSunrise) < ACCEPTABLE_DIFFERENCE;
System.out.println("Calculated sunset: " + twilight.sunset()); System.out.println("Calculated sunset: " + date.atStartOfDay().plus(twilight.sunset()));
System.out.println("Actual sunset: " + actualSunset); System.out.println("Actual sunset: " + date.atStartOfDay().plusMinutes(actualSunset));
assert Duration.between(twilight.sunset(), actualSunset).abs().getSeconds() < ACCEPTABLE_DIFFERENCE; assert Math.abs(twilight.sunset().toMinutes() - actualSunset) < ACCEPTABLE_DIFFERENCE;
System.out.println();
} }
} }

View file

@ -6,8 +6,6 @@ import eu.m724.wtapi.provider.twilight.TwilightTimeProvider;
import java.time.Duration; import java.time.Duration;
import java.time.LocalDate; import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
public class MockTwilightTimeProvider extends TwilightTimeProvider { public class MockTwilightTimeProvider extends TwilightTimeProvider {
@Override @Override
@ -15,8 +13,8 @@ public class MockTwilightTimeProvider extends TwilightTimeProvider {
int time = (int) (coordinates.latitude + coordinates.longitude); int time = (int) (coordinates.latitude + coordinates.longitude);
return new Twilight( return new Twilight(
date, date,
date.atStartOfDay().plusSeconds(-time), Duration.ofMinutes(-time),
date.atStartOfDay().plusSeconds(time) Duration.ofMinutes(time)
); );
} }
} }

View file

@ -17,10 +17,7 @@ public class MockTwilightTimeTest {
Twilight twilight = provider.calculateTwilightTime(date, coordinates); Twilight twilight = provider.calculateTwilightTime(date, coordinates);
assert twilight.date().equals(date); assert twilight.date().equals(date);
// this might make no sense but just a test remember assert twilight.sunrise().getSeconds() == -6840;
assert twilight.sunrise().getDayOfMonth() == 19; assert twilight.sunset().getSeconds() == 6840;
assert twilight.sunrise().toLocalTime().toSecondOfDay() == 86286;
assert twilight.sunset().getDayOfMonth() == 20;
assert twilight.sunset().toLocalTime().toSecondOfDay() == 114;
} }
} }