Skip to content

Commit

Permalink
Fix for issue #2: Error computing sunrise for a different timezone wh…
Browse files Browse the repository at this point in the history
…en sunrise occurs on a different day. Added testdata for this case with Lat/Long of Novosibirsk, Russia and target timezone of GMT.
  • Loading branch information
mikereedell committed May 9, 2012
1 parent dac4887 commit 68cf9b1
Show file tree
Hide file tree
Showing 6 changed files with 450 additions and 13 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,7 @@ public Calendar computeSunriseCalendar(Zenith solarZenith, Calendar date) {
public String computeSunsetTime(Zenith solarZenith, Calendar date) {
return getLocalTimeAsString(computeSolarEventTime(solarZenith, date, false));
}

/**
* Computes the sunset time for the given zenith at the given date.
*
Expand Down Expand Up @@ -174,8 +175,8 @@ private BigDecimal getMeanAnomaly(BigDecimal longitudeHour) {
*/
private BigDecimal getSunTrueLongitude(BigDecimal meanAnomaly) {
BigDecimal sinMeanAnomaly = new BigDecimal(Math.sin(convertDegreesToRadians(meanAnomaly).doubleValue()));
BigDecimal sinDoubleMeanAnomaly = new BigDecimal(Math.sin(multiplyBy(convertDegreesToRadians(meanAnomaly),
BigDecimal.valueOf(2)).doubleValue()));
BigDecimal sinDoubleMeanAnomaly = new BigDecimal(Math.sin(multiplyBy(convertDegreesToRadians(meanAnomaly), BigDecimal.valueOf(2))
.doubleValue()));

BigDecimal firstPart = meanAnomaly.add(multiplyBy(sinMeanAnomaly, new BigDecimal("1.916")));
BigDecimal secondPart = multiplyBy(sinDoubleMeanAnomaly, new BigDecimal("0.020")).add(new BigDecimal("282.634"));
Expand Down Expand Up @@ -295,9 +296,15 @@ private BigDecimal adjustForDST(BigDecimal localMeanTime, Calendar date) {
* <code>BigDecimal</code> representation of the local rise/set time.
* @return <code>String</code> representation of the local rise/set time in HH:MM format.
*/
private String getLocalTimeAsString(BigDecimal localTime) {
if (localTime == null)
private String getLocalTimeAsString(BigDecimal localTimeParam) {
if (localTimeParam == null) {
return "99:99";
}

BigDecimal localTime = localTimeParam;
if (localTime.compareTo(BigDecimal.ZERO) == -1) {
localTime = localTime.add(BigDecimal.valueOf(24.0D));
}
String[] timeComponents = localTime.toPlainString().split("\\.");
int hour = Integer.parseInt(timeComponents[0]);

Expand All @@ -307,6 +314,9 @@ private String getLocalTimeAsString(BigDecimal localTime) {
minutes = BigDecimal.ZERO;
hour += 1;
}
if (hour == 24) {
hour = 0;
}

String minuteString = minutes.intValue() < 10 ? "0" + minutes.toPlainString() : minutes.toPlainString();
String hourString = (hour < 10) ? "0" + String.valueOf(hour) : String.valueOf(hour);
Expand All @@ -316,13 +326,23 @@ private String getLocalTimeAsString(BigDecimal localTime) {
/**
* Returns the local rise/set time in the form HH:MM.
*
* @param localTime
* @param localTimeParam
* <code>BigDecimal</code> representation of the local rise/set time.
* @return <code>Calendar</code> representation of the local time as a calendar, or null for none.
*/
private Calendar getLocalTimeAsCalendar(BigDecimal localTime, Calendar date) {
if (localTime == null)
protected Calendar getLocalTimeAsCalendar(BigDecimal localTimeParam, Calendar date) {
if (localTimeParam == null) {
return null;
}

// Create a clone of the input calendar so we get locale/timezone information.
Calendar resultTime = (Calendar) date.clone();

BigDecimal localTime = localTimeParam;
if (localTime.compareTo(BigDecimal.ZERO) == -1) {
localTime = localTime.add(BigDecimal.valueOf(24.0D));
resultTime.add(Calendar.HOUR_OF_DAY, -24);
}
String[] timeComponents = localTime.toPlainString().split("\\.");
int hour = Integer.parseInt(timeComponents[0]);

Expand All @@ -332,13 +352,15 @@ private Calendar getLocalTimeAsCalendar(BigDecimal localTime, Calendar date) {
minutes = BigDecimal.ZERO;
hour += 1;
}
if (hour == 24) {
hour = 0;
}

// Create a clone of the input calendar so we get locale/timezone information.
Calendar resultTime = (Calendar)date.clone();
// Set the local time
resultTime.set(Calendar.HOUR_OF_DAY, hour);
resultTime.set(Calendar.MINUTE, minutes.intValue());
resultTime.set(Calendar.SECOND, 0);
resultTime.setTimeZone(date.getTimeZone());

return resultTime;
}
Expand Down
4 changes: 2 additions & 2 deletions src/main/ruby/solardatacollector.rb
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,10 @@
# Takes a years worth of solar data and creates a CSV file from it.
# The data comes from http://www.cmpsolv.com/los/sunsetexp.html

output = File.new("../testdata/solardata.csv", "w")
output = File.new("../../../testdata/solardata.csv", "w")
month = 0

File.open("../testdata/solardata.txt", "r").grep(/(\d)+\s(([0-1][0-9]|[2][0-3]):([0-5][0-9])(\s)?)+/).each do |line|
File.open("../../../testdata/solardata.txt", "r").grep(/(\d)+\s(([0-1][0-9]|[2][0-3]):([0-5][0-9])(\s)?)+/).each do |line|
line.chop!()
line.gsub!(/\s(DAY)/, '99:99')
line.gsub!(/\s{2}/, ' ')
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,14 @@

package com.luckycatlabs.sunrisesunset;

import static org.junit.Assert.assertEquals;

import java.util.Calendar;

import org.junit.Before;
import org.junit.Test;

import com.luckycatlabs.sunrisesunset.dto.Location;
import com.luckycatlabs.sunrisesunset.util.BaseTestCase;

/**
Expand Down Expand Up @@ -74,4 +79,21 @@ public void testComputeOfficialSunrise() {
public void testComputeOfficialSunset() {
assertTimeEquals("18:00", calc.getOfficialSunsetForDate(eventDate), eventDate.getTime().toString());
}

@Test
public void testSpecificDateLocationAndTimezone() {
Location loc = new Location("55.03", "82.91");
SunriseSunsetCalculator calculator = new SunriseSunsetCalculator(loc, "GMT");

Calendar calendar = Calendar.getInstance();
calendar.set(2012, 4, 7);

String officialSunriseForDate = calculator.getOfficialSunriseForDate(calendar);
assertEquals("22:35", officialSunriseForDate);

Calendar officialSunriseCalendarForDate = calculator.getOfficialSunriseCalendarForDate(calendar);
assertEquals(22, officialSunriseCalendarForDate.get(Calendar.HOUR_OF_DAY));
assertEquals(35, officialSunriseCalendarForDate.get(Calendar.MINUTE));
assertEquals(6, officialSunriseCalendarForDate.get(Calendar.DAY_OF_MONTH));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,9 @@

import static org.junit.Assert.assertEquals;

import java.math.BigDecimal;
import java.util.Calendar;

import org.junit.Before;
import org.junit.Test;

Expand All @@ -37,12 +40,33 @@ public void setupCalculator() {
@Test
public void testComputeSunriseTime() {
String localSunriseTime = "07:05";
assertEquals(localSunriseTime, calc.computeSunriseTime(Zenith.CIVIL, this.eventDate));
assertEquals(localSunriseTime, calc.computeSunriseTime(Zenith.CIVIL, eventDate));
}

@Test
public void testComputeSunsetTime() {
String localSunsetTime = "18:28";
assertEquals(localSunsetTime, calc.computeSunsetTime(Zenith.CIVIL, this.eventDate));
assertEquals(localSunsetTime, calc.computeSunsetTime(Zenith.CIVIL, eventDate));
}

@Test
public void testGetLocalTimeAsCalendar() {
Calendar localTime = calc.getLocalTimeAsCalendar(BigDecimal.valueOf(15.5D), Calendar.getInstance());
assertEquals(15, localTime.get(Calendar.HOUR_OF_DAY));
assertEquals(30, localTime.get(Calendar.MINUTE));
}

@Test
public void testGetLocalTimeAsCalendarForZero() {
Calendar localTime = calc.getLocalTimeAsCalendar(BigDecimal.valueOf(0.0D), Calendar.getInstance());
assertEquals(0, localTime.get(Calendar.HOUR_OF_DAY));
assertEquals(0, localTime.get(Calendar.MINUTE));
}

@Test
public void testGetLocalTimeAsCalendarForNegative() {
Calendar localTime = calc.getLocalTimeAsCalendar(BigDecimal.valueOf(-10.0D), Calendar.getInstance());
assertEquals(14, localTime.get(Calendar.HOUR_OF_DAY));
assertEquals(0, localTime.get(Calendar.MINUTE));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,9 @@ protected String getMessage(Object expected, Object actual) {

private int getMinutes(String timeString) {
String[] timeParts = timeString.split("\\:");
if (timeParts[0].equals("00")) {
timeParts[0] = "24";
}
return (60 * Integer.valueOf(timeParts[0])) + Integer.valueOf(timeParts[1]);
}
}
Loading

0 comments on commit 68cf9b1

Please sign in to comment.