noname
noname

Reputation: 369

How to get ISO week numbers from date

I would like to get the ISO week number from a given date in string format, where Monday is the first day of the week, and the week that contains the first Thursday of the year is considered to be the first week.

From other answers, I think strftime("2017-11-18", format = "%V") suits my purpose the best. However it doesn't work on Windows.

Any suggestions for alternatives with only the base package in R?

Upvotes: 2

Views: 10207

Answers (5)

Ward Weistra
Ward Weistra

Reputation: 68

The Python datetime library has a native function for getting ISO year, week number and week day: https://docs.python.org/3/library/datetime.html#datetime.date.isocalendar. It returns a tuple with all three values, so just select the second element if you want to have the week number only.

Example:

from datetime import datetime

// Create a datetime object from your string
my_date = datetime.strptime('2017-11-18', '%Y-%m-%d')
// Get the tuple of ISO date values from your datetime object
my_iso_tuple = my_date.isocalendar()
// Get the ISO week number
my_iso_week_number = my_iso_tuple[1]

Upvotes: 1

MichaelChirico
MichaelChirico

Reputation: 34703

data.table has an implementation of isoweek which you might want to just port (it's easy to replicate with base functionality)

# data.table approach:
isoweek <- function(x) {
  x = as.IDate(x)   # number of days since 1 Jan 1970 (a Thurs)
  nearest_thurs = as.IDate(7L * (as.integer(x + 3L) %/% 7L))
  year_start <- as.IDate(format(nearest_thurs, '%Y-01-01'))
  1L + (nearest_thurs - year_start) %/% 7L
}

Ported to be strictly base:

isoweek <- function(x) {
  x = as.Date(x)   # number of days since 1 Jan 1970 (a Thurs)
  nearest_thurs = as.Date(7L * (as.integer(x + 3L) %/% 7L), origin = '1970-01-01')
  year_start <- as.Date(format(nearest_thurs, '%Y-01-01'))
  1L + (nearest_thurs - year_start) %/% 7L
}

Upvotes: 2

Bertil Baron
Bertil Baron

Reputation: 5003

Use the package lubridate

it has a function isoweek()which gives you the ISOWeek of a given date

lubridate::isoweek("2017-11-18")
[1] 46

Now you just want to use the base packege. Here ist the code from lubridate for the ISO week

function (x) 
{
  xday <- make_datetime(year(x), month(x), day(x))
  dn <- 1 + (wday(x) + 5)%%7
  nth <- xday + ddays(4 - dn)
  jan1 <- make_datetime(year(nth), 1, 1)
  1L + as.integer(difftime(nth, jan1, units = "days"))%/%7L
}

we can take that an make it to something which only uses the base package.

myIsoweek <- function (x) 
{
  dateList <- as.list(strsplit(as.character(as.Date(x)),split = "-")[[1]])
  names(dateList) <- c("year","month","day")

  weekday <- as.POSIXlt(x)[["wday"]] + 1

  xday <- ISOdate(dateList$year, dateList$month, dateList$day)
  dn <- 1 + (weekday + 5)%%7
  nth <- xday + 86400*(4 - dn)
  jan1 <- ISOdate(format(nth,format = "%Y"), 1, 1)
  1L + as.integer(difftime(nth, jan1, units = "days"))%/%7L
}

Upvotes: 4

Smiley Bcc
Smiley Bcc

Reputation: 134

This should work

format(as.Date("2017-02-015"),"%W")

Upvotes: 0

Cihan
Cihan

Reputation: 2307

I believe strftime("2017-11-18", format = "%W") should work in Windows.

Upvotes: 1

Related Questions