acvwilson-currency 0.5.0
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/COPYING.txt +339 -0
- data/ChangeLog +8 -0
- data/LICENSE.txt +65 -0
- data/Manifest.txt +58 -0
- data/README.txt +51 -0
- data/Releases.txt +155 -0
- data/TODO.txt +9 -0
- data/currency.gemspec +18 -0
- data/examples/ex1.rb +13 -0
- data/examples/xe1.rb +20 -0
- data/lib/currency.rb +143 -0
- data/lib/currency/active_record.rb +265 -0
- data/lib/currency/config.rb +91 -0
- data/lib/currency/core_extensions.rb +83 -0
- data/lib/currency/currency.rb +175 -0
- data/lib/currency/currency/factory.rb +121 -0
- data/lib/currency/currency_version.rb +6 -0
- data/lib/currency/exception.rb +119 -0
- data/lib/currency/exchange.rb +48 -0
- data/lib/currency/exchange/rate.rb +214 -0
- data/lib/currency/exchange/rate/deriver.rb +157 -0
- data/lib/currency/exchange/rate/source.rb +89 -0
- data/lib/currency/exchange/rate/source/base.rb +166 -0
- data/lib/currency/exchange/rate/source/failover.rb +63 -0
- data/lib/currency/exchange/rate/source/federal_reserve.rb +160 -0
- data/lib/currency/exchange/rate/source/historical.rb +79 -0
- data/lib/currency/exchange/rate/source/historical/rate.rb +184 -0
- data/lib/currency/exchange/rate/source/historical/rate_loader.rb +186 -0
- data/lib/currency/exchange/rate/source/historical/writer.rb +220 -0
- data/lib/currency/exchange/rate/source/new_york_fed.rb +127 -0
- data/lib/currency/exchange/rate/source/provider.rb +120 -0
- data/lib/currency/exchange/rate/source/test.rb +50 -0
- data/lib/currency/exchange/rate/source/the_financials.rb +191 -0
- data/lib/currency/exchange/rate/source/timed_cache.rb +198 -0
- data/lib/currency/exchange/rate/source/xe.rb +165 -0
- data/lib/currency/exchange/time_quantitizer.rb +111 -0
- data/lib/currency/formatter.rb +310 -0
- data/lib/currency/macro.rb +321 -0
- data/lib/currency/money.rb +298 -0
- data/lib/currency/money_helper.rb +13 -0
- data/lib/currency/parser.rb +193 -0
- data/spec/ar_column_spec.rb +76 -0
- data/spec/ar_core_spec.rb +68 -0
- data/spec/ar_simple_spec.rb +23 -0
- data/spec/config_spec.rb +29 -0
- data/spec/federal_reserve_spec.rb +75 -0
- data/spec/formatter_spec.rb +72 -0
- data/spec/historical_writer_spec.rb +187 -0
- data/spec/macro_spec.rb +109 -0
- data/spec/money_spec.rb +355 -0
- data/spec/new_york_fed_spec.rb +73 -0
- data/spec/parser_spec.rb +105 -0
- data/spec/spec_helper.rb +25 -0
- data/spec/time_quantitizer_spec.rb +115 -0
- data/spec/timed_cache_spec.rb +95 -0
- data/spec/xe_spec.rb +50 -0
- metadata +117 -0
@@ -0,0 +1,73 @@
|
|
1
|
+
# Copyright (C) 2006-2007 Kurt Stephens <ruby-currency(at)umleta.com>
|
2
|
+
# See LICENSE.txt for details.
|
3
|
+
|
4
|
+
require 'test/test_base'
|
5
|
+
|
6
|
+
require 'currency' # For :type => :money
|
7
|
+
require 'currency/exchange/rate/source/new_york_fed'
|
8
|
+
|
9
|
+
module Currency
|
10
|
+
|
11
|
+
class NewYorkFedTest < TestBase
|
12
|
+
before do
|
13
|
+
super
|
14
|
+
end
|
15
|
+
|
16
|
+
|
17
|
+
@@available = nil
|
18
|
+
|
19
|
+
# New York Fed rates are not available on Saturday and Sunday.
|
20
|
+
def available?
|
21
|
+
if @@available == nil
|
22
|
+
@@available = @source.available?
|
23
|
+
STDERR.puts "Warning: NewYorkFed unavailable on Saturday and Sunday, skipping tests."
|
24
|
+
end
|
25
|
+
@@available
|
26
|
+
end
|
27
|
+
|
28
|
+
|
29
|
+
def get_rate_source
|
30
|
+
# Force NewYorkFed Exchange.
|
31
|
+
verbose = false
|
32
|
+
source = @source = Exchange::Rate::Source::NewYorkFed.new(:verbose => verbose)
|
33
|
+
deriver = Exchange::Rate::Deriver.new(:source => source, :verbose => source.verbose)
|
34
|
+
end
|
35
|
+
|
36
|
+
|
37
|
+
|
38
|
+
it "usd cad" do
|
39
|
+
return unless available?
|
40
|
+
|
41
|
+
rates = Exchange::Rate::Source.default.source.raw_rates.should.not == nil
|
42
|
+
rates[:USD].should.not == nil
|
43
|
+
usd_cad = rates[:USD][:CAD].should.not == nil
|
44
|
+
|
45
|
+
usd = Money.new(123.45, :USD).should.not == nil
|
46
|
+
cad = usd.convert(:CAD).should.not == nil
|
47
|
+
|
48
|
+
assert_kind_of Numeric, m = (cad.to_f / usd.to_f)
|
49
|
+
# $stderr.puts "m = #{m}"
|
50
|
+
assert_equal_float usd_cad, m, 0.001
|
51
|
+
end
|
52
|
+
|
53
|
+
|
54
|
+
it "cad eur" do
|
55
|
+
return unless available?
|
56
|
+
|
57
|
+
rates = Exchange::Rate::Source.default.source.raw_rates.should.not == nil
|
58
|
+
rates[:USD].should.not == nil
|
59
|
+
usd_cad = rates[:USD][:CAD].should.not == nil
|
60
|
+
usd_eur = rates[:USD][:EUR].should.not == nil
|
61
|
+
|
62
|
+
cad = Money.new(123.45, :CAD).should.not == nil
|
63
|
+
eur = cad.convert(:EUR).should.not == nil
|
64
|
+
|
65
|
+
assert_kind_of Numeric, m = (eur.to_f / cad.to_f)
|
66
|
+
# $stderr.puts "m = #{m}"
|
67
|
+
assert_equal_float (1.0 / usd_cad) * usd_eur, m, 0.001
|
68
|
+
end
|
69
|
+
|
70
|
+
end
|
71
|
+
|
72
|
+
end # module
|
73
|
+
|
data/spec/parser_spec.rb
ADDED
@@ -0,0 +1,105 @@
|
|
1
|
+
# Copyright (C) 2006-2007 Kurt Stephens <ruby-currency(at)umleta.com>
|
2
|
+
# See LICENSE.txt for details.
|
3
|
+
|
4
|
+
require 'test/test_base'
|
5
|
+
require 'currency'
|
6
|
+
|
7
|
+
module Currency
|
8
|
+
|
9
|
+
class ParserTest < TestBase
|
10
|
+
before do
|
11
|
+
super
|
12
|
+
@parser = ::Currency::Currency.USD.parser_or_default
|
13
|
+
end
|
14
|
+
|
15
|
+
############################################
|
16
|
+
# Simple stuff.
|
17
|
+
#
|
18
|
+
|
19
|
+
it "default" do
|
20
|
+
|
21
|
+
end
|
22
|
+
|
23
|
+
|
24
|
+
it "thousands" do
|
25
|
+
@parser.parse("1234567.89").rep.should == 123456789
|
26
|
+
assert_equal 123456789, @parser.parse("1,234,567.89").rep
|
27
|
+
end
|
28
|
+
|
29
|
+
|
30
|
+
it "cents" do
|
31
|
+
@parser.parse("1234567.89").rep.should == 123456789
|
32
|
+
@parser.parse("1234567").rep.should == 123456700
|
33
|
+
@parser.parse("1234567.").rep.should == 123456700
|
34
|
+
@parser.parse("1234567.8").rep.should == 123456780
|
35
|
+
@parser.parse("1234567.891").rep.should == 123456789
|
36
|
+
@parser.parse("-1234567").rep.should == -123456700
|
37
|
+
@parser.parse("+1234567").rep.should == 123456700
|
38
|
+
end
|
39
|
+
|
40
|
+
|
41
|
+
it "misc" do
|
42
|
+
m = "123.45 USD".money + "100 CAD".should.not == nil
|
43
|
+
(m.rep == 200.45).should.not == true
|
44
|
+
end
|
45
|
+
|
46
|
+
|
47
|
+
it "round trip" do
|
48
|
+
::Currency::Currency.default = :USD
|
49
|
+
m = ::Currency::Money("1234567.89", :CAD).should.not == nil
|
50
|
+
m2 = ::Currency::Money(m.inspect).should.not == nil
|
51
|
+
m2.rep.should == m.rep
|
52
|
+
m2.currency.should == m.currency
|
53
|
+
m2.time.should == nil
|
54
|
+
m2.inspect.should == m.inspect
|
55
|
+
end
|
56
|
+
|
57
|
+
|
58
|
+
it "round trip time" do
|
59
|
+
::Currency::Currency.default = :USD
|
60
|
+
time = Time.now.getutc
|
61
|
+
m = ::Currency::Money("1234567.89", :CAD, time).should.not == nil
|
62
|
+
m.time.should.not == nil
|
63
|
+
m2 = ::Currency::Money(m.inspect).should.not == nil
|
64
|
+
m2.time.should.not == nil
|
65
|
+
m2.rep.should == m.rep
|
66
|
+
m2.currency.should == m.currency
|
67
|
+
m2.time.to_i.should == m.time.to_i
|
68
|
+
m2.inspect.should == m.inspect
|
69
|
+
end
|
70
|
+
|
71
|
+
|
72
|
+
it "time nil" do
|
73
|
+
parser = ::Currency::Parser.new
|
74
|
+
parser.time = nil
|
75
|
+
|
76
|
+
m = parser.parse("$1234.55").should.not == nil
|
77
|
+
m.time.should == nil
|
78
|
+
end
|
79
|
+
|
80
|
+
|
81
|
+
it "time" do
|
82
|
+
parser = ::Currency::Parser.new
|
83
|
+
parser.time = Time.new
|
84
|
+
|
85
|
+
m = parser.parse("$1234.55").should.not == nil
|
86
|
+
m.time.should == parser.time
|
87
|
+
end
|
88
|
+
|
89
|
+
|
90
|
+
it "time now" do
|
91
|
+
parser = ::Currency::Parser.new
|
92
|
+
parser.time = :now
|
93
|
+
|
94
|
+
m = parser.parse("$1234.55").should.not == nil
|
95
|
+
m1_time = m.time.should.not == nil
|
96
|
+
|
97
|
+
m = parser.parse("$1234.55").should.not == nil
|
98
|
+
m2_time = m.time.should.not == nil
|
99
|
+
|
100
|
+
assert_not_equal m1_time, m2_time
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
end # module
|
105
|
+
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,25 @@
|
|
1
|
+
# Copyright (C) 2006-2007 Kurt Stephens <ruby-currency(at)umleta.com>
|
2
|
+
# See LICENSE.txt for details.
|
3
|
+
|
4
|
+
require 'spec'
|
5
|
+
require File.dirname(__FILE__) + '/../lib/currency'
|
6
|
+
require File.dirname(__FILE__) + '/../lib/currency/exchange/rate/source/test'
|
7
|
+
|
8
|
+
def setup
|
9
|
+
rate_source ||= get_rate_source
|
10
|
+
Currency::Exchange::Rate::Source.default = rate_source
|
11
|
+
|
12
|
+
# Force non-historical money values.
|
13
|
+
Currency::Money.default_time = nil
|
14
|
+
end
|
15
|
+
|
16
|
+
def get_rate_source
|
17
|
+
source = Currency::Exchange::Rate::Source::Test.instance
|
18
|
+
Currency::Exchange::Rate::Deriver.new(:source => source)
|
19
|
+
end
|
20
|
+
|
21
|
+
Spec::Runner.configure do |config|
|
22
|
+
config.before(:all) {setup}
|
23
|
+
end
|
24
|
+
|
25
|
+
|
@@ -0,0 +1,115 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/spec_helper'
|
2
|
+
|
3
|
+
describe Currency::Exchange::TimeQuantitizerTest do
|
4
|
+
|
5
|
+
def assert_test_day(t0)
|
6
|
+
tq = test_create
|
7
|
+
|
8
|
+
begin
|
9
|
+
t1 = tq.quantitize_time(t0).should_not == nil
|
10
|
+
#$stderr.puts "t0 = #{t0}"
|
11
|
+
#$stderr.puts "t1 = #{t1}"
|
12
|
+
|
13
|
+
t1.year.should == t0.year
|
14
|
+
t1.month.should == t0.month
|
15
|
+
t1.day.should == t0.day
|
16
|
+
assert_time_beginning_of_day(t1)
|
17
|
+
rescue Object => err
|
18
|
+
raise("#{err}\nDuring quantitize_time(#{t0} (#{t0.to_i}))")
|
19
|
+
end
|
20
|
+
|
21
|
+
t1
|
22
|
+
end
|
23
|
+
|
24
|
+
def assert_test_minute(t0)
|
25
|
+
tq = TimeQuantitizer.new(:time_quant_size => 60) # 1 minute
|
26
|
+
|
27
|
+
tq.local_timezone_offset
|
28
|
+
|
29
|
+
t1 = tq.quantitize_time(t0).should_not == nil
|
30
|
+
$stderr.puts "t0 = #{t0}"
|
31
|
+
$stderr.puts "t1 = #{t1}"
|
32
|
+
|
33
|
+
t1.year.should == t0.year
|
34
|
+
t1.month.should == t0.month
|
35
|
+
t1.day.should == t0.day
|
36
|
+
assert_time_beginning_of_day(t1)
|
37
|
+
|
38
|
+
t1
|
39
|
+
end
|
40
|
+
|
41
|
+
|
42
|
+
def assert_time_beginning_of_day(t1)
|
43
|
+
t1.hour.should == 0
|
44
|
+
assert_time_beginning_of_hour(t1)
|
45
|
+
end
|
46
|
+
|
47
|
+
|
48
|
+
def assert_time_beginning_of_hour(t1)
|
49
|
+
t1.min.should == 0
|
50
|
+
assert_time_beginning_of_min(t1)
|
51
|
+
end
|
52
|
+
|
53
|
+
|
54
|
+
def assert_time_beginning_of_min(t1)
|
55
|
+
t1.sec.should == 0
|
56
|
+
endshould_not
|
57
|
+
|
58
|
+
it "create" do
|
59
|
+
tq = TimeQuantitizer.new()
|
60
|
+
tg.should be_kind_of(TimeQuantitizer)
|
61
|
+
tq.time_quant_size.should == 60 * 60 * 24
|
62
|
+
tq.quantitize_time(nil).should == nil
|
63
|
+
end
|
64
|
+
|
65
|
+
|
66
|
+
it "localtime" do
|
67
|
+
t1 = assert_test_day(t0 = Time.new)
|
68
|
+
t1.utc_offset.should == t0.utc_offset
|
69
|
+
t1.utc_offset.should == Time.now.utc_offset
|
70
|
+
end
|
71
|
+
|
72
|
+
|
73
|
+
it "utc" do
|
74
|
+
t1 = assert_test_day(t0 = Time.new.utc)
|
75
|
+
t1.utc_offset.should == t0.utc_offset
|
76
|
+
end
|
77
|
+
|
78
|
+
|
79
|
+
it "random" do
|
80
|
+
(1 .. 1000).each do
|
81
|
+
t0 = Time.at(rand(1234567901).to_i)
|
82
|
+
assert_test_day(t0)
|
83
|
+
assert_test_hour(t0)
|
84
|
+
# Problem year?
|
85
|
+
t0 = Time.parse('1977/01/01') + rand(60 * 60 * 24 * 7 * 52).to_i
|
86
|
+
assert_test_day(t0)
|
87
|
+
assert_test_hour(t0)
|
88
|
+
# Problem year?
|
89
|
+
t0 = Time.parse('1995/01/01') + rand(60 * 60 * 24 * 7 * 52).to_i
|
90
|
+
assert_test_day(t0)
|
91
|
+
assert_test_hour(t0)
|
92
|
+
end
|
93
|
+
|
94
|
+
|
95
|
+
end
|
96
|
+
|
97
|
+
|
98
|
+
def assert_test_hour(t0)
|
99
|
+
tq = TimeQuantitizer.new(:time_quant_size => 60 * 60) # 1 hour
|
100
|
+
|
101
|
+
t1 = tq.quantitize_time(t0).should_not == nil
|
102
|
+
#$stderr.puts "t0 = #{t0}"
|
103
|
+
#$stderr.puts "t1 = #{t1}"
|
104
|
+
|
105
|
+
t1.year.should == t0.year
|
106
|
+
t1.month.should == t0.month
|
107
|
+
t1.day.should == t0.day
|
108
|
+
assert_time_beginning_of_hour(t1)
|
109
|
+
|
110
|
+
t1
|
111
|
+
end
|
112
|
+
|
113
|
+
end # class
|
114
|
+
|
115
|
+
|
@@ -0,0 +1,95 @@
|
|
1
|
+
# Copyright (C) 2006-2007 Kurt Stephens <ruby-currency(at)umleta.com>
|
2
|
+
# See LICENSE.txt for details.
|
3
|
+
|
4
|
+
require 'test/test_base'
|
5
|
+
|
6
|
+
require 'currency'
|
7
|
+
require 'currency/exchange/rate/source/xe'
|
8
|
+
require 'currency/exchange/rate/source/timed_cache'
|
9
|
+
|
10
|
+
module Currency
|
11
|
+
|
12
|
+
class TimedCacheTest < TestBase
|
13
|
+
before do
|
14
|
+
super
|
15
|
+
end
|
16
|
+
|
17
|
+
|
18
|
+
def get_rate_source
|
19
|
+
@source = source = Exchange::Rate::Source::Xe.new
|
20
|
+
|
21
|
+
# source.verbose = true
|
22
|
+
deriver = Exchange::Rate::Deriver.new(:source => source)
|
23
|
+
|
24
|
+
@cache = cache = Exchange::Rate::Source::TimedCache.new(:source => deriver)
|
25
|
+
|
26
|
+
cache
|
27
|
+
end
|
28
|
+
|
29
|
+
|
30
|
+
it "timed cache usd cad" do
|
31
|
+
rates = @source.raw_rates.should.not == nil
|
32
|
+
rates[:USD].should.not == nil
|
33
|
+
usd_cad = rates[:USD][:CAD].should.not == nil
|
34
|
+
|
35
|
+
usd = Money.new(123.45, :USD).should.not == nil
|
36
|
+
cad = usd.convert(:CAD).should.not == nil
|
37
|
+
|
38
|
+
assert_kind_of Numeric, m = (cad.to_f / usd.to_f)
|
39
|
+
# $stderr.puts "m = #{m}"
|
40
|
+
assert_equal_float usd_cad, m, 0.001
|
41
|
+
end
|
42
|
+
|
43
|
+
|
44
|
+
it "timed cache cad eur" do
|
45
|
+
rates = @source.raw_rates.should.not == nil
|
46
|
+
rates[:USD].should.not == nil
|
47
|
+
usd_cad = rates[:USD][:CAD].should.not == nil
|
48
|
+
usd_eur = rates[:USD][:EUR].should.not == nil
|
49
|
+
|
50
|
+
cad = Money.new(123.45, :CAD).should.not == nil
|
51
|
+
eur = cad.convert(:EUR).should.not == nil
|
52
|
+
|
53
|
+
assert_kind_of Numeric, m = (eur.to_f / cad.to_f)
|
54
|
+
# $stderr.puts "m = #{m}"
|
55
|
+
assert_equal_float((1.0 / usd_cad) * usd_eur, m, 0.001)
|
56
|
+
end
|
57
|
+
|
58
|
+
|
59
|
+
it "reload" do
|
60
|
+
# @cache.verbose = 5
|
61
|
+
|
62
|
+
test_timed_cache_cad_eur
|
63
|
+
|
64
|
+
rates = @source.raw_rates.should.not == nil
|
65
|
+
rates[:USD].should.not == nil
|
66
|
+
usd_cad_1 = rates[:USD][:CAD].should.not == nil
|
67
|
+
|
68
|
+
t1 = @cache.rate_load_time.should.not == nil
|
69
|
+
t1_reload = @cache.rate_reload_time.should.not == nil
|
70
|
+
t1_reload.to_i.should > t1.to_i
|
71
|
+
|
72
|
+
@cache.time_to_live = 5
|
73
|
+
@cache.time_to_live_fudge = 0
|
74
|
+
|
75
|
+
# puts @cache.rate_reload_time.to_i - @cache.rate_load_time.to_i
|
76
|
+
@cache.rate_reload_time.to_i - @cache.rate_load_time.to_i == @cache.time_to_live.should.not == nil
|
77
|
+
|
78
|
+
sleep 10
|
79
|
+
|
80
|
+
test_timed_cache_cad_eur
|
81
|
+
|
82
|
+
t2 = @cache.rate_load_time.should.not == nil
|
83
|
+
t1.to_i != t2.to_i.should.not == nil
|
84
|
+
|
85
|
+
rates = @source.raw_rates.should.not == nil
|
86
|
+
rates[:USD].should.not == nil
|
87
|
+
usd_cad_2 = rates[:USD][:CAD].should.not == nil
|
88
|
+
|
89
|
+
usd_cad_1.object_id != usd_cad_2.object_id.should.not == nil
|
90
|
+
end
|
91
|
+
|
92
|
+
end
|
93
|
+
|
94
|
+
end # module
|
95
|
+
|
data/spec/xe_spec.rb
ADDED
@@ -0,0 +1,50 @@
|
|
1
|
+
# Copyright (C) 2006-2007 Kurt Stephens <ruby-currency(at)umleta.com>
|
2
|
+
# See LICENSE.txt for details.
|
3
|
+
|
4
|
+
require 'currency/exchange/rate/source/xe'
|
5
|
+
|
6
|
+
describe Currency::Exchange::Rate::Source::XE do
|
7
|
+
|
8
|
+
before(:all) do
|
9
|
+
get_rate_source
|
10
|
+
end
|
11
|
+
|
12
|
+
def get_rate_source
|
13
|
+
source = Currency::Exchange::Rate::Source::XE.new
|
14
|
+
Currency::Exchange::Rate::Deriver.new(:source => source)
|
15
|
+
end
|
16
|
+
|
17
|
+
it "xe usd cad" do
|
18
|
+
rates = Currency::Exchange::Rate::Source.default.source.raw_rates
|
19
|
+
rates.should_not == nil
|
20
|
+
rates[:USD].should_not == nil
|
21
|
+
usd_cad = rates[:USD][:CAD].should_not == nil
|
22
|
+
|
23
|
+
usd = Currency::Money.new(123.45, :USD)
|
24
|
+
usd.should_not == nil
|
25
|
+
cad = usd.convert(:CAD).should_not == nil
|
26
|
+
|
27
|
+
m = (cad.to_f / usd.to_f)
|
28
|
+
m.should be_kind_of(Numeric)
|
29
|
+
m.should be_close(usd_cad, 0.001)
|
30
|
+
end
|
31
|
+
|
32
|
+
|
33
|
+
it "xe cad eur" do
|
34
|
+
rates = Currency::Exchange::Rate::Source.default.source.raw_rates
|
35
|
+
rates.should_not == nil
|
36
|
+
rates[:USD].should_not == nil
|
37
|
+
usd_cad = rates[:USD][:CAD].should_not == nil
|
38
|
+
usd_eur = rates[:USD][:EUR].should_not == nil
|
39
|
+
|
40
|
+
cad = Currency::Money.new(123.45, :CAD)
|
41
|
+
cad.should_not == nil
|
42
|
+
eur = cad.convert(:EUR)
|
43
|
+
eur.should_not == nil
|
44
|
+
|
45
|
+
m = (eur.to_f / cad.to_f)
|
46
|
+
m.should be_kind_of(Numeric)
|
47
|
+
m.should be_close((1.0 / usd_cad) * usd_eur, 0.001)
|
48
|
+
end
|
49
|
+
|
50
|
+
end
|