suprdate 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/LICENSE +10 -0
- data/README.md +108 -0
- data/TODO +6 -0
- data/VERSION +1 -0
- data/bin/coverage +19 -0
- data/bin/irb +6 -0
- data/dev_notes/week_definition.rb +62 -0
- data/lib/suprdate.rb +186 -0
- data/lib/suprdate/builder.rb +71 -0
- data/lib/suprdate/day.rb +94 -0
- data/lib/suprdate/month.rb +95 -0
- data/lib/suprdate/year.rb +62 -0
- data/spec/array_diff.spec.rb +17 -0
- data/spec/builder.spec.rb +65 -0
- data/spec/day.spec.rb +124 -0
- data/spec/inter_class_ranges.spec.rb +54 -0
- data/spec/month.spec.rb +149 -0
- data/spec/spec_helper.rb +19 -0
- data/spec/suprdate.spec.rb +193 -0
- data/spec/year.spec.rb +167 -0
- data/suprdate.gemspec +17 -0
- metadata +92 -0
data/lib/suprdate/day.rb
ADDED
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
module Suprdate
|
|
2
|
+
|
|
3
|
+
class Day < Unit
|
|
4
|
+
|
|
5
|
+
require 'date'
|
|
6
|
+
attr_reader :month
|
|
7
|
+
|
|
8
|
+
def initialize(month, value)
|
|
9
|
+
@month = month
|
|
10
|
+
unless (1..month.num_days).include? value
|
|
11
|
+
raise DateConstructionError.new("There are not #{value} days in #{month.of_year_as_s}")
|
|
12
|
+
end
|
|
13
|
+
super(value)
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
protected :initialize
|
|
17
|
+
|
|
18
|
+
STRFTIME_STR = '%Y-%m-%d'
|
|
19
|
+
|
|
20
|
+
def inspect() "#@month-#{@value.to_s.rjust(2, '0')}" end
|
|
21
|
+
def year() @month.year end
|
|
22
|
+
|
|
23
|
+
# This day as a Ruby Time object.
|
|
24
|
+
def time() Time.mktime(*parts) end
|
|
25
|
+
|
|
26
|
+
# This day as a Ruby Date object.
|
|
27
|
+
def date() Date.new(*parts) end
|
|
28
|
+
|
|
29
|
+
# This day as a Ruby DateTime object.
|
|
30
|
+
def datetime() DateTime.new(*parts) end
|
|
31
|
+
|
|
32
|
+
# Polymorphic feature; guarantees you a list of Suprdate::Day
|
|
33
|
+
def days() [self] end
|
|
34
|
+
|
|
35
|
+
# Polymorphic feature; guarantees you a Suprdate::Day
|
|
36
|
+
def day() self end
|
|
37
|
+
|
|
38
|
+
# Day of the week as a symbol. (See Suprdate::WEEKDAYS_AS_SYM)
|
|
39
|
+
def of_week_as_sym() WEEKDAYS_AS_SYM[of_week_as_i] end
|
|
40
|
+
|
|
41
|
+
# Day of the week as a string. (See Suprdate::WEEKDAYS_AS_STR)
|
|
42
|
+
def of_week_as_s() WEEKDAYS_AS_STR[of_week_as_i] end
|
|
43
|
+
|
|
44
|
+
# Day of the week as an integer. Presently Sunday is 1, Monday is 2 etc.
|
|
45
|
+
def of_week_as_i() date.wday + 1 end
|
|
46
|
+
|
|
47
|
+
# Day of the year. January 1st is 1.
|
|
48
|
+
def of_year() (date - Date.new(year.value, 1, 1)).numerator + 1 end
|
|
49
|
+
|
|
50
|
+
# Whether this day is a leap day or, in other words, February 29th.
|
|
51
|
+
def leap?() value == 29 && @month.value == 2 end
|
|
52
|
+
|
|
53
|
+
# Next successive day.
|
|
54
|
+
def succ() self + 1 end
|
|
55
|
+
|
|
56
|
+
# Return a new day incremented by an integer.
|
|
57
|
+
def +(increase) new_from_date(date + increase) end
|
|
58
|
+
|
|
59
|
+
# Return a new day decremented by an integer.
|
|
60
|
+
def -(decrease) new_from_date(date - decrease) end
|
|
61
|
+
|
|
62
|
+
# The number of days since parameter#day.
|
|
63
|
+
def since(operand) (date - operand.day.date).numerator end
|
|
64
|
+
|
|
65
|
+
# The number of days until parameter#day.
|
|
66
|
+
def until(operand) (operand.day.date - date).numerator end
|
|
67
|
+
|
|
68
|
+
def <=>(operand)
|
|
69
|
+
return -1 if operand == Infinity
|
|
70
|
+
date <=> operand.day.date
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
# If this day is the first Monday of the month this method returns 1.
|
|
74
|
+
# If this day is the second Monday of the month this method returns 2.
|
|
75
|
+
# Works for all days.
|
|
76
|
+
def weekday_occurrence_this_month
|
|
77
|
+
w = of_week_as_i
|
|
78
|
+
w_days_this_month = @month.days[0..value - 1].select do |day|
|
|
79
|
+
day.of_week_as_i == w
|
|
80
|
+
end
|
|
81
|
+
ORDINALS[w_days_this_month.nitems]
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
alias :of_month :value
|
|
85
|
+
|
|
86
|
+
def parts() [year.value, @month.value, value] end # :nodoc:
|
|
87
|
+
|
|
88
|
+
def new_from_date(date) # :nodoc:
|
|
89
|
+
new(@month.new(year.new(date.year), date.month), date.day)
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
end
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
module Suprdate
|
|
2
|
+
|
|
3
|
+
class Month < Unit
|
|
4
|
+
|
|
5
|
+
attr_accessor :day_factory
|
|
6
|
+
attr_reader :year
|
|
7
|
+
|
|
8
|
+
STRFTIME_STR = '%Y-%m'
|
|
9
|
+
|
|
10
|
+
def initialize(year, value)
|
|
11
|
+
@year = year
|
|
12
|
+
@value = if value.kind_of?(Symbol)
|
|
13
|
+
MONTHS_SYM_TO_I.fetch(value)
|
|
14
|
+
else
|
|
15
|
+
unless MONTH_RANGE.include?(value)
|
|
16
|
+
raise "Month value must specified as symbol or be within range #{MONTH_RANGE.inspect}"
|
|
17
|
+
end
|
|
18
|
+
value
|
|
19
|
+
end
|
|
20
|
+
self # intentional
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
protected :initialize
|
|
24
|
+
|
|
25
|
+
# Name of month as symbol.
|
|
26
|
+
def to_sym() MONTHS_AS_SYM[@value] end
|
|
27
|
+
|
|
28
|
+
# Number of day in this month.
|
|
29
|
+
def num_days
|
|
30
|
+
return 29 if leap?
|
|
31
|
+
NUM_DAYS_IN_MONTHS[@value]
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
# All the days in this month
|
|
35
|
+
def days
|
|
36
|
+
(1..num_days).to_a.map { |i| day_factory.new(self, i) }
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
# A choice of some specific days from this month.
|
|
40
|
+
def day(*indices)
|
|
41
|
+
indices = [1] if indices.empty?
|
|
42
|
+
rval = indices.map do |i|
|
|
43
|
+
i = num_days + 1 - i.abs if i < 0
|
|
44
|
+
day_factory.new(self, i)
|
|
45
|
+
end
|
|
46
|
+
Utility::disarray(rval)
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
# Whether this month contains a leap day.
|
|
50
|
+
def leap?() @value == 2 && @year.leap? end
|
|
51
|
+
|
|
52
|
+
def inspect() "#@year-#{@value.to_s.rjust(2, '0')}" end
|
|
53
|
+
|
|
54
|
+
def <=>(operand)
|
|
55
|
+
return -1 if operand == Infinity
|
|
56
|
+
operand = operand.month
|
|
57
|
+
(@year.value * NUM_MONTHS_IN_YEAR + @value) - (operand.year.value * NUM_MONTHS_IN_YEAR + operand.value)
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
# Number of months since parameter#month.
|
|
61
|
+
def since(operand) sum - operand.month.sum end
|
|
62
|
+
|
|
63
|
+
# Number of months until parameter#month.
|
|
64
|
+
def until(operand) operand.month.sum - sum end
|
|
65
|
+
|
|
66
|
+
# Return a new month incremented by an integer.
|
|
67
|
+
def +(increase) new_from_sum(sum + increase) end
|
|
68
|
+
|
|
69
|
+
# Return a new month decremented by an integer.
|
|
70
|
+
def -(decrease) new_from_sum(sum - decrease) end
|
|
71
|
+
|
|
72
|
+
# Next successive month.
|
|
73
|
+
def succ() self + 1 end
|
|
74
|
+
|
|
75
|
+
def of_year_as_sym() MONTHS_AS_SYM[@value] end
|
|
76
|
+
def of_year_as_s() MONTHS_AS_STR[@value] end
|
|
77
|
+
def month() self end
|
|
78
|
+
|
|
79
|
+
alias :of_year_as_i :value
|
|
80
|
+
alias :[] :day
|
|
81
|
+
|
|
82
|
+
protected
|
|
83
|
+
|
|
84
|
+
# total number of months from 0 years 0 months
|
|
85
|
+
def sum
|
|
86
|
+
@year.value * NUM_MONTHS_IN_YEAR + @value - 1
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
def new_from_sum(sum)
|
|
90
|
+
new(@year.new(sum / NUM_MONTHS_IN_YEAR), sum % NUM_MONTHS_IN_YEAR + 1)
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
end
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
module Suprdate
|
|
2
|
+
|
|
3
|
+
class Year < Unit
|
|
4
|
+
|
|
5
|
+
attr_accessor :month_factory, :day_factory, :week_factory, :week_definition
|
|
6
|
+
|
|
7
|
+
MINIMUM_VALUE = 1582 # year when leap years were first standardized
|
|
8
|
+
STRFTIME_STR = '%Y'
|
|
9
|
+
|
|
10
|
+
def initialize(v)
|
|
11
|
+
v = v.to_i
|
|
12
|
+
raise DateConstructionError.new(
|
|
13
|
+
"Attempted to create a year valued #{v}, #{MINIMUM_VALUE - v} less than minimum " +
|
|
14
|
+
"allowed value of #{MINIMUM_VALUE}"
|
|
15
|
+
) if v < MINIMUM_VALUE
|
|
16
|
+
super(v)
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
protected :initialize # for + and -
|
|
20
|
+
|
|
21
|
+
def <=>(operand)
|
|
22
|
+
return -1 if operand == Infinity
|
|
23
|
+
operand = operand.year
|
|
24
|
+
@value - operand.value
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def month(*indices)
|
|
28
|
+
indices = [1] if indices.empty?
|
|
29
|
+
Utility::disarray(indices.map { |i| new_month(i) })
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def +(increase) new(@value + increase) end
|
|
33
|
+
def -(decrease) new(@value - decrease) end
|
|
34
|
+
def succ() self + 1 end
|
|
35
|
+
def months() MONTH_RANGE.to_a.map { |i| new_month(i) } end
|
|
36
|
+
def days() months.map { |m| m.days }.flatten end
|
|
37
|
+
def day(*args) month(1).day(*args) end
|
|
38
|
+
def inspect() @value.to_s end
|
|
39
|
+
def year() self end
|
|
40
|
+
def since(year) @value - year.value end
|
|
41
|
+
def until(year) year.value - @value end
|
|
42
|
+
|
|
43
|
+
def leap?
|
|
44
|
+
return true if @value % 400 == 0
|
|
45
|
+
return false if @value % 100 == 0
|
|
46
|
+
return true if @value % 4 == 0
|
|
47
|
+
false
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
alias :[] :month
|
|
51
|
+
|
|
52
|
+
protected
|
|
53
|
+
|
|
54
|
+
def new_month(value)
|
|
55
|
+
month = month_factory.new(self, value)
|
|
56
|
+
month.day_factory = day_factory
|
|
57
|
+
month
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
end
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
require File.dirname(__FILE__) + '/spec_helper'
|
|
2
|
+
|
|
3
|
+
describe 'array diff' do
|
|
4
|
+
|
|
5
|
+
it 'should remove equal year elems' do
|
|
6
|
+
([y(2010), y(2011)] - [y(2010)]).should == [y(2011)]
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
it 'should remove equal month elems' do
|
|
10
|
+
([m(2010,1), m(2010, 2)] - [m(2010,1)]).should == [m(2010, 2)]
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
it 'should remove equal day elems' do
|
|
14
|
+
([d(2010, 1, 1), d(2010, 1, 2)] - [d(2010, 1, 1)]).should == [d(2010, 1, 2)]
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
end
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
require File.dirname(__FILE__) + '/spec_helper'
|
|
2
|
+
|
|
3
|
+
describe Builder, 'normal unit methods' do
|
|
4
|
+
|
|
5
|
+
it "should build years" do
|
|
6
|
+
year = Builder.new.year(expected = (rand * 100).round + 1700)
|
|
7
|
+
year.should be_instance_of(Year)
|
|
8
|
+
year.to_i.should == expected
|
|
9
|
+
year.month_factory.should == Month
|
|
10
|
+
year.day_factory.should == Day
|
|
11
|
+
|
|
12
|
+
# reminds me to update the builder when I add this functionality
|
|
13
|
+
year.week_definition.should == nil
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
it "should build months" do
|
|
17
|
+
month = Builder.new.month(2008, expected = (rand * 11).round + 1)
|
|
18
|
+
month.should be_instance_of(Month)
|
|
19
|
+
month.to_i.should == expected
|
|
20
|
+
month.day_factory.should == Day
|
|
21
|
+
month.year.week_definition.should == nil
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
it "should build days" do
|
|
25
|
+
day = Builder.new.day(2008, 1, expected = (rand * 30).round + 1)
|
|
26
|
+
day.should be_instance_of(Day)
|
|
27
|
+
day.year.week_definition.should == nil
|
|
28
|
+
day.year.month_factory.should == Month
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
it "should build today" do
|
|
32
|
+
Builder.new.today.should be_instance_of(Day)
|
|
33
|
+
Builder.new.today.to_s.should == Time.now.strftime(Day::STRFTIME_STR)
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
describe Builder, 'date method' do
|
|
39
|
+
|
|
40
|
+
it "should abstract the other methods of Builder" do
|
|
41
|
+
Builder::DATE_NUM_PARTS_RANGE.each do |num_parts|
|
|
42
|
+
b = Builder.new
|
|
43
|
+
b.should_receive(Builder::UNIT_NUM_PARTS[num_parts]).once.and_return(expected = rand_int)
|
|
44
|
+
b.date(*date_parts(num_parts)).should == expected
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
it "should raise if wrong number of args" do
|
|
49
|
+
lambda { Builder.new.date(1,2,3,4) }.should raise_error(DateConstructionError)
|
|
50
|
+
lambda { Builder.new.date() }.should raise_error(DateConstructionError)
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
describe Builder, 'exported builder methods' do
|
|
56
|
+
|
|
57
|
+
it "should be defined" do
|
|
58
|
+
defined = ['Year', 'Month', 'Day', 'Date', 'Today'].each do |e|
|
|
59
|
+
respond_to?(e).should == true
|
|
60
|
+
end
|
|
61
|
+
(Builder.builder_methods.map { |m| m.to_export } - defined).should == []
|
|
62
|
+
Day(2008, 10, 10).should == DEFAULT_BUILDER.day(2008, 10, 10)
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
end
|
data/spec/day.spec.rb
ADDED
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
require File.dirname(__FILE__) + '/spec_helper'
|
|
2
|
+
|
|
3
|
+
describe Day, 'creation' do
|
|
4
|
+
|
|
5
|
+
it "should work from an integer" do
|
|
6
|
+
d(2000, 1, 1).to_s.should == '2000-01-01'
|
|
7
|
+
d(2000, 1, 8).to_s.should == '2000-01-08'
|
|
8
|
+
d(2000, 2, 3).to_s.should == '2000-02-03'
|
|
9
|
+
d(1999, 3, 4).to_s.should == '1999-03-04'
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
it "should prevent the creation of impossible days" do
|
|
13
|
+
lambda { d(2000, 1, 40) }.should raise_error(DateConstructionError)
|
|
14
|
+
lambda { d(2000, 2, 30) }.should raise_error(DateConstructionError)
|
|
15
|
+
lambda { d(2000, 4, 31) }.should raise_error(DateConstructionError)
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
describe Day, 'readers' do
|
|
21
|
+
|
|
22
|
+
it "should give you the day of the year" do
|
|
23
|
+
d(2000, 1, 1).of_year.should == 1
|
|
24
|
+
d(2000, 1, 5).of_year.should == 5
|
|
25
|
+
d(2000, 2, 2).of_year.should == 33
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
it "should give you the day of the week" do
|
|
29
|
+
d(2008, 11, 9).of_week_as_s.should == "Sunday"
|
|
30
|
+
d(2008, 11, 29).of_week_as_sym.should == :sat
|
|
31
|
+
d(2008, 11, 28).of_week_as_sym.should == :fri
|
|
32
|
+
d(2008, 11, 28).of_week_as_i.should == 6
|
|
33
|
+
d(2008, 12, 1).of_week_as_i.should == 2
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
it "should give you equivalent Date, DateTime and Time objects" do
|
|
37
|
+
day = d(2000, 1, 1)
|
|
38
|
+
day.date.should be_instance_of(Date)
|
|
39
|
+
day.time.should be_instance_of(Time)
|
|
40
|
+
day.datetime.should be_instance_of(DateTime)
|
|
41
|
+
# returns are representitive:
|
|
42
|
+
day.date.strftime('%Y-%m-%d').should == day.to_s
|
|
43
|
+
day.time.strftime('%Y-%m-%d').should == day.to_s
|
|
44
|
+
day.datetime.strftime('%Y-%m-%d').should == day.to_s
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
it "should return appropriate symbol" do
|
|
48
|
+
d(2008, 11, 2).weekday_occurrence_this_month.should == :first
|
|
49
|
+
d(2008, 11, 9).weekday_occurrence_this_month.should == :second
|
|
50
|
+
d(2008, 11, 30).weekday_occurrence_this_month.should == :fifth
|
|
51
|
+
d(2008, 11, 19).weekday_occurrence_this_month.should == :third
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
it "should know when it is one" do
|
|
55
|
+
d(2000, 2, 29).leap?.should == true
|
|
56
|
+
d(2000, 2, 28).leap?.should == false
|
|
57
|
+
lambda { d(2001, 2, 29) }.should raise_error(DateConstructionError)
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
describe Day, 'math and logic' do
|
|
63
|
+
|
|
64
|
+
it "should be comparable" do
|
|
65
|
+
(d(2000, 1, 21) == d(2000, 1, 21)).should == true
|
|
66
|
+
(d(2000, 1, 20) == d(2000, 1, 21)).should == false
|
|
67
|
+
(d(2000, 6, 21) == d(2000, 5, 21)).should == false
|
|
68
|
+
(d(2000, 5, 21) == d(2001, 5, 21)).should == false
|
|
69
|
+
(d(2000, 1, 21) > d(2000, 1, 22)).should == false
|
|
70
|
+
(d(2000, 1, 22) > d(2000, 1, 21)).should == true
|
|
71
|
+
(d(2000, 6, 21) > d(2000, 5, 21)).should == true
|
|
72
|
+
(d(2000, 5, 21) > d(2000, 6, 21)).should == false
|
|
73
|
+
(d(2000, 5, 21) > d(2001, 5, 21)).should == false
|
|
74
|
+
(d(2001, 5, 21) > d(2000, 5, 21)).should == true
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
it "should be able to add with integers" do
|
|
78
|
+
(d(2000, 1, 11) + 1).should == d(2000, 1, 12)
|
|
79
|
+
(d(1999, 12, 31) + 1).should == d(2000, 1, 1)
|
|
80
|
+
# accounts for leap
|
|
81
|
+
(d(2000, 2, 28) + 2).should == d(2000, 3, 1)
|
|
82
|
+
(d(2001, 2, 28) + 2).should == d(2001, 3, 2)
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
it "should be able to subtract with integers" do
|
|
86
|
+
(d(2000, 1, 12) - 1).should == d(2000, 1, 11)
|
|
87
|
+
(d(2000, 1, 1) - 1).should == d(1999, 12, 31)
|
|
88
|
+
# accounts for leap
|
|
89
|
+
(d(2000, 3, 1) - 2).should == d(2000, 2, 28)
|
|
90
|
+
(d(2001, 3, 2) - 2).should == d(2001, 2, 28)
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
it "should hold state after arithmetic" do
|
|
94
|
+
a = d(2000, 1, 28)
|
|
95
|
+
# Because Day has no writable state of it's own (but Year does) I am assigning a random value
|
|
96
|
+
# to month_factory (an attribute on the year).
|
|
97
|
+
a.year.month_factory = expected = rand_int
|
|
98
|
+
b = a + 5 # the month and the day change
|
|
99
|
+
# but the month should still hold the original random value
|
|
100
|
+
b.year.month_factory.should == expected
|
|
101
|
+
b.object_id.should_not == a.object_id
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
it "should be enumerable in a range" do
|
|
105
|
+
(d(2000, 1, 1)..d(2000, 1, 4)).to_a.should == [
|
|
106
|
+
d(2000, 1, 1), d(2000, 1, 2), d(2000, 1, 3), d(2000, 1, 4)
|
|
107
|
+
]
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
it "should be able to get days since and until other days" do
|
|
111
|
+
d(2000, 1, 3).since(d(2000, 1, 1)).should == 2
|
|
112
|
+
d(2000, 2, 1).since(d(2000, 1, 1)).should == 31
|
|
113
|
+
d(2000, 1, 1).until(d(2000, 1, 3)).should == 2
|
|
114
|
+
d(2000, 1, 1).until(d(2000, 2, 1)).should == 31
|
|
115
|
+
end
|
|
116
|
+
|
|
117
|
+
it "should be able to get days since and until other months and years" do
|
|
118
|
+
d(2000, 1, 3).since(m(2000, 1)).should == 2
|
|
119
|
+
d(2000, 1, 3).since(y(2000)).should == 2
|
|
120
|
+
d(2000, 3, 3).since(m(2000, 3)).should == 2
|
|
121
|
+
d(2000, 1, 3).since(y(2000)).should == 2
|
|
122
|
+
end
|
|
123
|
+
|
|
124
|
+
end
|