Created
October 25, 2018 10:07
-
-
Save carpodaster/71eee0a205f78917576540c052b39f29 to your computer and use it in GitHub Desktop.
Maybe date monad
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# 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