Calculate Julian Day based on a different reference day

77 Views Asked by At

My purpose is to calculate Julian Day based on a new reference, meaning that Julian Day 1 now will correspond to June 1st and Julian Day 366 to January 1st.

Hello everyone,

I've been struggling to calculate Julian Day where the reference day is not January 1st anymore. Indeed, I want to extract from my data Julian Day where June 1st correspond to 1 and January 1st to 366.

I tried to add 152 to Julian Day calculated with January 1st as a reference however my data than exceed 366 and I don't think it's the exact solution.

I'm really confused and know it's about mathematical suite but I'm not comfortable with it.

If you could help me I would be very grateful :)

1

There are 1 best solutions below

1
r2evans On

Under the assumption that you meant May 31 instead of Jan 1, then a perhaps-convoluted method could start with:

set.seed(42)
dates <- sort(as.Date("2020-06-01") + c(-1, 0, sample(1000, size=5)))
dates
# [1] "2020-05-31" "2020-06-01" "2020-08-14" "2020-11-01" "2021-04-18" "2021-12-14" "2023-02-23"
june1s <- as.POSIXlt(paste0(substring(dates, 1, 4), "-06-01"))
june1s
# [1] "2020-06-01 EDT" "2020-06-01 EDT" "2020-06-01 EDT" "2020-06-01 EDT" "2021-06-01 EDT" "2021-06-01 EDT"
# [7] "2023-06-01 EDT"
june1s$year <- june1s$year - (as.Date(june1s) > dates)
dates - as.Date(june1s) + 1L
# Time differences in days
# [1] 366   1  75 154 322 197 268
as.numeric(dates - as.Date(june1s) + 1L, units = "days")
# [1] 366   1  75 154 322 197 268

I included 05-31 and 06-01 to demonstrate the two extremes of the June-1-based-julian-year. The last step (as.numeric) is mostly a defensive habit of mine: difftime and similar functions often auto-change the units based on the scale of the difference, and that might be problematic; using units="days" forces this. (There are other ways to deal with this, as well.)

One can functionize this with:

myjulian <- function(dates, origin = "-01-01") {
  if (!inherits(dates, "Date")) dates <- as.Date(dates)
  origins <- as.POSIXlt(paste0(substring(dates, 1, 4), origin))
  origins$year <- origins$year - (as.Date(origins) > dates)
  as.numeric(dates - as.Date(origins) + 1L, units = "days")
}

With brief validation:

myjulian("2023-06-01") # jan-1
# [1] 152
format(as.Date("2023-06-01"), format = "%j")
# [1] "152"

myjulian("2023-06-01", origin = "-06-01")
# [1] 1