-
-
Notifications
You must be signed in to change notification settings - Fork 17
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
On day of time changes, the sunrise is off by 1 if the time is set to midnight #10
Comments
I've got a repro, and I think I've got a good idea for the fix. I'll try to get tests and a PR in the next day or two. The easiest work around in the meantime is to provide a Utc DateTime as input and convert after getting the results back. Treat the returned DateTime as Utc Repro when run on a system in United States Central Time: using Innovative.SolarCalculator;
var date = new DateTime(2022, 3, 10, 0, 0, 0, DateTimeKind.Unspecified);
var solarTimes = new SolarTimes(date, 44.927481, -93.306843);
var sunrise1 = solarTimes.Sunrise.ToUniversalTime();
Console.WriteLine($"sunrise for: {date} : {solarTimes.Sunrise} ({solarTimes.Sunrise.ToUniversalTime()})");
date = new DateTime(2022, 3, 11, 0, 0, 0, DateTimeKind.Unspecified);
solarTimes = new SolarTimes(date, 44.927481, -93.306843);
var sunrise2 = solarTimes.Sunrise.ToUniversalTime();
Console.WriteLine($"sunrise for: {date} : {solarTimes.Sunrise} ({solarTimes.Sunrise.ToUniversalTime()})");
date = new DateTime(2022, 3, 12, 0, 0, 0, DateTimeKind.Unspecified);
solarTimes = new SolarTimes(date, 44.927481, -93.306843);
var sunrise3 = solarTimes.Sunrise.ToUniversalTime();
Console.WriteLine($"sunrise for: {date} : {solarTimes.Sunrise} ({solarTimes.Sunrise.ToUniversalTime()})");
date = new DateTime(2022, 3, 13, 0, 0, 0, DateTimeKind.Unspecified);
solarTimes = new SolarTimes(date, 44.927481, -93.306843);
var sunrise4 = solarTimes.Sunrise.ToUniversalTime();
Console.WriteLine($"sunrise for: {date} : {solarTimes.Sunrise} ({solarTimes.Sunrise.ToUniversalTime()})");
date = new DateTime(2022, 3, 14, 0, 0, 0, DateTimeKind.Unspecified);
solarTimes = new SolarTimes(date, 44.927481, -93.306843);
var sunrise5 = solarTimes.Sunrise.ToUniversalTime();
Console.WriteLine($"sunrise for: {date} : {solarTimes.Sunrise} ({solarTimes.Sunrise.ToUniversalTime()})");
date = new DateTime(2022, 3, 15, 0, 0, 0, DateTimeKind.Unspecified);
solarTimes = new SolarTimes(date, 44.927481, -93.306843);
var sunrise6 = solarTimes.Sunrise.ToUniversalTime();
Console.WriteLine($"sunrise for: {date} : {solarTimes.Sunrise} ({solarTimes.Sunrise.ToUniversalTime()})");
// shows a jump back of one hour, and then a jump forward of one hour. This seems to be the described problem.
// one of those jumps (forward) is correct, as part of Daylight Saving
Console.WriteLine($"Sunrise2 is ~{((sunrise2 - sunrise1).TotalMinutes) - 1440:#0.##} difference from the day before.");
Console.WriteLine($"Sunrise3 is ~{((sunrise3 - sunrise2).TotalMinutes) - 1440:#0.##} difference from the day before.");
Console.WriteLine($"Sunrise4 is ~{((sunrise4 - sunrise3).TotalMinutes) - 1440:#0.##} difference from the day before.");
Console.WriteLine($"Sunrise5 is ~{((sunrise5 - sunrise4).TotalMinutes) - 1440:#0.##} difference from the day before.");
Console.WriteLine($"Sunrise6 is ~{((sunrise6 - sunrise5).TotalMinutes) - 1440:#0.##} difference from the day before.");
date = new DateTime(2022, 3, 10, 0, 0, 0, DateTimeKind.Utc);
solarTimes = new SolarTimes(date, 44.927481, -93.306843);
sunrise1 = solarTimes.Sunrise.ToUniversalTime();
Console.WriteLine($"sunrise for: {date} : {solarTimes.Sunrise} ({solarTimes.Sunrise.ToUniversalTime()})");
date = new DateTime(2022, 3, 11, 0, 0, 0, DateTimeKind.Utc);
solarTimes = new SolarTimes(date, 44.927481, -93.306843);
sunrise2 = solarTimes.Sunrise.ToUniversalTime();
Console.WriteLine($"sunrise for: {date} : {solarTimes.Sunrise} ({solarTimes.Sunrise.ToUniversalTime()})");
date = new DateTime(2022, 3, 12, 0, 0, 0, DateTimeKind.Utc);
solarTimes = new SolarTimes(date, 44.927481, -93.306843);
sunrise3 = solarTimes.Sunrise.ToUniversalTime();
Console.WriteLine($"sunrise for: {date} : {solarTimes.Sunrise} ({solarTimes.Sunrise.ToUniversalTime()})");
date = new DateTime(2022, 3, 13, 0, 0, 0, DateTimeKind.Utc);
solarTimes = new SolarTimes(date, 44.927481, -93.306843);
sunrise4 = solarTimes.Sunrise.ToUniversalTime();
Console.WriteLine($"sunrise for: {date} : {solarTimes.Sunrise} ({solarTimes.Sunrise.ToUniversalTime()})");
date = new DateTime(2022, 3, 14, 0, 0, 0, DateTimeKind.Utc);
solarTimes = new SolarTimes(date, 44.927481, -93.306843);
sunrise5 = solarTimes.Sunrise.ToUniversalTime();
Console.WriteLine($"sunrise for: {date} : {solarTimes.Sunrise} ({solarTimes.Sunrise.ToUniversalTime()})");
date = new DateTime(2022, 3, 15, 0, 0, 0, DateTimeKind.Utc);
solarTimes = new SolarTimes(date, 44.927481, -93.306843);
sunrise6 = solarTimes.Sunrise.ToUniversalTime();
Console.WriteLine($"sunrise for: {date} : {solarTimes.Sunrise} ({solarTimes.Sunrise.ToUniversalTime()})");
// shows correct times, UTC, but math shows jump since these are Unspecified Kind, should be UTC.
Console.WriteLine($"Sunrise2 is ~{((sunrise2 - sunrise1).TotalMinutes) - 1440:#0.##} difference from the day before.");
Console.WriteLine($"Sunrise3 is ~{((sunrise3 - sunrise2).TotalMinutes) - 1440:#0.##} difference from the day before.");
Console.WriteLine($"Sunrise4 is ~{((sunrise4 - sunrise3).TotalMinutes) - 1440:#0.##} difference from the day before.");
Console.WriteLine($"Sunrise5 is ~{((sunrise5 - sunrise4).TotalMinutes) - 1440:#0.##} difference from the day before.");
Console.WriteLine($"Sunrise6 is ~{((sunrise6 - sunrise5).TotalMinutes) - 1440:#0.##} difference from the day before.");
date = new DateTime(2022, 3, 10, 12, 0, 0, DateTimeKind.Unspecified);
solarTimes = new SolarTimes(date, 44.927481, -93.306843);
sunrise1 = solarTimes.Sunrise.ToUniversalTime();
Console.WriteLine($"sunrise for: {date} : {solarTimes.Sunrise} ({solarTimes.Sunrise.ToUniversalTime()})");
date = new DateTime(2022, 3, 11, 12, 0, 0, DateTimeKind.Unspecified);
solarTimes = new SolarTimes(date, 44.927481, -93.306843);
sunrise2 = solarTimes.Sunrise.ToUniversalTime();
Console.WriteLine($"sunrise for: {date} : {solarTimes.Sunrise} ({solarTimes.Sunrise.ToUniversalTime()})");
date = new DateTime(2022, 3, 12, 12, 0, 0, DateTimeKind.Unspecified);
solarTimes = new SolarTimes(date, 44.927481, -93.306843);
sunrise3 = solarTimes.Sunrise.ToUniversalTime();
Console.WriteLine($"sunrise for: {date} : {solarTimes.Sunrise} ({solarTimes.Sunrise.ToUniversalTime()})");
date = new DateTime(2022, 3, 13, 12, 0, 0, DateTimeKind.Unspecified);
solarTimes = new SolarTimes(date, 44.927481, -93.306843);
sunrise4 = solarTimes.Sunrise.ToUniversalTime();
Console.WriteLine($"sunrise for: {date} : {solarTimes.Sunrise} ({solarTimes.Sunrise.ToUniversalTime()})");
date = new DateTime(2022, 3, 14, 12, 0, 0, DateTimeKind.Unspecified);
solarTimes = new SolarTimes(date, 44.927481, -93.306843);
sunrise5 = solarTimes.Sunrise.ToUniversalTime();
Console.WriteLine($"sunrise for: {date} : {solarTimes.Sunrise} ({solarTimes.Sunrise.ToUniversalTime()})");
date = new DateTime(2022, 3, 15, 12, 0, 0, DateTimeKind.Unspecified);
solarTimes = new SolarTimes(date, 44.927481, -93.306843);
sunrise6 = solarTimes.Sunrise.ToUniversalTime();
Console.WriteLine($"sunrise for: {date} : {solarTimes.Sunrise} ({solarTimes.Sunrise.ToUniversalTime()})");
// Shows correct times, local to the sunrise.
Console.WriteLine($"Sunrise2 is ~{((sunrise2 - sunrise1).TotalMinutes) - 1440:#0.##} difference from the day before.");
Console.WriteLine($"Sunrise3 is ~{((sunrise3 - sunrise2).TotalMinutes) - 1440:#0.##} difference from the day before.");
Console.WriteLine($"Sunrise4 is ~{((sunrise4 - sunrise3).TotalMinutes) - 1440:#0.##} difference from the day before.");
Console.WriteLine($"Sunrise5 is ~{((sunrise5 - sunrise4).TotalMinutes) - 1440:#0.##} difference from the day before.");
Console.WriteLine($"Sunrise6 is ~{((sunrise6 - sunrise5).TotalMinutes) - 1440:#0.##} difference from the day before."); output:
|
If you don't need full exact date precision, you can just convert the library DateTime objects to TimeOnly objects taking into account that times across two days will require additional logic for range checking (sunrise hhmm > sunset hhmm) |
I noticed an issue that might be a bug, or at least something that I misunderstood from the examples provided in the README.
Example: We have a location in Berlin, Germany. We now want to calculate the sunrise for the following three days
The way I used the library, the correct sunrise/sunset was calculated for the day before and the day after, but not for the day of the winter time change.
For each case I created a DateTime with Kind
Unspecified
. So for the example of Oct 31:This calculates the wrong date, because at 00:00 the UTC offset is still 2. At 3:00 the UTC offset changes to 1. The offset is used in internal calculations, which I found out after debugging a while.
So as a workaround/fix, we are now always passing a DateTime set to noon (12:00).
Then it works very well.
In my mind that seems like a bug, because even if you are checking the sunrise/sunset of a day before 3:00 AM (e.g. via DateTime.Now), you should be able to get the correct sunrise/sunset for that day.
The above examples are a bit simplified from my real code and I didn't double check them, but the point is that some days have 2 valid UTC offsets, and if the wrong one is accidentally used, then the sunrise is off by 1.
Did I misunderstand something maybe, or might this be a bug?
The text was updated successfully, but these errors were encountered: