Rappster
Rappster

Reputation: 13070

POSIX date from dates in weekly time format

I have dates encoded in a weekly time format (European convention >> 01 through 52/53, e.g. "2016-48") and would like to standardize them to a POSIX date:

require(magrittr)
(x <- as.POSIXct("2016-12-01") %>% format("%Y-%V"))
# [1] "2016-48"
as.POSIXct(x, format = "%Y-%V")
# [1] "2016-01-11 CET"

I expected the last statement to return "2016-12-01" again. What am I missing here?


Edit

Thanks to Dirk, I was able to piece it together:

y <- sprintf("%s-1", x)

While I still don't get why this doesn't work

(as.POSIXct(y, format = "%Y-%V-%u"))
# [1] "2016-01-11 CET"

this does

(as.POSIXct(y, format = "%Y-%U-%u")
# [1] "2016-11-28 CET"

Edit 2

Oh my, I think using %V is a very bad idea in general:

as.POSIXct("2016-01-01") %>% format("%Y-%V")
# [1] "2016-53"

Should this be considered to be on a "serious bug" level that requires further action?!

Sticking to either %U or %W seems to be the right way to go

as.POSIXct("2016-01-01") %>% format("%Y-%U")
# [1] "2016-00"

Edit 3

Nope, not quite finished/still puzzled: the approach doesn't work for the very first week

(x <- as.POSIXct("2016-01-01") %>% format("%Y-%W"))
# [1] "2016-00"

as.POSIXct(sprintf("%s-1", x), format = "%Y-%W-%u")
# [1] NA

It does for week 01 as defined in the underlying convention when using %U or %W (so "week 2", actually)

as.POSIXct("2016-01-1", format = "%Y-%W-%u")
# [1] "2016-01-04 CET"

Upvotes: 3

Views: 591

Answers (1)

Uwe
Uwe

Reputation: 42544

As I have to deal a lot with reporting by ISO weeks, I've created the ISOweek package some years ago.

The package includes the function ISOweek2date() which returns the date of a given weekdate (year, week of the year, day of week according to ISO 8601). It's the inverse function to date2ISOweek().

With ISOweek, your examples become:

library(ISOweek)

# define dates to convert
dates <- as.Date(c("2016-12-01", "2016-01-01"))

# convert to full ISO 8601 week-based date yyyy-Www-d
(week_dates <- date2ISOweek(dates))
[1] "2016-W48-4" "2015-W53-5"
# convert back to class Date 
ISOweek2date(week_dates)
[1] "2016-12-01" "2016-01-01"

Note that date2ISOweek() requires a full ISO week-based date in the format yyyy-Www-d including the day of the week (1 to 7, Monday to Sunday).

So, if you only have year and ISO week number you have to create a character string with a day of the week specified.

A typical phrase in many reports is, e.g., "reporting week 31 ending 2017-08-06":h

yr <- 2017
wk <- 31
ISOweek2date(sprintf("%4i-W%02i-%1i", yr, wk, 7))
 [1] "2017-08-06"

Addendum

Please, see this answer for another use case and more background information on the ISOweek package.

Upvotes: 3

Related Questions