Search code examples
rdateposix

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"

Solution

  • 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.