Skip to content

Instantly share code, notes, and snippets.

@carpodaster
Created October 25, 2018 10:07
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save carpodaster/71eee0a205f78917576540c052b39f29 to your computer and use it in GitHub Desktop.
Save carpodaster/71eee0a205f78917576540c052b39f29 to your computer and use it in GitHub Desktop.
Maybe date monad
# frozen_string_literal: true
require 'minitest/autorun'
require 'date'
class MaybeDate < SimpleDelegator
include Comparable
def initialize(date = nil, default: 9999)
date = begin
Date.parse(date.to_s)
rescue ArgumentError
Date.new(default)
end
super(date)
end
def <=>(other)
other = self.class.new(other) unless other.is_a? self.class
self.__getobj__ <=> other.__getobj__
end
end
class MaybeFutureDate < MaybeDate
def initialize(*args)
super(*args, default: 9999)
end
end
class MaybePastDate < MaybeDate
def initialize(*args)
super(*args, default: 0)
end
end
describe MaybeDate do
describe "its constructor" do
it "returns a Date-like object when passed a real date" do
subject = MaybeDate.new(Date.today)
subject.must_be_kind_of Date
end
it "parses a compatible string and returns a Date-like object" do
subject = MaybeDate.new("2018-12-31")
subject.must_equal Date.new(2018, 12, 31)
end
it "parses an incompatible string and returns a Date-like object" do
subject = MaybeDate.new("No, definitely not")
subject.must_be_kind_of Date
end
it "accepts nil and returns a Date-like object" do
subject = MaybeDate.new(nil)
subject.must_be_kind_of Date
end
it "does not require an argument to return a Date-like object" do
subject = MaybeDate.new
subject.must_be_kind_of Date
end
end
describe "comparision" do
it "can be sorted by underlying date" do
d1 = MaybeDate.new("2017-12-23")
d2 = MaybeDate.new(Date.new(2010, 7, 4))
d3 = MaybeDate.new("2016-10-03")
[d1, d2, d3].sort.must_equal [d2, d3, d1]
end
it "can be compared to a date" do
d1 = MaybeDate.new("2017-12-23")
d2 = Date.new(2018, 7, 4)
(d1 < d2).must_equal true
end
it "returns a 'future' date by default" do
d1 = MaybeDate.new
d2 = Date.new(2010, 7, 4)
(d1 > d2).must_equal true
end
it "returns a 'past' date optionally" do
d1 = MaybeDate.new(default: 0)
d2 = Date.new(2010, 7, 4)
(d1 > d2).must_equal false
end
end
end
describe MaybeFutureDate do
it "is in the future" do
(MaybeFutureDate.new > Date.today).must_equal true
end
end
describe MaybePastDate do
it "is in the past" do
(MaybePastDate.new > Date.today).must_equal false
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment