Skip to content

Instantly share code, notes, and snippets.

@wacko wacko/short_date.rb
Last active Jan 3, 2020

Embed
What would you like to do?
Class to represent a short date (MM/DD), without the year component
require 'date'
class ShortDate
attr_reader :month, :day
include Comparable
def initialize(string)
date = Date.strptime(string, '%m/%d')
@month, @day = date.month, date.day
rescue StandardError
end
def ==(other_day)
month == other_day.month && day == other_day.day
end
def <=>(other_day)
if month == other_day.month
day <=> other_day.day
else
month <=> other_day.month
end
end
def to_s
'%02u/%02u' % [month, day] if month && day
end
def valid?
@month && @day
end
end
require 'spec_helper'
require './lib/short_date'
RSpec.describe ShortDate do
it 'has day and month attributes' do
date = ShortDate.new("1/2")
expect(date.month).to eq 1
expect(date.day).to eq 2
end
it 'can be converted to a string' do
expect(ShortDate.new("10/11").to_s).to eq '10/11'
# invalid dates
expect(ShortDate.new("20/20").to_s).to be_nil
end
it 'is comparabable' do
# when date1.month < date2.month
expect(ShortDate.new("1/2")).to be <= ShortDate.new("2/1")
expect(ShortDate.new("1/2")).to be <= ShortDate.new("2/2")
expect(ShortDate.new("1/2")).to be <= ShortDate.new("2/3")
# when date1.month == date2.month
expect(ShortDate.new("2/2")).to be >= ShortDate.new("2/1")
expect(ShortDate.new("2/2")).to be == ShortDate.new("2/2")
expect(ShortDate.new("2/2")).to be <= ShortDate.new("2/3")
# when date1.month > date2.month
expect(ShortDate.new("3/2")).to be >= ShortDate.new("2/1")
expect(ShortDate.new("3/2")).to be >= ShortDate.new("2/2")
expect(ShortDate.new("3/2")).to be >= ShortDate.new("2/3")
# with leading zeroes
expect(ShortDate.new('04/06')).to be == ShortDate.new("4/6")
# '4/6/2000' still matches '%m/%d' ...
expect(ShortDate.new('4/6/2000')).to be == ShortDate.new("4/6")
end
it 'is validable' do
expect(ShortDate.new("1/1")).to be_valid
# invalid dates
expect(ShortDate.new("20/1")).to_not be_valid
expect(ShortDate.new("1/32")).to_not be_valid
expect(ShortDate.new("2/30")).to_not be_valid
# any other format will fail
expect(ShortDate.new('2000/4/6')).to_not be_valid
expect(ShortDate.new('Apr 6')).to_not be_valid
end
end
@wacko

This comment has been minimized.

Copy link
Owner Author

wacko commented Jan 3, 2020

Example with Rails:

class RecurringEvent < ActiveRecord::Base
  composed_of :date, class_name: "ShortDate"
end
@wacko

This comment has been minimized.

Copy link
Owner Author

wacko commented Jan 3, 2020

A simpler implementation, but without day/month attributes

require 'date'

class ShortDate
  attr_reader :date
  include Comparable

  def initialize(string)
    temp = Date.strptime(string, '%m/%d')
    @date = '%02u/%02u' % [temp.month, temp.day]
  rescue StandardError
  end

  def ==(other_day)
    date == other_day.date
  end

  def <=>(other_day)
    date <=> other_day.date
  end

  def to_s
    date
  end

  def valid?
    !date.nil?
  end

end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.