rails-units 1.3.1

Sign up to get free protection for your applications and to get access to all the features.
data/TODO ADDED
@@ -0,0 +1,2 @@
1
+ 2006-10-02 Currency handling remains to be implemented well
2
+ 2011-04-23 Refactor caching
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 1.3.1
@@ -0,0 +1,14 @@
1
+ $LOAD_PATH << File.dirname(__FILE__)
2
+ require "ruby_units/version"
3
+ require "ruby_units/cache"
4
+ require 'ruby_units/array'
5
+ require 'ruby_units/date'
6
+ require 'ruby_units/time'
7
+ require 'ruby_units/math'
8
+ require 'ruby_units/numeric'
9
+ require 'ruby_units/object'
10
+ require 'ruby_units/string'
11
+ require 'ruby_units/unit_definitions'
12
+ require 'ruby_units/unit'
13
+ require 'ruby_units/fixnum'
14
+
@@ -0,0 +1,14 @@
1
+ $LOAD_PATH << File.dirname(__FILE__)
2
+ require "ruby_units/version"
3
+ require "ruby_units/cache"
4
+ require 'ruby_units/array'
5
+ require 'ruby_units/date'
6
+ require 'ruby_units/time'
7
+ require 'ruby_units/math'
8
+ require 'ruby_units/numeric'
9
+ require 'ruby_units/object'
10
+ require 'ruby_units/string'
11
+ require 'ruby_units/unit_definitions'
12
+ require 'ruby_units/unit'
13
+ require 'ruby_units/fixnum'
14
+
@@ -0,0 +1,9 @@
1
+ # make a unit from an array
2
+ # [1, 'mm'].unit => 1 mm
3
+ class Array
4
+ def to_unit(other = nil)
5
+ other ? Unit.new(self).to(other) : Unit.new(self)
6
+ end
7
+ alias :unit :to_unit
8
+ alias :u :to_unit
9
+ end
@@ -0,0 +1,20 @@
1
+ class Unit < Numeric
2
+ @@cached_units = {}
3
+
4
+ class Cache
5
+ def self.get(key = nil)
6
+ key.nil? ? @@cached_units : @@cached_units[key]
7
+ end
8
+
9
+ def self.set(key, value)
10
+ @@cached_units[key] = value
11
+ end
12
+
13
+ def self.clear
14
+ @@cached_units = {}
15
+ @@base_unit_cache = {}
16
+ Unit.new(1)
17
+ end
18
+
19
+ end
20
+ end
@@ -0,0 +1,53 @@
1
+ # Allow date objects to do offsets by a time unit
2
+ # Date.today + U"1 week" => gives today+1 week
3
+
4
+ require 'date'
5
+
6
+ class Date
7
+ alias :unit_date_add :+
8
+ def +(unit)
9
+ case unit
10
+ when Unit
11
+ unit = unit.to('d').round if ['y', 'decade', 'century'].include? unit.units
12
+ unit_date_add(unit.to('day').scalar)
13
+ else
14
+ unit_date_add(unit)
15
+ end
16
+ end
17
+
18
+
19
+ alias :unit_date_sub :-
20
+ def -(unit)
21
+ case unit
22
+ when Unit
23
+ unit = unit.to('d').round if ['y', 'decade', 'century'].include? unit.units
24
+ unit_date_sub(unit.to('day').scalar)
25
+ else
26
+ unit_date_sub(unit)
27
+ end
28
+ end
29
+
30
+ def to_unit(other = nil)
31
+ other ? Unit.new(self).to(other) : Unit.new(self)
32
+ end
33
+ alias :unit :to_unit
34
+
35
+ unless Date.instance_methods.include?(:to_time)
36
+ def to_time
37
+ Time.local(*ParseDate.parsedate(self.to_s))
38
+ end
39
+ end
40
+
41
+ alias :units_datetime_inspect :inspect
42
+ def inspect(raw = false)
43
+ return self.units_datetime_inspect if raw
44
+ self.to_s
45
+ end
46
+
47
+ unless Date.instance_methods.include?(:to_date)
48
+ def to_date
49
+ Date.civil(self.year, self.month, self.day)
50
+ end
51
+ end
52
+
53
+ end
@@ -0,0 +1,20 @@
1
+ # this patch is necessary for ruby 1.8 because cases where
2
+ # Integers are divided by Units don't work quite right
3
+
4
+ if RUBY_VERSION < "1.9"
5
+ class Fixnum
6
+ alias quo_without_units quo
7
+
8
+ def quo_with_units(other)
9
+ case other
10
+ when Unit
11
+ self * other.inverse
12
+ else
13
+ quo_without_units(other)
14
+ end
15
+ end
16
+
17
+ alias quo quo_with_units
18
+ alias / quo_with_units
19
+ end
20
+ end
@@ -0,0 +1,101 @@
1
+ # Math will convert unit objects to radians and then attempt to use the value for
2
+ # trigonometric functions.
3
+ require 'mathn'
4
+
5
+ module Math
6
+
7
+ alias :unit_sqrt :sqrt
8
+ def sqrt(n)
9
+ if Unit === n
10
+ (n**(Rational(1,2))).to_unit
11
+ else
12
+ unit_sqrt(n)
13
+ end
14
+ end
15
+ module_function :unit_sqrt
16
+ module_function :sqrt
17
+
18
+ #:nocov:
19
+ if self.respond_to?(:cbrt)
20
+ alias :unit_cbrt :cbrt
21
+ def cbrt(n)
22
+ if Unit === n
23
+ (n**(Rational(1,3))).to_unit
24
+ else
25
+ unit_cbrt(n)
26
+ end
27
+ end
28
+ module_function :unit_cbrt
29
+ module_function :cbrt
30
+ end
31
+ #:nocov:
32
+
33
+ alias :unit_sin :sin
34
+ def sin(n)
35
+ Unit === n ? unit_sin(n.to('radian').scalar) : unit_sin(n)
36
+ end
37
+ module_function :unit_sin
38
+ module_function :sin
39
+
40
+ alias :unit_cos :cos
41
+ def cos(n)
42
+ Unit === n ? unit_cos(n.to('radian').scalar) : unit_cos(n)
43
+ end
44
+ module_function :unit_cos
45
+ module_function :cos
46
+
47
+ alias :unit_sinh :sinh
48
+ def sinh(n)
49
+ Unit === n ? unit_sinh(n.to('radian').scalar) : unit_sinh(n)
50
+ end
51
+ module_function :unit_sinh
52
+ module_function :sinh
53
+
54
+ alias :unit_cosh :cosh
55
+ def cosh(n)
56
+ Unit === n ? unit_cosh(n.to('radian').scalar) : unit_cosh(n)
57
+ end
58
+ module_function :unit_cosh
59
+ module_function :cosh
60
+
61
+ alias :unit_tan :tan
62
+ def tan(n)
63
+ Unit === n ? unit_tan(n.to('radian').scalar) : unit_tan(n)
64
+ end
65
+ module_function :tan
66
+ module_function :unit_tan
67
+
68
+ alias :unit_tanh :tanh
69
+ def tanh(n)
70
+ Unit === n ? unit_tanh(n.to('radian').scalar) : unit_tanh(n)
71
+ end
72
+ module_function :unit_tanh
73
+ module_function :tanh
74
+
75
+ alias :unit_hypot :hypot
76
+ # Convert parameters to consistent units and perform the function
77
+ def hypot(x,y)
78
+ if Unit === x && Unit === y
79
+ (x**2 + y**2)**(1/2)
80
+ else
81
+ unit_hypot(x,y)
82
+ end
83
+ end
84
+ module_function :unit_hypot
85
+ module_function :hypot
86
+
87
+ alias :unit_atan2 :atan2
88
+ def atan2(x,y)
89
+ case
90
+ when (x.is_a?(Unit) && y.is_a?(Unit)) && (x !~ y)
91
+ raise ArgumentError, "Incompatible Units"
92
+ when (x.is_a?(Unit) && y.is_a?(Unit)) && (x =~ y)
93
+ Math::unit_atan2(x.base_scalar, y.base_scalar)
94
+ else
95
+ Math::unit_atan2(x,y)
96
+ end
97
+ end
98
+ module_function :unit_atan2
99
+ module_function :atan2
100
+
101
+ end
@@ -0,0 +1,8 @@
1
+ # make a unitless unit with a given scalar
2
+ class Numeric
3
+ def to_unit(other = nil)
4
+ other ? Unit.new(self, other) : Unit.new(self)
5
+ end
6
+ alias :unit :to_unit
7
+ alias :u :to_unit
8
+ end
@@ -0,0 +1,8 @@
1
+ class Object
2
+ def Unit(*other)
3
+ other.to_unit
4
+ end
5
+
6
+ alias :U :Unit
7
+ alias :u :Unit
8
+ end
@@ -0,0 +1,122 @@
1
+ require 'time'
2
+ # make a string into a unit
3
+ class String
4
+ def to_unit(other = nil)
5
+ other ? Unit.new(self).to(other) : Unit.new(self)
6
+ end
7
+ alias :unit :to_unit
8
+ alias :u :to_unit
9
+ alias :unit_format :%
10
+
11
+ # format unit output using formating codes '%0.2f' % '1 mm'.unit => '1.00 mm'
12
+ def %(*args)
13
+ return "" if self.empty?
14
+ case
15
+ when args.first.is_a?(Unit)
16
+ args.first.to_s(self)
17
+ when (!defined?(Uncertain).nil? && args.first.is_a?(Uncertain))
18
+ args.first.to_s(self)
19
+ when args.first.is_a?(Complex)
20
+ args.first.to_s
21
+ else
22
+ unit_format(*args)
23
+ end
24
+ end
25
+
26
+ #needed for compatibility with Rails, which defines a String.from method
27
+ if self.public_instance_methods.include? 'from'
28
+ alias :old_from :from
29
+ end
30
+
31
+ # "5 min".from("now")
32
+ def from(time_point = ::Time.now)
33
+ return old_from(time_point) if self.respond_to?(:old_from) && time_point.instance_of?(Integer)
34
+ self.unit.from(time_point)
35
+ end
36
+
37
+ alias :after :from
38
+
39
+ def from_now
40
+ self.from('now')
41
+ end
42
+
43
+ # "5 min".ago
44
+ def ago
45
+ self.unit.ago
46
+ end
47
+
48
+ def before(time_point = ::Time.now)
49
+ self.unit.before(time_point)
50
+ end
51
+
52
+ def before_now
53
+ self.before('now')
54
+ end
55
+
56
+ def since(time_point = ::Time.now)
57
+ self.unit.since(time_point)
58
+ end
59
+
60
+ def until(time_point = ::Time.now)
61
+ self.unit.until(time_point)
62
+ end
63
+
64
+ def time(options = {})
65
+ self.to_time(options) rescue self.to_datetime(options)
66
+ end
67
+
68
+ def to_time(options = {})
69
+ begin
70
+ #raises exception when Chronic not defined or when it returns a nil (i.e., can't parse the input)
71
+ r = Chronic.parse(self,options)
72
+ raise(ArgumentError, 'Invalid Time String') unless r
73
+ return r
74
+ rescue
75
+ case
76
+ when self == "now"
77
+ Time.now
78
+ when Time.respond_to?(:parse)
79
+ Time.parse(self)
80
+ else
81
+ Time.local(*ParseDate.parsedate(self))
82
+ end
83
+ end
84
+ end
85
+
86
+ def to_datetime(options = {})
87
+ begin
88
+ # raises an exception if Chronic.parse = nil or if Chronic not defined
89
+ r = Chronic.parse(self,options).send(:to_datetime)
90
+ rescue Exception => e
91
+ r = case
92
+ when self.to_s == "now"
93
+ DateTime.now
94
+ else
95
+ DateTime.parse(self)
96
+ end
97
+ end
98
+ raise RuntimeError, "Invalid Time String (#{self.to_s})" if r == DateTime.new
99
+ return r
100
+ end
101
+
102
+ def to_date(options={})
103
+ begin
104
+ r = Chronic.parse(self,options).to_date
105
+ rescue
106
+ r = case
107
+ when self == "today"
108
+ Date.today
109
+ when RUBY_VERSION < "1.9"
110
+ Date.civil(*ParseDate.parsedate(self)[0..5].compact)
111
+ else
112
+ Date.parse(self)
113
+ end
114
+ end
115
+ raise RuntimeError, 'Invalid Date String' if r == Date.new
116
+ return r
117
+ end
118
+
119
+ def datetime(options = {})
120
+ self.to_datetime(options) rescue self.to_time(options)
121
+ end
122
+ end
@@ -0,0 +1,71 @@
1
+ #
2
+ # Time math is handled slightly differently. The difference is considered to be an exact duration if
3
+ # the subtracted value is in hours, minutes, or seconds. It is rounded to the nearest day if the offset
4
+ # is in years, decades, or centuries. This leads to less precise values, but ones that match the
5
+ # calendar better.
6
+ class Time
7
+
8
+ class << self
9
+ alias unit_time_at at
10
+ end
11
+
12
+ # Convert a duration to a Time value by considering the duration to be the number of seconds since the
13
+ # epoch
14
+ def self.at(arg)
15
+ case arg
16
+ when Unit
17
+ unit_time_at(arg.to("s").scalar)
18
+ else
19
+ unit_time_at(arg)
20
+ end
21
+ end
22
+
23
+ def to_unit(other = nil)
24
+ other ? Unit.new(self).to(other) : Unit.new(self)
25
+ end
26
+ alias :unit :to_unit
27
+ alias :u :to_unit
28
+ alias :unit_add :+
29
+
30
+ unless Time.instance_methods.include?(:to_date)
31
+ def to_date
32
+ x=(Date.civil(1970,1,1)+((self.to_f+self.gmt_offset)/86400.0)-0.5)
33
+ Date.civil(x.year, x.month, x.day)
34
+ end
35
+ end
36
+
37
+ def +(other)
38
+ case other
39
+ when Unit
40
+ other = other.to('d').round.to('s') if ['y', 'decade', 'century'].include? other.units
41
+ begin
42
+ unit_add(other.to('s').scalar)
43
+ rescue RangeError
44
+ self.to_datetime + other
45
+ end
46
+ else
47
+ unit_add(other)
48
+ end
49
+ end
50
+
51
+ # usage: Time.in '5 min'
52
+ def self.in(duration)
53
+ Time.now + duration.to_unit
54
+ end
55
+
56
+ alias :unit_sub :-
57
+
58
+ def -(other)
59
+ case other
60
+ when Unit
61
+ other = other.to('d').round.to('s') if ['y', 'decade', 'century'].include? other.units
62
+ begin
63
+ unit_sub(other.to('s').scalar)
64
+ rescue RangeError
65
+ self.send(:to_datetime) - other
66
+ end
67
+ else
68
+ unit_sub(other)
69
+ end
70
+ end
71
+ end