I work at a university library, and when I analyse data I like to arrange things by academic year (September to August) so I often need to find the academic year for a given date. Here are Ruby and R functions I made to do that. Both are pretty simple—they could be better, I’m sure, but they’re good enough for now. They use the same method: subtract eight months and then find the year you’re in.
The Ruby is the shortest, and uses the Date class. First, subtract eight months, with <<
.
d « n: Returns a date object pointing n months before self. The n should be a numeric value.
Rather cryptic. Then we find the year with .year
, which is pretty clear. This is the function:
Example:
> academic_year("2016-09-22")
=> 2016
The function is very short because Ruby nicely handles leap years and months of varying lengths. What is 30 October 2015 - eight months?
> Date.parse("2015-10-30") << 8
=> #<Date: 2015-02-28 ((2457082j,0s,0n),+0s,2299161j)>
2016 is a leap year—what is 30 October 2016 - eight months?
> Date.parse("2016-10-30") << 8
=> #<Date: 2016-02-29 ((2457448j,0s,0n),+0s,2299161j)>
Sensible. And the function returns a number (a Fixnum), not a string, which is what I want.
In R things are more complicated. How to subtract months from a date in R? gives a few answers, but none are pretty. Using lubridate makes things much easier (and besides, I use lubridate
in pretty much everything anyway).
Example:
> academic_year("2016-09-22")
[1] 2016
The floor_date
function gets called twice, the first time to drop back to the start of the month, which avoids R’s problems dealing with leap years:
> as.Date("2016-10-30") - months(8)
[1] NA
But you can always subtract 8 months from the first of a month. Then the function goes to 01 January of that year, pulls out just the year (“%Y”) and returns it as an integer. I’m sure it could be faster.
And once the academic year is identified, when making charts it’s nice to have September–August on the x axis. I often do something like this, with a data frame called data
that has a date
column:
Finding the academic year of a date could be a code golf thing, but Stack Overflow has too many rules.