Skip to content
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

sunrise() / sunset() documentation #180

Closed
adokter opened this issue Dec 12, 2018 · 7 comments
Closed

sunrise() / sunset() documentation #180

adokter opened this issue Dec 12, 2018 · 7 comments
Milestone

Comments

@adokter
Copy link
Owner

adokter commented Dec 12, 2018

Need to clarify

  • that time is not taken into account
  • which date classes are accepted by this function
  • clearly distinguish between input time zone and output time zone, and how they affect the result
  • In certain timezones there is a transition to the next day during daytime - how does that affect the result
  • explain that NA is returned if there is no sunrise/sunset (arctic circle)

It seems like the crepuscule function assumes that the input date refers to the day in the local timezone of the given coordinates

This interpretation explains this example (output day is not necessarily the same as the input day)

sunset("2016-11-15", -98.41306, 45.45583)
# Gives next sunset, on same date
> "2016-11-15 22:59:16 UTC"

sunset("2016-03-04", -98.41306, 45.45583)
# Gives next sunset, on next date (occurs after midnight UTC)
> "2016-03-05 00:22:19 UTC"

Also explains this jump

# On the day of 6 Oct (local timezone) at this location, sunset is actually on the 7 Oct in UTC time zone, i.e. the next day in UTC timezone
> sunset("2016-10-6", -98.41306, 45.45583)
[1] "2016-10-07 00:00:14 UTC"

# On the day of 7 Oct (local timezone) at this location, sunset is also the 7 Oct in UTC time zone
> sunset("2016-10-7", -98.41306, 45.45583)
[1] "2016-10-07 23:58:22 UTC"
@adokter adokter added this to the 0.5.0 milestone Dec 12, 2018
@adokter adokter changed the title sunrise / sunset time documentation sunrise() / sunset() documentation Dec 12, 2018
@CeciliaNilsson709
Copy link
Collaborator

I think the key thing here is to make clear that crepuscule only works on date, not time, and always gives you the sunset at the end of the day (even if that has another date) and never a sunset at the start of the day. With different timezones this leads to some unexpected results in for example as.data.frame.

So a datetime stamp like this:

sunset("2016-03-04 00:12:14", -98.41306, 45.45583)
# Gives
> "2016-03-05 00:22:19 UTC"

and not what I would say is the "correct" sunset time for that measurement ("2016-03-04 00:20:57 UTC").

Since as.data.frame uses the sunset function to calculate a sunset per datetime, I think what is actually returned as sunset in the data frame is both unclear to the user (it is not the closest sunset nor the sunset on the same date), and, in some cases, it is wrong (as above).

@peterdesmet
Copy link
Collaborator

Would it be clearer if we could adapt the function so input/output is UTC?

  1. Date times (2016-03-04 00:12:14) in my dataframe are assumed UTC
  2. Uses that 2016-03-04 UTC date and selects the sunset within the 00:00 - 23:59 time window for that position.

Note that it looks like check_night() is already assuming a UTC date time as input:

# UTC midnight at a UTC position:
check_night("2016-03-04 00:00", 0, 45.45583)
[1] TRUE # 00:00 UTC => 00:00 UTC for that position

# UTC midnight for a GMT-6 position
check_night("2016-03-04 00:00", -98.41306, 45.45583)
[1] FALSE # 00:00 UTC => 2016-03-03 18:00 local GMT-6 for that position

# Other UTC timestamps for that GMT-6 position
check_night("2016-03-04 06:00", -98.41306, 45.45583)
[1] TRUE # 06:00 UTC => 00:00 local GMT-6
check_night("2016-03-04 12:00", -98.41306, 45.45583)
[1] TRUE # 12:00 UTC => 06:00 local GMT-6
check_night("2016-03-04 18:00", -98.41306, 45.45583)
[1] FALSE # 18:00 UTC => 12:00 local GMT-6

@CeciliaNilsson709
Copy link
Collaborator

No, that's not the issue, all input and outputs are already in UTC.

The problem is:

  1. crepuscule (used inside sunrise/sunset) only takes date, not time, into account

and

  1. crepuscule returns the (intuitively correct) sunset at the end of the "day", even if that is on the next date (it probably disregards sunsets before noon, or uses date as local date as Adriaan suggested).

Together these two things mean that if you give it a date and time (in UTC) you don't always get the response you expect. You can see this in my example above, where the measurement (2016-03-04 00:12:14) takes place just before sunset, but it returns not the sunset that occurs 8 minuts later on the same date (2016-03-04 00:20:57), but instead the sunset of the next date, 24h and 10m later (2016-03-05 00:22:19).

We either need to fix this in sunrise/sunset (maybe by using some of the twisting of dates that already happens in check_night and that seem to magically work 🤷‍♀️), or not use sunrise/sunset in that way (it is now used like that in as.data.frame).

This is not a high priority thing, but would be good to keep track of it and fix once there is time...

@adokter adokter modified the milestones: 0.5.0, 0.6.0 Oct 4, 2019
@adokter
Copy link
Owner Author

adokter commented Apr 6, 2020

It gets more confusing:

sunset("2016-03-04", -100, 45)
> "2016-03-05 00:29:02 UTC"
# i.e. sunset on 2016-03-04 falls on the next day in UTC

sunrise("2016-11-01", 102, 45)
> "2016-10-31 23:53:50 UTC"
# i.e. sunrise on 2016-11-01 falls on the previous day in UTC

Why jump forward a day in the first case, and backward a day in the second case?

Differences of the input datetime in various time zones do not give clues as to why:

# 2016-03-04 00:00 UTC in local time zone:
as_datetime(as_datetime("2016-03-04",tz="UTC"),tz=tz_lookup_coords(45,-100, method="accurate"))
> "2016-03-03 18:00:00 CST"

# 2016-03-04 00:00 UTC in local time zone:
as_datetime(as_datetime("2016-03-04",tz="UTC"),tz=tz_lookup_coords(45,-100, method="accurate"))
> "2016-03-04 06:00:00 UTC"

# 2016-11-01 00:00 UTC in local time zone:
as_datetime(as_datetime("2016-11-01",tz="UTC"),tz=tz_lookup_coords(45,102, method="accurate"))
> "2016-11-01 08:00:00 +08"

# 2016-11-01 00:00 local time zone in UTC:
as_datetime(as_datetime("2016-11-01",tz=tz_lookup_coords(45,102, method="accurate")), tz="UTC")
"2016-10-31 16:00:00 UTC"

Also there is continuity along longitude, and we can change the output date by adding 360 degrees:

> sunset("2016-03-04", -100, 45)
[1] "2016-03-05 00:29:02 UTC"
> sunset("2016-03-04", -100+360, 45)
[1] "2016-03-04 00:27:42 UTC"

Do not understand the underlying function maptools::crepuscule()...

@adokter
Copy link
Owner Author

adokter commented Apr 6, 2020

Sunrise and sunset are calculated relative to the solar noon of the input date. Therefore, sunrises can fall a day earlier, and sunsets can fall a day later.

solar noon sunset example: 2016-03-04 18:51:32
solar noon sunrise example: 2016-11-01 04:55:32

@adokter
Copy link
Owner Author

adokter commented Apr 7, 2020

Add the option force_tz which converts the input date first to the desired timezone prior to calculating sunrise/sunset, and forces the output to the specified timezone (UTC by default), see commit 4968019

adokter added a commit that referenced this issue Apr 7, 2020
@adokter
Copy link
Owner Author

adokter commented Apr 7, 2020

fixed by 56a1f29

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants