summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--lib/ayk/age.rb70
-rw-r--r--spec/age.rb97
-rw-r--r--spec/age_spec.rb82
3 files changed, 135 insertions, 114 deletions
diff --git a/lib/ayk/age.rb b/lib/ayk/age.rb
index 0ecc40e..f51b8f1 100644
--- a/lib/ayk/age.rb
+++ b/lib/ayk/age.rb
@@ -1,37 +1,73 @@
#! /usr/bin/env ruby
# -*- coding: UTF-8 -*-
-
-#----------------------------------------------------------------------------
#
-# File : age.rb
-# Author : Jérémy Zurcher <jeremy@asynk.ch>
-# Date : 22/08/09
+# Copyright (c) 2009-2011 Jérémy Zurcher
+#
+# Permission is hereby granted, free of charge, to any person obtaining
+# a copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sublicense, and/or sell copies of the Software, and to
+# permit persons to whom the Software is furnished to do so, subject to
+# the following conditions:
+#
+# The above copyright notice and this permission notice shall be
+# included in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#
#----------------------------------------------------------------------------
-
+#
require 'date'
-
+#
class DateTime
# returns an array representing years,months,days,hours,minutes,seconds
# between self and futur DateTime at
def age at=DateTime.now
return [nil]*6 if at<self
- # years
+ return [0]*6 if at==self
years = at.year-self.year
+ months = at.month-self.month
+ # move years forward
x = self>>(12*years)
if x>at
- years -= 1
- x<<=12
- end
- months = at.month-x.month+(11*(at.year-x.year))
- x >>=months
- if x>at
- months -= 1
- x <<=1
+ # move months backward
+ x>>=months
+ # adjust years and months
+ years-=1
+ months+=12
+ else
+ # move months forward
+ x>>=months
end
- # 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
diff --git a/spec/age.rb b/spec/age.rb
deleted file mode 100644
index 1e4c9a8..0000000
--- a/spec/age.rb
+++ /dev/null
@@ -1,97 +0,0 @@
-#! /usr/bin/env ruby
-# -*- coding: UTF-8 -*-
-
-require 'ayk/age'
-#
-def age_spec(birth,dy,dm,dd)
- at = ((birth>>(12*dy))>>dm)+dd
-# puts at.strftime "%d.%m.%Y"
- y,m,d,h,i,s = birth.age(at)
-# puts "#{y} #{m} #{d}"
- y.should eql dy
- m.should eql dm
- d.should eql dd
-end
-#
-describe DateTime do
- #
- before(:all) do
- @b = DateTime.civil 2009,7,27,4,40,0 # Róisín Mannion-Zurcher [IRL|CH] )
- end
- it "should pass time checks" do
- y,m,d,h,i,s = @b.age( DateTime.civil(2009,7,27,4,40,0) )
- h.should eql 0
- i.should eql 0
- s.should eql 0
- y,m,d,h,i,s = @b.age( DateTime.civil(2009,7,27,7,2,2) )
- h.should eql 2
- i.should eql 22
- s.should eql 2
- end
- it "simple checks" do
- age_spec(@b,0,0,0)
- age_spec(@b,0,0,1)
- age_spec(@b,0,1,0)
- age_spec(@b,0,1,1)
- age_spec(@b,1,0,0)
- age_spec(@b,1,0,1)
- age_spec(@b,1,1,0)
- age_spec(@b,1,1,1)
- end
- it "should pass day computations" do
- at = ((@b>>(12*0))>>15)+3
- y,m,d,h,i,s = @b.age(at)
- y.should eql 1
- m.should eql 3
- d.should eql 3
- at = ((@b>>(12*0))>>1)+366
- y,m,d,h,i,s = @b.age(at)
- y.should eql 1
- m.should eql 1
- d.should eql 1
- at = ((@b>>(12*5))>>10)+15
- y,m,d,h,i,s = @b.age(at)
- y.should eql 5
- m.should eql 10
- d.should eql 15
- at = ((@b>>(12*0))>>0)+750
- y,m,d,h,i,s = @b.age(at)
- y.should eql 2
- m.should eql 0
- d.should eql 20
- end
- it "should pass more complicated one" do
- at = DateTime.civil 2010,7,13,4,40,0 # Corina Mannion
- y,m,d,h,i,s = @b.age(at)
- y.should eql 0
- m.should eql 11
- d.should eql 16
- h.should eql 0
- i.should eql 0
- s.should eql 0
- at = DateTime.civil 2010,7,13,0,0,0 # Corina Mannion
- y,m,d,h,i,s = @b.age(at)
- y.should eql 0
- m.should eql 11
- d.should eql 15
- h.should eql 19
- i.should eql 20
- s.should eql 0
- end
- it "should correctly handle 1 year -1 day "
- y,m,d,h,i,s = @b.age( DateTime.civil(2009,7,26,4,40,0) )
- y.should eql 0
- m.should eql 11
- d.should eql 15
- h.should eql 19
- i.should eql 20
- s.should eql 0
- end
-end
-
-
-#(1..365).each do |n|
-# dt = birth.age( birth+n)
-# puts "#{n} => #{dt[1]} #{dt[2]}"
-#end
-
diff --git a/spec/age_spec.rb b/spec/age_spec.rb
new file mode 100644
index 0000000..7c447e0
--- /dev/null
+++ b/spec/age_spec.rb
@@ -0,0 +1,82 @@
+#! /usr/bin/env ruby
+# -*- coding: UTF-8 -*-
+
+require 'ayk/age'
+#
+def age_spec birth, dy, dm, dd
+ at = (birth>>(12*dy+dm))+dd
+ y,m,d,hh,mm,ss = birth.age(at)
+ y.should eql dy
+ m.should eql dm
+ d.should eql dd
+ hh.should eql 0
+ mm.should eql 0
+ ss.should eql 0
+end
+def full_check birth, at, y, m, d, hh, mm, ss
+ r = birth.age at
+ r[0].should eql y
+ r[1].should eql m
+ r[2].should eql d
+ r[3].should eql hh
+ r[4].should eql mm
+ r[5].should eql ss
+ x = ((birth>>(12*y+m))+d+(hh/24.0)+(mm/1440.0)+(ss/86400.0))
+ x.year.should eql at.year
+ x.month.should eql at.month
+ x.day.should eql at.day
+ x.hour.should eql at.hour
+# x.minute.should eql at.minute
+# x.second.should eql at.second
+end
+#
+describe DateTime do
+ #
+ before(:all) do
+ @b = DateTime.civil 2009,7,27,4,40,0 # Róisín Mannion-Zurcher [IRL|CH] )
+ end
+ it "should pass basic futur checks" do
+ age_spec(@b,0,0,0)
+ age_spec(@b,0,0,1)
+ age_spec(@b,0,1,0)
+ age_spec(@b,0,1,1)
+ age_spec(@b,1,0,0)
+ age_spec(@b,1,0,1)
+ age_spec(@b,1,1,0)
+ age_spec(@b,1,1,1)
+ end
+ it "should pass 10000 days computation" do
+ (0..10000).each do |n|
+ at = @b+n
+ r = @b.age at
+ x = (@b>>(12*r[0]+r[1]))+r[2]
+ x.year.should eql at.year
+ x.month.should eql at.month
+ x.day.should eql at.day
+ end
+ end
+ it "should pass time computation" do
+ 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
+ full_check @b, DateTime.civil( 2010, 9, 25, 4, 40, 0), 1, 1, 29, 0, 0, 0
+ full_check @b, DateTime.civil( 2010, 9, 26, 3, 40, 0), 1, 1, 29, 23, 0, 0
+ full_check @b, DateTime.civil( 2010, 9, 26, 4, 39, 0), 1, 1, 29, 23, 59, 0
+ full_check @b, DateTime.civil( 2010, 9, 26, 4, 39, 59), 1, 1, 29, 23, 59, 59
+ full_check @b, DateTime.civil( 2010, 9, 26, 4, 40, 0), 1, 1, 30, 0, 0, 0
+ full_check @b, DateTime.civil( 2010, 9, 27, 3, 40, 0), 1, 1, 30, 23, 0, 0
+ full_check @b, DateTime.civil( 2010, 9, 27, 4, 39, 0), 1, 1, 30, 23, 59, 0
+ full_check @b, DateTime.civil( 2010, 9, 27, 4, 39, 59), 1, 1, 30, 23, 59, 59
+ full_check @b, DateTime.civil( 2010, 9, 27, 4, 40, 0), 1, 2, 0, 0, 0, 0
+ full_check @b, DateTime.civil( 2010, 9, 28, 3, 40, 0), 1, 2, 0, 23, 0, 0
+ full_check @b, DateTime.civil( 2010, 9, 28, 4, 39, 0), 1, 2, 0, 23, 59, 0
+ 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