Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Counting days of the year with leap years

I am currently trying to code this in R. I would like to take a date that I have in %Y-%m-%d (ex: 2017-12-31) format and convert it to the day of the year. However, I would like it to always count 02/28 as day #59 and 03/01 as day #61. When it is not a leap year, it will just skip #60. This way, 01/01 is always #1 and 12/31 is always #366.

I have already tried using strftime() and yday(), but both of those do not skip day #60 when it is a leap year. It will just make 12/31 be day #365 or #366 depending on if it is a leap year or not.

If anyone has any insight on how I could code this in R, that would be great! Thank you so much.

file <- read.table("PATHTOMYFILE", fill = TRUE, header = TRUE)
file <- file[-c(1), ]
file$datetime <- as.Date(as.character(file$datetime))
file <- file[which(file$datetime <= as.Date("2017-09-30")), ]
file$x <- file[, 4]
file$x <- as.numeric(as.character(file$x))

# Year-day function
yearday <- function(d){
# Count previous months
yd <- ifelse(lubridate::month(d) > 1, sum(lubridate::days_in_month(1: 
(lubridate::month(d)-1))), 0)

# Add days so far in month & extra day if after February
yd <- yd + lubridate::day(d) + ifelse(lubridate::month(d)>2, 1, 0)
yd
}

file$Day <- yearday(as.Date((file$datetime), format = "%Y-%m-%d"))
like image 577
Sarah Avatar asked Oct 28 '22 18:10

Sarah


2 Answers

One option would be to use this function:

How to account for leap years?

leap_year <- function(year) {
  return(ifelse((year %%4 == 0 & year %%100 != 0) | year %%400 == 0, TRUE, FALSE))
}

Then write some code that manipulates the day number you have based on your rules (e.g. in a leap year

 if(leap_year(mydate)== TRUE & day_num>60) {
 day_num + 1} else{
  day_num}
like image 200
MDEWITT Avatar answered Oct 31 '22 09:10

MDEWITT


You could use the lubridate's leap_year function. E.g.,

library(lubridate)
dates <- c(as.Date("2017-12-31"), as.Date("2016-12-31"))
y <- as.Date("2016-12-31")
z <- as.Date("2017-12-31")
leap_every_year <- function(x) {
   ifelse(yday(x) > 59 & leap_year(x) == FALSE, yday(x) + 1, yday(x))
}
leap_every_year(y)
[1] 366
leap_every_year(z)
[1] 366
leap_every_year(dates)
[1] 366 366

EDIT: saw this was very similar to @MDEWITT's solution but it uses lubridate instead. Similar ideas though. Good luck!

like image 37
Andrew Avatar answered Oct 31 '22 08:10

Andrew