Skip to content

Instantly share code, notes, and snippets.

@henrik

henrik/month.rb

Last active Jan 12, 2018
Embed
What would you like to do?
Ruby Month class.
require "attr_extras" # gem
class Month
vattr_initialize :year, :month_number
def self.from(object)
case object
when Month then object
else new(object.year, object.month)
end
end
# Relies on Rails' Time.zone.
def self.now
from(Time.zone.now)
end
def first_date
Date.new(year, month_number, 1)
end
def last_date
Date.new(year, month_number, -1)
end
def last_day
last_date.day
end
def date_for_day(number)
Date.new(year, month_number, number)
end
def previous
self.class.from(first_date - 1)
end
def next
self.class.from(last_date + 1)
end
end
require "spec_helper"
describe Month do
it "has value object equality" do
expect(Month.new(2014, 6)).to eq Month.new(2014, 6)
end
end
describe Month, ".from" do
it "builds a Month from a Date" do
month = Month.from(Date.new(2014, 6, 1))
expect(month).to eq Month.new(2014, 6)
end
it "builds a Month from a Time" do
month = Month.from(Time.zone.local(2014, 6, 1, 0, 0, 0))
expect(month).to eq Month.new(2014, 6)
end
it "returns the input when given a Month, since it's a value object" do
month = Month.from(Month.new(2014, 6))
expect(month).to eq Month.new(2014, 6)
end
end
describe Month, ".now" do
it "is the current month" do
Timecop.freeze(Time.zone.local(2014, 1, 1, 0, 0, 0)) do
expect(Month.now).to eq Month.new(2014, 1)
end
end
end
describe Month, "#first_date" do
it "is the first date of the month" do
month = Month.new(2014, 2)
expect(month.first_date).to eq Date.new(2014, 2, 1)
end
end
describe Month, "#last_date" do
it "is the last date of the month" do
month = Month.new(2014, 2)
expect(month.last_date).to eq Date.new(2014, 2, 28)
end
end
describe Month, "#last_day" do
it "is the last day number of the month" do
month = Month.new(2014, 2)
expect(month.last_day).to eq 28
end
end
describe Month, "#date_for_day" do
it "gives you such a date" do
date = Month.new(2014, 1).date_for_day(2)
expect(date).to eq Date.new(2014, 1, 2)
end
end
describe Month, "#previous" do
it "is the previous month" do
month = Month.new(2014, 2)
expect(month.previous).to eq Month.new(2014, 1)
expect(month.previous.previous).to eq Month.new(2013, 12)
end
end
describe Month, "#next" do
it "is the next month" do
month = Month.new(2013, 11)
expect(month.next).to eq Month.new(2013, 12)
expect(month.next.next).to eq Month.new(2014, 1)
end
end
@dasch

This comment has been minimized.

Copy link

@dasch dasch commented Jul 2, 2014

If you use pred and succ rather than previous and next you'll get range support for free...

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment