ruby-units 0.2.2 → 0.2.3
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG +9 -0
- data/README +1 -1
- data/lib/ruby-units.rb +76 -31
- data/lib/units.rb +2 -2
- data/test/test_ruby-units.rb +102 -1
- metadata +2 -2
data/CHANGELOG
CHANGED
@@ -100,4 +100,13 @@ Change Log for Ruby-units
|
|
100
100
|
* added Time.in("5 min")
|
101
101
|
* added Unit.to_unit to simplify some calls
|
102
102
|
|
103
|
+
2006-09-22 0.2.3 * added support for date/time parsing with the Chronic gem
|
104
|
+
parsing will use Chronic if it is loaded
|
105
|
+
* allows Date / Time / DateTime conversions
|
106
|
+
* better test coverage
|
107
|
+
* The 'string'.to_time returns a Time object
|
108
|
+
* 'string'.to_datetime returns a DateTime object
|
109
|
+
* 'string'.time returns a Time object or a DateTime if the Time object fails
|
110
|
+
* 'string'.datetime returns a DateTime or a Time if the DateTime fails
|
111
|
+
|
103
112
|
|
data/README
CHANGED
data/lib/ruby-units.rb
CHANGED
@@ -2,7 +2,7 @@ require 'mathn'
|
|
2
2
|
require 'rational'
|
3
3
|
require 'date'
|
4
4
|
require 'parsedate'
|
5
|
-
# = Ruby Units 0.2.
|
5
|
+
# = Ruby Units 0.2.3
|
6
6
|
#
|
7
7
|
# Copyright 2006 by Kevin C. Olbrich, Ph.D.
|
8
8
|
#
|
@@ -135,7 +135,10 @@ class Unit < Numeric
|
|
135
135
|
return true if @signature == 400 && @numerator.size == 1 && @numerator[0] =~ /(celcius|kelvin|farenheit|rankine)/
|
136
136
|
n = @numerator + @denominator
|
137
137
|
n.compact.each do |x|
|
138
|
-
return false unless x == '<1>' ||
|
138
|
+
return false unless x == '<1>' ||
|
139
|
+
(@@UNIT_VALUES[Regexp.escape(x)] &&
|
140
|
+
@@UNIT_VALUES[Regexp.escape(x)][:denominator].nil? &&
|
141
|
+
@@UNIT_VALUES[Regexp.escape(x)][:numerator].include?(Regexp.escape(x)))
|
139
142
|
end
|
140
143
|
return true
|
141
144
|
end
|
@@ -564,14 +567,14 @@ class Unit < Numeric
|
|
564
567
|
|
565
568
|
# '5 min'.unit.ago
|
566
569
|
def ago
|
567
|
-
Time.now - self
|
570
|
+
Time.now - self rescue DateTime.now - self
|
568
571
|
end
|
569
572
|
|
570
573
|
# '5 min'.before(time)
|
571
574
|
def before(time_point = ::Time.now)
|
572
575
|
raise ArgumentError, "Must specify a Time" unless time_point
|
573
576
|
if String === time_point
|
574
|
-
|
577
|
+
time_point.time - self
|
575
578
|
else
|
576
579
|
time_point - self
|
577
580
|
end
|
@@ -583,9 +586,10 @@ class Unit < Numeric
|
|
583
586
|
case time_point
|
584
587
|
when Time: (Time.now - time_point).unit('s').to(self)
|
585
588
|
when DateTime: (DateTime.now - time_point).unit('d').to(self)
|
586
|
-
when String:
|
589
|
+
when String:
|
590
|
+
(DateTime.now - time_point.time(:context=>:past)).unit('d').to(self)
|
587
591
|
else
|
588
|
-
raise ArgumentError, "Must specify a Time"
|
592
|
+
raise ArgumentError, "Must specify a Time, DateTime, or String"
|
589
593
|
end
|
590
594
|
end
|
591
595
|
|
@@ -594,9 +598,11 @@ class Unit < Numeric
|
|
594
598
|
case time_point
|
595
599
|
when Time: (time_point - Time.now).unit('s').to(self)
|
596
600
|
when DateTime: (time_point - DateTime.now).unit('d').to(self)
|
597
|
-
when String:
|
601
|
+
when String:
|
602
|
+
r = (time_point.time(:context=>:future) - DateTime.now)
|
603
|
+
Time === time_point.time ? r.unit('s').to(self) : r.unit('d').to(self)
|
598
604
|
else
|
599
|
-
raise ArgumentError, "Must specify a Time"
|
605
|
+
raise ArgumentError, "Must specify a Time, DateTime, or String"
|
600
606
|
end
|
601
607
|
end
|
602
608
|
|
@@ -604,7 +610,7 @@ class Unit < Numeric
|
|
604
610
|
def from(time_point = ::Time.now)
|
605
611
|
raise ArgumentError, "Must specify a Time" unless time_point
|
606
612
|
if String === time_point
|
607
|
-
|
613
|
+
time_point.time + self
|
608
614
|
else
|
609
615
|
time_point + self
|
610
616
|
end
|
@@ -659,7 +665,6 @@ class Unit < Numeric
|
|
659
665
|
def replace_temperature
|
660
666
|
return self unless self.signature == 400 && self.units =~ /temp(R|K|F|C)/
|
661
667
|
un = $1
|
662
|
-
puts "self:#{self} #{un}"
|
663
668
|
target = self.units
|
664
669
|
@numerator = case un
|
665
670
|
when 'R' : ['<rankine>']
|
@@ -822,25 +827,15 @@ class Unit < Numeric
|
|
822
827
|
end
|
823
828
|
end
|
824
829
|
|
825
|
-
# Need the 'Uncertain' gem for this to do anything helpful
|
826
|
-
if defined? Uncertain
|
827
|
-
class Uncertain
|
828
|
-
def to_unit(other=nil)
|
829
|
-
other ? Unit.new(self).to(other) : Unit.new(self)
|
830
|
-
end
|
831
|
-
alias :unit :to_unit
|
832
|
-
alias :u :to_unit
|
833
|
-
end
|
834
|
-
end
|
835
|
-
|
836
830
|
|
837
831
|
# Allow date objects to do offsets by a time unit
|
838
832
|
# Date.today + U"1 week" => gives today+1 week
|
839
833
|
class Date
|
840
834
|
alias :unit_date_add :+
|
841
835
|
def +(unit)
|
842
|
-
|
843
|
-
|
836
|
+
case unit
|
837
|
+
when Unit: unit_date_add(unit.to('day').scalar)
|
838
|
+
when Time: unit_date_add(unit.to_datetime)
|
844
839
|
else
|
845
840
|
unit_date_add(unit)
|
846
841
|
end
|
@@ -848,12 +843,24 @@ class Date
|
|
848
843
|
|
849
844
|
alias :unit_date_sub :-
|
850
845
|
def -(unit)
|
851
|
-
|
852
|
-
|
846
|
+
case unit
|
847
|
+
when Unit: unit_date_sub(unit.to('day').scalar)
|
848
|
+
when Time: unit_date_sub(unit.to_datetime)
|
853
849
|
else
|
854
850
|
unit_date_sub(unit)
|
855
851
|
end
|
856
852
|
end
|
853
|
+
|
854
|
+
def to_time
|
855
|
+
Time.local(*ParseDate.parsedate(self.to_s))
|
856
|
+
end
|
857
|
+
|
858
|
+
alias :units_datetime_inspect :inspect
|
859
|
+
def inspect(raw = false)
|
860
|
+
return self.units_datetime_inspect if raw
|
861
|
+
self.to_s
|
862
|
+
end
|
863
|
+
|
857
864
|
end
|
858
865
|
|
859
866
|
class Object
|
@@ -894,8 +901,9 @@ class String
|
|
894
901
|
|
895
902
|
# format unit output using formating codes '%0.2f' % '1 mm'.unit => '1.00 mm'
|
896
903
|
def %(*args)
|
897
|
-
|
898
|
-
|
904
|
+
case args[0]
|
905
|
+
when Unit: args[0].to_s(self)
|
906
|
+
when Complex: args[0].to_s
|
899
907
|
else
|
900
908
|
unit_format(*args)
|
901
909
|
end
|
@@ -927,6 +935,36 @@ class String
|
|
927
935
|
def to(other)
|
928
936
|
self.unit.to(other)
|
929
937
|
end
|
938
|
+
|
939
|
+
def time(options = {})
|
940
|
+
self.to_time(options) rescue self.to_datetime(options)
|
941
|
+
end
|
942
|
+
|
943
|
+
def to_time(options = {})
|
944
|
+
begin
|
945
|
+
#raises exception when Chronic not defined or when it returns a nil (i.e., can't parse the input)
|
946
|
+
r = Chronic.parse(self,options)
|
947
|
+
raise(ArgumentError, 'Invalid Time String') unless r
|
948
|
+
return r
|
949
|
+
rescue
|
950
|
+
Time.local(*ParseDate.parsedate(self))
|
951
|
+
end
|
952
|
+
end
|
953
|
+
|
954
|
+
def to_datetime(options = {})
|
955
|
+
begin
|
956
|
+
# raises an exception if Chronic.parse = nil or if Chronic not defined
|
957
|
+
r = Chronic.parse(self,options).to_datetime
|
958
|
+
rescue
|
959
|
+
r=DateTime.civil(*ParseDate.parsedate(self)[0..5].compact)
|
960
|
+
end
|
961
|
+
raise RuntimeError, "Invalid Time String" if r == DateTime.new
|
962
|
+
return r
|
963
|
+
end
|
964
|
+
|
965
|
+
def datetime(options = {})
|
966
|
+
self.to_datetime(options) rescue self.to_time(options)
|
967
|
+
end
|
930
968
|
end
|
931
969
|
|
932
970
|
|
@@ -951,9 +989,15 @@ class Time
|
|
951
989
|
alias :unit :to_unit
|
952
990
|
alias :u :to_unit
|
953
991
|
alias :unit_add :+
|
992
|
+
|
993
|
+
def to_datetime
|
994
|
+
DateTime.civil(1970,1,1)+(self.to_f+self.gmt_offset)/86400
|
995
|
+
end
|
996
|
+
|
954
997
|
def +(other)
|
955
|
-
|
956
|
-
|
998
|
+
case other
|
999
|
+
when Unit: unit_add(other.to('s').scalar)
|
1000
|
+
when DateTime: unit_add(other.to_time)
|
957
1001
|
else
|
958
1002
|
unit_add(other)
|
959
1003
|
end
|
@@ -965,8 +1009,9 @@ class Time
|
|
965
1009
|
|
966
1010
|
alias :unit_sub :-
|
967
1011
|
def -(other)
|
968
|
-
|
969
|
-
|
1012
|
+
case other
|
1013
|
+
when Unit: unit_sub(other.to('s').scalar)
|
1014
|
+
when DateTime: unit_sub(other.to_time)
|
970
1015
|
else
|
971
1016
|
unit_sub(other)
|
972
1017
|
end
|
data/lib/units.rb
CHANGED
@@ -101,10 +101,10 @@ UNIT_DEFINITIONS = {
|
|
101
101
|
#time
|
102
102
|
'<second>'=> [%w{s sec second seconds}, 1.0, :time, %w{<second>}],
|
103
103
|
'<minute>'=> [%w{min minute minutes}, 60.0, :time, %w{<second>}],
|
104
|
-
'<hour>'=> [%w{h hour hours}, 3600.0, :time, %w{<second>}],
|
104
|
+
'<hour>'=> [%w{h hr hrs hour hours}, 3600.0, :time, %w{<second>}],
|
105
105
|
'<day>'=> [%w{d day days}, 3600*24, :time, %w{<second>}],
|
106
106
|
'<week>'=> [%w{wk week weeks}, 7*3600*24, :time, %w{<second>}],
|
107
|
-
'<fortnight>'=> [%w{fortnight}, 1209600, :time, %W{<second>}],
|
107
|
+
'<fortnight>'=> [%w{fortnight fortnights}, 1209600, :time, %W{<second>}],
|
108
108
|
'<year>'=> [%w{y yr year years annum}, 31556926, :time, %w{<second>}],
|
109
109
|
'<decade>'=>[%w{decade decades}, 315569260, :time, %w{<second>}],
|
110
110
|
'<century>'=>[%w{century centuries}, 3155692600, :time, %w{<second>}],
|
data/test/test_ruby-units.rb
CHANGED
@@ -3,6 +3,7 @@ require 'rubygems'
|
|
3
3
|
require 'ruby-units'
|
4
4
|
require 'yaml'
|
5
5
|
require 'uncertain'
|
6
|
+
require 'chronic'
|
6
7
|
|
7
8
|
class Unit < Numeric
|
8
9
|
@@USER_DEFINITIONS = {'<inchworm>' => [%w{inworm inchworm}, 0.0254, :length, %w{<meter>} ],
|
@@ -11,7 +12,51 @@ class Unit < Numeric
|
|
11
12
|
Unit.setup
|
12
13
|
end
|
13
14
|
|
15
|
+
class Time
|
16
|
+
@@forced_now = nil
|
17
|
+
class << self
|
18
|
+
alias :unforced_now :now
|
19
|
+
def forced_now
|
20
|
+
return @@forced_now ? @@forced_now : unforced_now
|
21
|
+
end
|
22
|
+
alias :now :forced_now
|
23
|
+
|
24
|
+
def forced_now=(now)
|
25
|
+
@@forced_now = now
|
26
|
+
end
|
27
|
+
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
class DateTime
|
32
|
+
@@forced_now = nil
|
33
|
+
class << self
|
34
|
+
alias :unforced_now :now
|
35
|
+
def forced_now
|
36
|
+
return @@forced_now ? @@forced_now : unforced_now
|
37
|
+
end
|
38
|
+
alias :now :forced_now
|
39
|
+
|
40
|
+
def forced_now=(now)
|
41
|
+
@@forced_now = now
|
42
|
+
end
|
43
|
+
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
14
47
|
class TestRubyUnits < Test::Unit::TestCase
|
48
|
+
|
49
|
+
def setup
|
50
|
+
@april_fools = Time.at 1143910800
|
51
|
+
@april_fools_datetime = DateTime.parse('2006-4-1 12:00')
|
52
|
+
Time.forced_now = @april_fools
|
53
|
+
DateTime.forced_now = @april_fools_datetime
|
54
|
+
end
|
55
|
+
|
56
|
+
def teardown
|
57
|
+
Time.forced_now = nil
|
58
|
+
DateTime.forced_now = nil
|
59
|
+
end
|
15
60
|
|
16
61
|
def test_to_yaml
|
17
62
|
unit = "1 mm".u
|
@@ -29,9 +74,44 @@ class TestRubyUnits < Test::Unit::TestCase
|
|
29
74
|
assert_in_delta "1 h".unit + Time.now, "1 h".from_now, 1
|
30
75
|
assert_in_delta Time.now - 3600, "1 h".before_now, 1
|
31
76
|
assert_in_delta (Time.now.unit - Time.now).unit.scalar, 0, 1
|
32
|
-
|
33
77
|
assert_equal "60 min", "min".until(Time.now + 3600).to_s
|
34
78
|
assert_equal "01:00", "min".since(Time.now - 3600).to_s("%H:%M")
|
79
|
+
assert_in_delta Time.now, "now".time, 1
|
80
|
+
end
|
81
|
+
|
82
|
+
def test_time_helpers
|
83
|
+
assert_equal @april_fools, Time.now
|
84
|
+
assert_equal "1 day".from_now, @april_fools + 86400
|
85
|
+
assert_equal "1 day".from("now"), @april_fools + 86400
|
86
|
+
assert_equal "1 day".ago, @april_fools - 86400
|
87
|
+
assert_equal "1 day".before_now, @april_fools - 86400
|
88
|
+
assert_equal '1 days'.before('now'), @april_fools - 86400
|
89
|
+
assert_equal 'days'.since(@april_fools - 86400), "1 day".unit
|
90
|
+
assert_equal 'days'.since('3/31/06 12:00'), "1 day".unit
|
91
|
+
assert_equal 'days'.since(DateTime.parse('2006-3-31 12:00')), "1 day".unit
|
92
|
+
assert_equal 'days'.until('4/2/2006'), '1 day'.unit
|
93
|
+
assert_equal 'now'.time, Time.now
|
94
|
+
assert_equal 'now'.datetime, DateTime.now
|
95
|
+
assert_raises(ArgumentError) { 'days'.until(1) }
|
96
|
+
assert_raises(ArgumentError) { 'days'.since(1) }
|
97
|
+
assert_equal Unit.new(Time.now).scalar, 1143910800
|
98
|
+
assert_equal @april_fools.unit.to_time, @april_fools
|
99
|
+
assert_equal Time.in('1 day'), @april_fools + 86400
|
100
|
+
assert_equal @april_fools_datetime.inspect, "2006-04-01T12:00:00Z"
|
101
|
+
end
|
102
|
+
|
103
|
+
def test_string_helpers
|
104
|
+
assert_equal '1 mm'.to('in'), Unit('1 mm').to('in')
|
105
|
+
end
|
106
|
+
|
107
|
+
def test_math
|
108
|
+
pi = Math::PI
|
109
|
+
assert_equal Math.sin(pi), Math.sin("180 deg".unit)
|
110
|
+
assert_equal Math.cos(pi), Math.cos("180 deg".unit)
|
111
|
+
assert_equal Math.tan(pi), Math.tan("180 deg".unit)
|
112
|
+
assert_equal Math.sinh(pi), Math.sinh("180 deg".unit)
|
113
|
+
assert_equal Math.cosh(pi), Math.cosh("180 deg".unit)
|
114
|
+
assert_equal Math.tanh(pi), Math.tanh("180 deg".unit)
|
35
115
|
end
|
36
116
|
|
37
117
|
def test_clone
|
@@ -68,6 +148,7 @@ class TestRubyUnits < Test::Unit::TestCase
|
|
68
148
|
|
69
149
|
def test_to_unit
|
70
150
|
unit1 = "1 mm".to_unit
|
151
|
+
assert_equal unit1, unit1.to_unit
|
71
152
|
assert Unit === unit1
|
72
153
|
unit2 = Unit("1 mm")
|
73
154
|
assert Unit === unit1
|
@@ -431,6 +512,11 @@ class TestRubyUnits < Test::Unit::TestCase
|
|
431
512
|
end
|
432
513
|
|
433
514
|
def test_temperature_conversions
|
515
|
+
assert_in_delta '0 tempC'.unit.scalar, '273.15 degK'.unit.scalar, 0.01
|
516
|
+
assert_in_delta '0 tempF'.unit.scalar, '255.37 degK'.unit.scalar, 0.01
|
517
|
+
assert_in_delta '0 tempK'.unit.scalar, '0 degK'.unit.scalar, 0.01
|
518
|
+
assert_in_delta '0 tempR'.unit.scalar, '0 degK'.unit.scalar, 0.01
|
519
|
+
|
434
520
|
unit1 = Unit.new("37 degC")
|
435
521
|
unit2 = unit1 >> "tempF"
|
436
522
|
assert_in_delta 98.6, unit2.scalar, 0.1
|
@@ -615,4 +701,19 @@ class TestRubyUnits < Test::Unit::TestCase
|
|
615
701
|
assert_equal "cells", a.units
|
616
702
|
end
|
617
703
|
|
704
|
+
def test_uncertain
|
705
|
+
if defined? Uncertain
|
706
|
+
a = Uncertain.new(1,1)
|
707
|
+
b = a.unit('mm')
|
708
|
+
assert_equal b.to_s, '1 +/- 1 mm'
|
709
|
+
else
|
710
|
+
fail "Can't test Uncertain Units unless 'Uncertain' gem is installed"
|
711
|
+
end
|
712
|
+
end
|
713
|
+
|
714
|
+
def test_format
|
715
|
+
assert_equal "%0.2f" % "1 mm".unit, "1.00 mm"
|
716
|
+
|
717
|
+
end
|
718
|
+
|
618
719
|
end
|
metadata
CHANGED
@@ -3,8 +3,8 @@ rubygems_version: 0.9.0
|
|
3
3
|
specification_version: 1
|
4
4
|
name: ruby-units
|
5
5
|
version: !ruby/object:Gem::Version
|
6
|
-
version: 0.2.
|
7
|
-
date: 2006-09-
|
6
|
+
version: 0.2.3
|
7
|
+
date: 2006-09-22 00:00:00 -04:00
|
8
8
|
summary: A model that performs unit conversions and unit math
|
9
9
|
require_paths:
|
10
10
|
- lib
|