ruby-units 0.2.2 → 0.2.3
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/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
|