user11740857
user11740857

Reputation: 480

Extract previous specific day based on date

Is there a specific way to extract specific day based on the date passed. Example if the user pass Sys.Date(), the user should get the previous date which was saturday. In case if today is Saturday, the user should get today's date itself since it is saturday

> Sys.Date()
[1] "2021-02-11"

Here I need what is the date on the previous Saturday of this date(today). SO the expected output is below which is Saturaday

[1] "2021-02-06" 

In Case if

Upvotes: 1

Views: 564

Answers (3)

GKi
GKi

Reputation: 39667

You can try:

x <- as.Date("2021-02-11")
x - 8 + which(format(seq(x - 7, by=1, length.out = 7), "%u") == 6)
#x - 8 + which(format(seq(x - 7, by=1, length.out = 7), "%a") == "Sat") #Alternative depending on locale
#[1] "2021-02-06"

Or if the current day counts already:

x <- as.Date("2021-02-06")
x - 7 + which(format(seq(x - 6, by=1, length.out = 7), "%u") == 6)
#[1] "2021-02-06"

Or maybe:

x <- seq(as.Date("2021-02-04"), by=1, length.out = 7)
x - rep(0:6, 2)[as.integer(format(x, "%u"))+2]
#[1] "2021-01-30" "2021-01-30" "2021-02-06" "2021-02-06" "2021-02-06"
#[6] "2021-02-06" "2021-02-06"

Or with a lookup vector:

x <- seq(as.Date("2021-02-04"), by=1, length.out = 7)
LU <- c(2:6, 0:1)
x - LU[as.integer(format(x, "%u"))]
#[1] "2021-01-30" "2021-01-30" "2021-02-06" "2021-02-06" "2021-02-06"
#[6] "2021-02-06" "2021-02-06"

Upvotes: 1

G. Grothendieck
G. Grothendieck

Reputation: 269634

The following is based on a formula given in one of the zoo package vignettes but does not depend on that package or any other package.

Suppose x is a vector of Date class and d is a day of the week where Sunday = 0, Monday = 1 and so on. Then

X0 <- as.Date(d - 4, origin = "1970-01-01")

falls on day of the week d so we can count how many weeks since then including any fraction of a week and then round down and multiply by 7 adding that to X0 to get the prior Date falling on day of the week d (or x if it is already that day of the week).

Thus if an element of Date class vector x is on day of the week d then the following returns x for that element and otherwise it gives the prior Date on that day of the week.

Regarding the code, if zoo is loaded then the origin= argument could optionally be omitted.

No packages are used, the function is vectorized so x may be a Date vector and not just a single Date and there is no dependence on locale or time zone.

# x is Date vector, d is weekday where 0 = Sun, 1 = Mon, etc.
prev <- function(x, d = 0) 7 * floor(as.numeric(x - d + 4) / 7) + 
  as.Date(d - 4, origin = "1970-01-01")

Using Saturday, i.e. day of the week 6, as an example,

x <- as.Date("2000-01-08") + 0:8
x
## [1] "2000-01-08" "2000-01-09" "2000-01-10" "2000-01-11" "2000-01-12"
## [6] "2000-01-13" "2000-01-14" "2000-01-15" "2000-01-16"

weekdays(x)
## [1] "Saturday"  "Sunday"    "Monday"    "Tuesday"   "Wednesday" "Thursday" 
## [7] "Friday"    "Saturday"  "Sunday"   

p <- prev(x, 6)  # 6 means Saturday
p
## [1] "2000-01-08" "2000-01-08" "2000-01-08" "2000-01-08" "2000-01-08"
## [6] "2000-01-08" "2000-01-08" "2000-01-15" "2000-01-15"

weekdays(p)
## [1] "Saturday" "Saturday" "Saturday" "Saturday" "Saturday" "Saturday" "Saturday"
## [8] "Saturday" "Saturday"

Upvotes: 1

user10917479
user10917479

Reputation:

You can use floor_date() from lubridate. Note that your day of the week may be regional, so 6 may or may not be Saturday for everybody (but you can set the week_start optional argument).

library(lubridate)

x <- as.Date("2021-02-06")
floor_date(x, "week", 6)
# [1] "2021-02-06"

x <- Sys.Date()
floor_date(x, "week", 6)
# [1] "2021-02-06"

Upvotes: 2

Related Questions