adokter / bioRad

R package for analysis and visualisation of biological signals in weather radar data
http://adokter.github.io/bioRad
Other
28 stars 16 forks source link

sunrise sunset conflict with tibble #657

Closed grapemanJac closed 2 months ago

grapemanJac commented 3 months ago

I'm bald - now! I've been tearing my hair out for the best part of two days trying to sort out why these functions were returning values that were a day behind and as at UTC rather than UTC + 8 (thus a day and 8 hours). The problem seems to arise from constraints tibble applies to dates and in particular to timezones. I resolved the problems, finally, by working with data.frame() rather than tibble(). I might try data.table() which I will do if my files get too large. The timezone is that in which I am located. Had thought this would be simple but!!!

I imagine the problem arose in 'suntools' who imported script from 'maptools' (now retired). The scripts were built prior to the development of tibble.

I realise this is a tiny part of your package but it presents the output in a much more useable format than suntools

#This doesn't work:
dat <- tibble(Date = seq(as.POSIXct("2023-08-01 00:00:00",
                                    format = "%Y-%m-%d 00:00:00",
                                    tz = "Australia/Perth",
                                    force_tz = TRUE),
                         as.POSIXct("2023-08-05 00:00:00",
                                    format = "%Y-%m-%d 00:00:00",
                                    tz = "Australia/Perth",
                                    force_tz = TRUE),
                         by = '1 day'))
dat
x <- dat[1,1]
x
tz(x)

#bioRad - default tz
dat <- dat %>% mutate(Sunrise = bioRad::sunrise(Date, lon = 122.48, lat = -17.846),
                      Sunset = bioRad::sunset(Date, lon = 122.48, lat = -17.846))
dat

dat <- dat %>% mutate(diffSR = Sunrise +as.POSIXct("00-00-01 00:00:00"),
                      diffSS = Sunset + as.POSIXct("00-00-01 00:00:00"))

#This does
dat <- data.frame(Date = seq(as.POSIXct("2023-08-01 00:00:00",
                                    format = "%Y-%m-%d 00:00:00",
                                    tz = "Australia/Perth",
                                    force_tz = TRUE),
                         as.POSIXct("2023-08-05 00:00:00",
                                    format = "%Y-%m-%d 00:00:00",
                                    tz = "Australia/Perth",
                                    force_tz = TRUE),
                         by = '1 day'))
dat
x <- dat[1,1]
x
tz(x)

dat <- dat %>% mutate(Sunrise = bioRad::sunrise(Date, lon = 122.48, lat = -17.846,
                                            tz = "Australia/Perth", force_tz = TRUE),
                      Sunset = bioRad::sunset(Date, lon = 122.48, lat = -17.846,
                                            tz = "Australia/Perth", force_tz = TRUE))
dat

Kind Regards

jac john.considine@uwa.edu.au

peterdesmet commented 3 months ago

Not familiar with this issue, but if bioRad provides a more sensible output than suntools, than it might be good to update suntools. @adokter or @pieterH, could you look into this and potentially transfer this issue to https://github.com/adokter/suntools/issues?

adokter commented 2 months ago

@iskandari could you look into this and the suggestion by @peterdesmet of transfering to suntools?

iskandari commented 2 months ago

@grapemanJac thanks for highlighting this nuance with tibbles, which I just found out are actually just lists:

 typeof(dat)
[1] "list"

You are not able to extract a timezone using lubridate::tz() because you are passing a tibble object instead of a POSIXct object, so you have to go one level deeper:

dat <- tibble(Date = seq(as.POSIXct("2023-08-01 00:00:00",
                                    format = "%Y-%m-%d 00:00:00",
                                    tz = "Australia/Perth",
                                    force_tz = TRUE),
                         as.POSIXct("2023-08-05 00:00:00",
                                    format = "%Y-%m-%d 00:00:00",
                                    tz = "Australia/Perth",
                                    force_tz = TRUE),
                         by = '1 day'))

tz(dat[1,1])
[1] "UTC"
Warning message:
tz(): Don't know how to compute timezone for object of class tbl_df/tbl/data.frame; returning "UTC"

For example, any of these work:

tz(dat$Date)
[1] "Australia/Perth"

dat[1,1]$Date
[1] "2023-08-01 AWST"

tz(dat[1,1]$Date)
[1] "Australia/Perth"

tz(dat$Date[1])
[1] "Australia/Perth"

So this can be easily remedied in dplyr::mutate() by extracting the tz directly from the Date vector:

#Roebuck, AU

dat <- dat %>% mutate(Sunrise = bioRad::sunrise(Date, lon = 122.48, lat = -17.846, tz=tz(Date), force_tz = TRUE),
                      Sunset = bioRad::sunset(Date, lon = 122.48, lat = -17.846, tz=tz(Date), force_tz = TRUE))

dat
# A tibble: 5 × 3
  Date                Sunrise             Sunset             
  <dttm>              <dttm>              <dttm>             
1 2023-08-01 00:00:00 2023-08-01 06:19:31 2023-08-01 17:33:35
2 2023-08-02 00:00:00 2023-08-02 06:19:06 2023-08-02 17:33:52
3 2023-08-03 00:00:00 2023-08-03 06:18:40 2023-08-03 17:34:10
4 2023-08-04 00:00:00 2023-08-04 06:18:13 2023-08-04 17:34:27
5 2023-08-05 00:00:00 2023-08-05 06:17:45 2023-08-05 17:34:44