summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJérémy Zurcher <jeremy@asynk.ch>2011-08-04 14:13:05 +0200
committerJérémy Zurcher <jeremy@asynk.ch>2011-08-04 14:13:05 +0200
commit1cd140288d68a1daf05e397df685d854b70bd7cd (patch)
treea375470226b52a1128570001fbc2607e64b15501
parent041886c20a28823e3ad50679e6e52272bd2a3ae5 (diff)
downloadayk-1cd140288d68a1daf05e397df685d854b70bd7cd.zip
ayk-1cd140288d68a1daf05e397df685d854b70bd7cd.tar.gz
DateTime.age, be clever now
-rw-r--r--lib/ayk/age.rb46
-rw-r--r--spec/age_spec.rb23
2 files changed, 31 insertions, 38 deletions
diff --git a/lib/ayk/age.rb b/lib/ayk/age.rb
index f51b8f1..05a7407 100644
--- a/lib/ayk/age.rb
+++ b/lib/ayk/age.rb
@@ -32,45 +32,25 @@ class DateTime
def age at=DateTime.now
return [nil]*6 if at<self
return [0]*6 if at==self
+ # hours, minutes, seconds
+ hms = (at.hour*3600+at.minute*60+at.sec)-(self.hour*3600+self.minute*60+self.second)
+ hours,r = (hms<0 ? (hms+24*3600) : hms ).divmod 3600
+ mins,secs = r.divmod 60
+ # years, months, days
years = at.year-self.year
months = at.month-self.month
- # move years forward
- x = self>>(12*years)
- if x>at
- # move months backward
- x>>=months
- # adjust years and months
+ days = at.mday-self.mday
+ # adjust years and months
+ days-=1 if hms<0
+ months-=1 if days<0
+ if months<0
years-=1
months+=12
- else
- # move months forward
- x>>=months
end
+ # move years months forward
+ x = self>>(12*years+months)
+ # compute days
days = (at-x).to_i
- if days<0
- # move 1 month backward
- x<<=1
- # adjust months and days
- months-=1
- days = (at-x).to_i
- end
- # move days forward
- x += days
- if x>at
- # move 1 day backward
- x-=1
- days-=1
- if days<0
- x+=1
- x<<=1
- months-=1
- days = (at-x).to_i
- x+=days
- end
- end
- # hours
- hours,r = (at.to_time-x.to_time).to_i.divmod 3600
- mins,secs = r.divmod 60
# return
[years,months,days,hours,mins,secs]
end
diff --git a/spec/age_spec.rb b/spec/age_spec.rb
index 7c447e0..23d54cb 100644
--- a/spec/age_spec.rb
+++ b/spec/age_spec.rb
@@ -16,6 +16,10 @@ end
def full_check birth, at, y, m, d, hh, mm, ss
r = birth.age at
r[0].should eql y
+ if r[1]<0 or r[1]>11 or r[2]<0 or r[2]>31
+ puts birth
+ puts at
+ end
r[1].should eql m
r[2].should eql d
r[3].should eql hh
@@ -49,6 +53,14 @@ describe DateTime do
(0..10000).each do |n|
at = @b+n
r = @b.age at
+ r[1].should >= 0
+ r[1].should <= 11
+ r[2].should >= 0
+ if r[2]>31
+ puts @b
+ puts at
+ end
+ r[2].should <= 31
x = (@b>>(12*r[0]+r[1]))+r[2]
x.year.should eql at.year
x.month.should eql at.month
@@ -56,6 +68,12 @@ describe DateTime do
end
end
it "should pass time computation" do
+ # change years
+ full_check @b, DateTime.civil( 2010, 6, 27, 4, 40, 0), 0, 11, 0, 0, 0, 0
+ full_check @b, DateTime.civil( 2010, 7, 27, 3, 40, 0), 0, 11, 29, 23, 0, 0
+ full_check @b, DateTime.civil( 2010, 7, 27, 4, 39, 0), 0, 11, 29, 23, 59, 0
+ full_check @b, DateTime.civil( 2010, 7, 27, 4, 39, 59), 0, 11, 29, 23, 59, 59
+ full_check @b, DateTime.civil( 2010, 7, 27, 4, 40, 0), 1, 0, 0, 0, 0, 0
full_check @b, DateTime.civil( 2010, 9, 25, 3, 40, 0), 1, 1, 28, 23, 0, 0
full_check @b, DateTime.civil( 2010, 9, 25, 4, 39, 0), 1, 1, 28, 23, 59, 0
full_check @b, DateTime.civil( 2010, 9, 25, 4, 39, 59), 1, 1, 28, 23, 59, 59
@@ -73,10 +91,5 @@ describe DateTime do
full_check @b, DateTime.civil( 2010, 9, 28, 4, 39, 59), 1, 2, 0, 23, 59, 59
full_check @b, DateTime.civil( 2010, 9, 28, 4, 40, 0), 1, 2, 1, 0, 0, 0
full_check @b, DateTime.civil( 2010, 9, 29, 3, 40, 0), 1, 2, 1, 23, 0, 0
- # change years
- full_check @b, DateTime.civil( 2010, 7, 27, 4, 40, 0), 1, 0, 0, 0, 0, 0
- full_check @b, DateTime.civil( 2010, 7, 27, 3, 40, 0), 0, 11, 29, 23, 0, 0
- full_check @b, DateTime.civil( 2010, 7, 27, 4, 39, 0), 0, 11, 29, 23, 59, 0
- full_check @b, DateTime.civil( 2010, 7, 27, 4, 39, 59), 0, 11, 29, 23, 59, 59
end
end