temporal 0.4.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +4 -0
- data/Gemfile +2 -0
- data/Gemfile.lock +27 -0
- data/README.txt +6 -0
- data/Rakefile +9 -0
- data/lib/temporal/anomaly.rb +4 -0
- data/lib/temporal/helpers.rb +12 -0
- data/lib/temporal/mathematics.rb +92 -0
- data/lib/temporal/parser/afrikaans.rb +24 -0
- data/lib/temporal/parser/english.rb +24 -0
- data/lib/temporal/parser.rb +37 -0
- data/lib/temporal/shift.rb +163 -0
- data/lib/temporal/version.rb +3 -0
- data/lib/temporal.rb +7 -0
- data/temporal.gemspec +24 -0
- data/test/days.rb +56 -0
- data/test/hours.rb +17 -0
- data/test/minutes.rb +17 -0
- data/test/months.rb +19 -0
- data/test/seconds.rb +17 -0
- data/test/weeks.rb +16 -0
- data/test/years.rb +7 -0
- metadata +132 -0
data/.gitignore
ADDED
data/Gemfile
ADDED
data/Gemfile.lock
ADDED
@@ -0,0 +1,27 @@
|
|
1
|
+
PATH
|
2
|
+
remote: .
|
3
|
+
specs:
|
4
|
+
temporal (0.4.0)
|
5
|
+
|
6
|
+
GEM
|
7
|
+
remote: http://rubygems.org/
|
8
|
+
specs:
|
9
|
+
diff-lcs (1.1.2)
|
10
|
+
rake (0.8.7)
|
11
|
+
rspec (2.4.0)
|
12
|
+
rspec-core (~> 2.4.0)
|
13
|
+
rspec-expectations (~> 2.4.0)
|
14
|
+
rspec-mocks (~> 2.4.0)
|
15
|
+
rspec-core (2.4.0)
|
16
|
+
rspec-expectations (2.4.0)
|
17
|
+
diff-lcs (~> 1.1.2)
|
18
|
+
rspec-mocks (2.4.0)
|
19
|
+
|
20
|
+
PLATFORMS
|
21
|
+
ruby
|
22
|
+
|
23
|
+
DEPENDENCIES
|
24
|
+
bundler (>= 1.0.0)
|
25
|
+
rake (>= 0.8.7)
|
26
|
+
rspec (>= 1.3.0)
|
27
|
+
temporal!
|
data/README.txt
ADDED
data/Rakefile
ADDED
@@ -0,0 +1,12 @@
|
|
1
|
+
[Numeric,Range].each do |klass|
|
2
|
+
Temporal::Mathematics.units( klass )
|
3
|
+
Temporal::Mathematics.operators( klass )
|
4
|
+
end
|
5
|
+
|
6
|
+
[Time].each do |klass|
|
7
|
+
Temporal::Mathematics.operators( klass )
|
8
|
+
end
|
9
|
+
|
10
|
+
[Range].each do |klass|
|
11
|
+
Temporal::Mathematics.negation( klass )
|
12
|
+
end
|
@@ -0,0 +1,92 @@
|
|
1
|
+
module Temporal
|
2
|
+
module Mathematics
|
3
|
+
|
4
|
+
def self.units klass
|
5
|
+
klass.class_eval do
|
6
|
+
Temporal::Shift.units.each do |unit|
|
7
|
+
if klass == Range
|
8
|
+
define_method unit do
|
9
|
+
if exclude_end?
|
10
|
+
return Temporal::Shift.new( first, unit )...Temporal::Shift.new( last, unit )
|
11
|
+
else
|
12
|
+
return Temporal::Shift.new( first, unit )..Temporal::Shift.new( last, unit )
|
13
|
+
end
|
14
|
+
end
|
15
|
+
else
|
16
|
+
define_method unit do
|
17
|
+
Temporal::Shift.new( self, unit )
|
18
|
+
end
|
19
|
+
end
|
20
|
+
define_method "#{unit}s" do
|
21
|
+
send(unit)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
def self.negation klass
|
28
|
+
klass.class_eval do
|
29
|
+
begin
|
30
|
+
alias :temporal_negation :-@
|
31
|
+
rescue
|
32
|
+
def temporal_negation
|
33
|
+
raise NoMethodError.new( "undefined method `-@' for #{self.to_s}:#{self.class.to_s}" )
|
34
|
+
end
|
35
|
+
end
|
36
|
+
def -@
|
37
|
+
return temporal_negation unless self.class == Temporal::Shift or self.class == Range
|
38
|
+
if exclude_end?
|
39
|
+
-first...-last
|
40
|
+
else
|
41
|
+
-first..-last
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
def self.operators klass
|
48
|
+
klass.class_eval do
|
49
|
+
begin
|
50
|
+
alias :temporal_addition :+
|
51
|
+
rescue
|
52
|
+
def temporal_addition target
|
53
|
+
raise NoMethodError.new( "undefined method `+' for #{self.to_s}:#{self.class.to_s}" )
|
54
|
+
end
|
55
|
+
end
|
56
|
+
def + target
|
57
|
+
if target.class == Range
|
58
|
+
if self.class == Range
|
59
|
+
raise Temporal::Anomaly.new( "Missmatched Range end exclusions" ) if exclude_end? != target.exclude_end?
|
60
|
+
if target.exclude_end?
|
61
|
+
return (target.first + first)...(target.last + last)
|
62
|
+
else
|
63
|
+
return (target.first + first)..(target.last + last)
|
64
|
+
end
|
65
|
+
else
|
66
|
+
if target.exclude_end?
|
67
|
+
return (target.first + self)...(target.last + self)
|
68
|
+
else
|
69
|
+
return (target.first + self)..(target.last + self)
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
73
|
+
return temporal_addition( target ) unless target.class == Temporal::Shift
|
74
|
+
target + self
|
75
|
+
end
|
76
|
+
|
77
|
+
begin
|
78
|
+
alias :temporal_subtraction :-
|
79
|
+
rescue
|
80
|
+
def temporal_subtraction target
|
81
|
+
raise NoMethodError.new( "undefined method `-' for #{self.to_s}:#{self.class.to_s}" )
|
82
|
+
end
|
83
|
+
end
|
84
|
+
def - target
|
85
|
+
return temporal_subtraction( target ) unless target.class == Temporal::Shift or target.class == Range
|
86
|
+
(-target) + self
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
end
|
92
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
module Temporal
|
2
|
+
class Parser
|
3
|
+
|
4
|
+
add_literal( /(^|\W)noe(\W|$)/i ) do
|
5
|
+
Time.now
|
6
|
+
end
|
7
|
+
|
8
|
+
add_literal( /(^|\W)vandag(\W|$)/i ) do
|
9
|
+
today_start = Time.parse(Time.now.strftime("%Y-%m-%d"))
|
10
|
+
today_start...today_start+1.day
|
11
|
+
end
|
12
|
+
|
13
|
+
add_literal( /(^|\W)gister(\W|$)/i ) do
|
14
|
+
yesterday_start = Time.parse((Time.now-1.day).strftime("%Y-%m-%d"))
|
15
|
+
yesterday_start...yesterday_start+1.day
|
16
|
+
end
|
17
|
+
|
18
|
+
add_literal( /(^|\W)more(\W|$)/i ) do
|
19
|
+
tomorrow_start = Time.parse((Time.now+1.day).strftime("%Y-%m-%d"))
|
20
|
+
tomorrow_start...tomorrow_start+1.day
|
21
|
+
end
|
22
|
+
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
module Temporal
|
2
|
+
class Parser
|
3
|
+
|
4
|
+
add_literal( /(^|\W)now(\W|$)/i ) do
|
5
|
+
Time.now
|
6
|
+
end
|
7
|
+
|
8
|
+
add_literal( /(^|\W)today(\W|$)/i ) do
|
9
|
+
today_start = Time.parse(Time.now.strftime("%Y-%m-%d"))
|
10
|
+
today_start...today_start+1.day
|
11
|
+
end
|
12
|
+
|
13
|
+
add_literal( /(^|\W)yesterday(\W|$)/i ) do
|
14
|
+
yesterday_start = Time.parse((Time.now-1.day).strftime("%Y-%m-%d"))
|
15
|
+
yesterday_start...yesterday_start+1.day
|
16
|
+
end
|
17
|
+
|
18
|
+
add_literal( /(^|\W)tomorrow(\W|$)/i ) do
|
19
|
+
tomorrow_start = Time.parse((Time.now+1.day).strftime("%Y-%m-%d"))
|
20
|
+
tomorrow_start...tomorrow_start+1.day
|
21
|
+
end
|
22
|
+
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
module Temporal
|
2
|
+
class Parser
|
3
|
+
@@literals = {}
|
4
|
+
|
5
|
+
def self.add_literal literal, &block
|
6
|
+
@@literals[ literal ] = block
|
7
|
+
end
|
8
|
+
|
9
|
+
def self.match? string
|
10
|
+
to_match = string.downcase.strip
|
11
|
+
@@literals.keys.each do |key|
|
12
|
+
return true if to_match =~ key
|
13
|
+
end
|
14
|
+
return false
|
15
|
+
end
|
16
|
+
|
17
|
+
def self.parse string
|
18
|
+
@@literals.keys.each do |key|
|
19
|
+
match = string.match(key)
|
20
|
+
next unless match
|
21
|
+
result = []
|
22
|
+
result << parse(match.pre_match) if match.pre_match.strip.size > 0
|
23
|
+
result << @@literals[key].call
|
24
|
+
result << parse(match.post_match) if match.post_match.strip.size > 0
|
25
|
+
result.flatten!
|
26
|
+
if result.empty?
|
27
|
+
result = nil
|
28
|
+
else
|
29
|
+
result = result.pop if result.size == 1
|
30
|
+
end
|
31
|
+
return result
|
32
|
+
end
|
33
|
+
string
|
34
|
+
end
|
35
|
+
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,163 @@
|
|
1
|
+
module Temporal
|
2
|
+
class Shift
|
3
|
+
|
4
|
+
include Comparable
|
5
|
+
|
6
|
+
MINUTE = 60
|
7
|
+
HOUR = MINUTE * 60
|
8
|
+
DAY = HOUR * 24
|
9
|
+
WEEK = DAY * 7
|
10
|
+
|
11
|
+
YEAR = 12
|
12
|
+
|
13
|
+
MAX_MONTH_DAY = %w|31 0 31 30 31 30 31 31 30 31 30 31|.map{|n|n.to_i} # Don't worry about February
|
14
|
+
|
15
|
+
attr_accessor :seconds
|
16
|
+
attr_accessor :months
|
17
|
+
|
18
|
+
def initialize amount, unit
|
19
|
+
unless self.class.unit?( unit )
|
20
|
+
raise Temporal::Anomaly.new( "Bad #{self.class}.unit type of `#{unit}' given" )
|
21
|
+
end
|
22
|
+
|
23
|
+
@seconds = 0
|
24
|
+
@months = 0
|
25
|
+
|
26
|
+
unit = unit.to_s.downcase
|
27
|
+
unit.chop! if unit[-1..-1] == 's'
|
28
|
+
unit = unit.to_sym
|
29
|
+
|
30
|
+
case unit
|
31
|
+
when :second
|
32
|
+
@seconds = amount
|
33
|
+
when :minute
|
34
|
+
@seconds = amount * MINUTE
|
35
|
+
when :hour
|
36
|
+
@seconds = amount * HOUR
|
37
|
+
when :day
|
38
|
+
@seconds = amount * DAY
|
39
|
+
when :week
|
40
|
+
@seconds = amount * WEEK
|
41
|
+
when :month
|
42
|
+
@months = amount
|
43
|
+
when :year
|
44
|
+
@months = amount * YEAR
|
45
|
+
else
|
46
|
+
raise Temporal::Anomaly.new( "Internal Error, failed to catch bad #{self.class}.unit type of `#{unit}' given" )
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
def <=> target
|
51
|
+
return 1 if @months > target.months
|
52
|
+
return -1 if @months < target.months
|
53
|
+
return 1 if @seconds > target.seconds
|
54
|
+
return -1 if @seconds < target.seconds
|
55
|
+
0
|
56
|
+
end
|
57
|
+
|
58
|
+
def self.units
|
59
|
+
%w|second minute hour day week month year|
|
60
|
+
end
|
61
|
+
|
62
|
+
def self.unit? unit
|
63
|
+
(unit.to_s.strip.downcase =~ /^(#{units.join('|')})s?$/) != nil
|
64
|
+
end
|
65
|
+
|
66
|
+
def + to_be_added
|
67
|
+
|
68
|
+
if to_be_added.class == self.class
|
69
|
+
result_instance = self.class.new( @seconds + to_be_added.seconds, :seconds )
|
70
|
+
result_instance.months = @months + to_be_added.months
|
71
|
+
return result_instance
|
72
|
+
end
|
73
|
+
|
74
|
+
if to_be_added.class == Time
|
75
|
+
new_time = (to_be_added + @seconds).localtime
|
76
|
+
new_year = new_time.year+(((new_time.month-1)+months)/12)
|
77
|
+
new_month = (((new_time.month-1)+months)%12)
|
78
|
+
new_day = new_time.day
|
79
|
+
if new_month == 1
|
80
|
+
if (new_year%4 == 0 and new_year%100 != 0) or new_year%400 == 0
|
81
|
+
max_mday = 29
|
82
|
+
else
|
83
|
+
max_mday = 28
|
84
|
+
end
|
85
|
+
else
|
86
|
+
max_mday = MAX_MONTH_DAY[ new_month ];
|
87
|
+
end
|
88
|
+
new_day = max_mday if new_day > max_mday
|
89
|
+
return Time.local( new_year, new_month+1 , new_day, new_time.hour, new_time.min, new_time.sec, new_time.usec )
|
90
|
+
end
|
91
|
+
|
92
|
+
if to_be_added.class == Range
|
93
|
+
new_first = self + to_be_added.first
|
94
|
+
new_last = self + to_be_added.last
|
95
|
+
if to_be_added.exclude_end?
|
96
|
+
return new_first...new_last
|
97
|
+
else
|
98
|
+
return new_first..new_last
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
raise Temporal::Anomaly.new( "Unable to add #{self.class} to instances of `#{to_be_added.class}'" )
|
103
|
+
end
|
104
|
+
|
105
|
+
def -@
|
106
|
+
negated = self.class.new( -@seconds, :seconds )
|
107
|
+
negated.months = -@months
|
108
|
+
return negated
|
109
|
+
end
|
110
|
+
|
111
|
+
def - to_be_subtracted
|
112
|
+
begin
|
113
|
+
self + ( -to_be_subtracted )
|
114
|
+
rescue Exception => e
|
115
|
+
raise Temporal::Anomaly.new( "Unable to subtract an instance of #{to_be_subtracted.class} from #{self.class}" )
|
116
|
+
end
|
117
|
+
end
|
118
|
+
|
119
|
+
def to_s
|
120
|
+
result = {}
|
121
|
+
|
122
|
+
result[:months] = @months
|
123
|
+
|
124
|
+
result[:years] = (result[:months]/12).truncate
|
125
|
+
result[:months] = result[:months] - ( result[:years] * 12 )
|
126
|
+
result[:months] = result[:months].truncate if result[:months].modulo(1) == 0
|
127
|
+
|
128
|
+
result[:seconds] = @seconds
|
129
|
+
|
130
|
+
result[:weeks] = (result[:seconds] / WEEK).truncate
|
131
|
+
result[:seconds] = result[:seconds] - (result[:weeks] * WEEK)
|
132
|
+
result[:days] = (result[:seconds] / DAY).truncate
|
133
|
+
result[:seconds] = result[:seconds] - (result[:days] * DAY)
|
134
|
+
result[:hours] = (result[:seconds] / HOUR).truncate
|
135
|
+
result[:seconds] = result[:seconds] - (result[:hours] * HOUR)
|
136
|
+
result[:minutes] = (result[:seconds] / MINUTE).truncate
|
137
|
+
result[:seconds] = result[:seconds] - (result[:minutes] * MINUTE)
|
138
|
+
result[:seconds] = result[:seconds].truncate if result[:seconds].modulo(1) == 0
|
139
|
+
|
140
|
+
result = Hash[ *result.select{|unit, amount| amount != 0 }.flatten ]
|
141
|
+
|
142
|
+
string = ""
|
143
|
+
|
144
|
+
%w|years months weeks days hours minutes seconds|.each do |unit|
|
145
|
+
unit = unit.to_sym
|
146
|
+
next unless result.has_key?( unit )
|
147
|
+
string += "#{result[ unit ]} #{unit}"
|
148
|
+
string.chop! if result[ unit ].abs == 1
|
149
|
+
result.delete( unit )
|
150
|
+
break if result.size == 0
|
151
|
+
if result.size == 1
|
152
|
+
string += " and "
|
153
|
+
else
|
154
|
+
string += ", "
|
155
|
+
end
|
156
|
+
end
|
157
|
+
|
158
|
+
string
|
159
|
+
end
|
160
|
+
|
161
|
+
end
|
162
|
+
|
163
|
+
end
|
data/lib/temporal.rb
ADDED
data/temporal.gemspec
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
require File.expand_path("../lib/temporal/version", __FILE__)
|
3
|
+
|
4
|
+
Gem::Specification.new do |s|
|
5
|
+
s.name = "temporal"
|
6
|
+
s.version = Temporal::VERSION
|
7
|
+
s.platform = Gem::Platform::RUBY
|
8
|
+
s.authors = ["Clive Crous"]
|
9
|
+
s.email = ["clive@crous.co.za"]
|
10
|
+
s.homepage = "http://www.darkarts.co.za/temporal"
|
11
|
+
s.summary = "A natural language date and time parser"
|
12
|
+
s.description = "This project is still in early development. Only the mathematical side is complete. eg: Time.now + 3.years + 2.months"
|
13
|
+
|
14
|
+
s.required_rubygems_version = ">= 1.3.6"
|
15
|
+
s.rubyforge_project = "temporal"
|
16
|
+
|
17
|
+
s.add_development_dependency "bundler", ">= 1.0.0"
|
18
|
+
s.add_development_dependency "rspec", ">= 1.3.0"
|
19
|
+
s.add_development_dependency "rake", ">= 0.8.7"
|
20
|
+
|
21
|
+
s.files = `git ls-files`.split("\n")
|
22
|
+
s.executables = `git ls-files`.split("\n").map{|f| f =~ /^bin\/(.*)/ ? $1 : nil}.compact
|
23
|
+
s.require_path = 'lib'
|
24
|
+
end
|
data/test/days.rb
ADDED
@@ -0,0 +1,56 @@
|
|
1
|
+
require 'temporal'
|
2
|
+
|
3
|
+
describe 'Temporal math with days' do
|
4
|
+
|
5
|
+
before do
|
6
|
+
@context = Time.local( 1975, 05, 13, 01, 23, 45)
|
7
|
+
end
|
8
|
+
|
9
|
+
it 'should add a day' do
|
10
|
+
( @context + 1.day ).should == Time.local( 1975, 05, 14, 01, 23, 45)
|
11
|
+
end
|
12
|
+
|
13
|
+
it 'should subtract a day' do
|
14
|
+
( @context - 1.day ).should == Time.local( 1975, 05, 12, 01, 23, 45)
|
15
|
+
end
|
16
|
+
|
17
|
+
it 'should add days' do
|
18
|
+
( @context + 2.days ).should == Time.local( 1975, 05, 15, 01, 23, 45)
|
19
|
+
end
|
20
|
+
|
21
|
+
it 'should subtract days' do
|
22
|
+
( @context - 2.days ).should == Time.local( 1975, 05, 11, 01, 23, 45)
|
23
|
+
end
|
24
|
+
|
25
|
+
it 'should wrap months while adding' do
|
26
|
+
( Time.local( 1975, 05, 31, 01, 23, 45 ) + 1.day ).should == Time.local( 1975, 06, 1, 01, 23, 45 )
|
27
|
+
end
|
28
|
+
|
29
|
+
it 'should wrap months while subtracting' do
|
30
|
+
( Time.local( 1975, 05, 1, 01, 23, 45 ) - 1.day ).should == Time.local( 1975, 04, 30, 01, 23, 45 )
|
31
|
+
end
|
32
|
+
|
33
|
+
it 'should wrap years while adding' do
|
34
|
+
( Time.local( 1975, 12, 31, 01, 23, 45 ) + 1.day ).should == Time.local( 1976, 01, 01, 01, 23, 45 )
|
35
|
+
end
|
36
|
+
|
37
|
+
it 'should wrap years while subtracting' do
|
38
|
+
( Time.local( 1975, 01, 01, 01, 23, 45 ) - 1.day ).should == Time.local( 1974, 12, 31, 01, 23, 45 )
|
39
|
+
end
|
40
|
+
|
41
|
+
end
|
42
|
+
|
43
|
+
describe 'One day in other units' do
|
44
|
+
it 'is 86400 seconds' do
|
45
|
+
1.day.should == 86400.seconds
|
46
|
+
end
|
47
|
+
it 'is 1440 minutes' do
|
48
|
+
1.day.should == 1440.minutes
|
49
|
+
end
|
50
|
+
it 'is 24 hours' do
|
51
|
+
1.day.should == 24.hours
|
52
|
+
end
|
53
|
+
it 'is 1/7th of a week' do
|
54
|
+
1.day.should == (1.0/7).weeks
|
55
|
+
end
|
56
|
+
end
|
data/test/hours.rb
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
require 'temporal'
|
2
|
+
|
3
|
+
describe 'One hour in other units' do
|
4
|
+
it 'is 3600 seconds' do
|
5
|
+
1.hour.should == 3600.seconds
|
6
|
+
end
|
7
|
+
it 'is 60 minutes' do
|
8
|
+
1.hour.should == 60.minutes
|
9
|
+
end
|
10
|
+
it 'is 1/24th of a day' do
|
11
|
+
1.hour.should == (1.0/24).days
|
12
|
+
end
|
13
|
+
it 'is 1/168th of a week' do
|
14
|
+
1.hour.should == (1.0/168).weeks
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
data/test/minutes.rb
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
require 'temporal'
|
2
|
+
|
3
|
+
describe 'One minute in other units' do
|
4
|
+
it 'is 60 seconds' do
|
5
|
+
1.minute.should == 60.seconds
|
6
|
+
end
|
7
|
+
it 'is 1/60th of an hour' do
|
8
|
+
1.minute.should == (1.0/60).hours
|
9
|
+
end
|
10
|
+
it 'is 1/1440th of a day' do
|
11
|
+
1.minute.should == (1.0/1440).days
|
12
|
+
end
|
13
|
+
it 'is 1/10080th of a week' do
|
14
|
+
1.minute.should == (1.0/10080).weeks
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
data/test/months.rb
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
require 'temporal'
|
2
|
+
|
3
|
+
describe 'Temporal math with months' do
|
4
|
+
|
5
|
+
it 'should wrap years while adding' do
|
6
|
+
( Time.local( 1975, 8, 1 ) + 5.months ).should == Time.local( 1976, 1, 1 )
|
7
|
+
end
|
8
|
+
|
9
|
+
it 'should not wrap years while adding 1 month to november' do
|
10
|
+
( Time.local( 1975, 11, 1 ) + 1.month ).should == Time.local( 1975, 12, 1 )
|
11
|
+
end
|
12
|
+
|
13
|
+
end
|
14
|
+
|
15
|
+
describe 'One month in other units' do
|
16
|
+
it 'is 1/12th of a year' do
|
17
|
+
1.month.should == (1.0/12).years
|
18
|
+
end
|
19
|
+
end
|
data/test/seconds.rb
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
require 'temporal'
|
2
|
+
|
3
|
+
describe 'One second in other units' do
|
4
|
+
it 'is 1/60th of a minute' do
|
5
|
+
1.second.should == (1.0/60).minutes
|
6
|
+
end
|
7
|
+
it 'is 1/3600th of a hour' do
|
8
|
+
1.second.should == (1.0/3600).hours
|
9
|
+
end
|
10
|
+
it 'is 1/86400th of a day' do
|
11
|
+
1.second.should == (1.0/86400).days
|
12
|
+
end
|
13
|
+
it 'is 1/604800th of a week' do
|
14
|
+
1.second.should == (1.0/604800).weeks
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
data/test/weeks.rb
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
require 'temporal'
|
2
|
+
|
3
|
+
describe 'One week in other units' do
|
4
|
+
it 'is 604800 seconds' do
|
5
|
+
1.week.should == 604800.seconds
|
6
|
+
end
|
7
|
+
it 'is 10080 minutes' do
|
8
|
+
1.week.should == 10080.minutes
|
9
|
+
end
|
10
|
+
it 'is 168 hours' do
|
11
|
+
1.week.should == 168.hours
|
12
|
+
end
|
13
|
+
it 'is 7 days' do
|
14
|
+
1.week.should == 7.days
|
15
|
+
end
|
16
|
+
end
|
data/test/years.rb
ADDED
metadata
ADDED
@@ -0,0 +1,132 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: temporal
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
prerelease: false
|
5
|
+
segments:
|
6
|
+
- 0
|
7
|
+
- 4
|
8
|
+
- 0
|
9
|
+
version: 0.4.0
|
10
|
+
platform: ruby
|
11
|
+
authors:
|
12
|
+
- Clive Crous
|
13
|
+
autorequire:
|
14
|
+
bindir: bin
|
15
|
+
cert_chain: []
|
16
|
+
|
17
|
+
date: 2011-01-18 00:00:00 +02:00
|
18
|
+
default_executable:
|
19
|
+
dependencies:
|
20
|
+
- !ruby/object:Gem::Dependency
|
21
|
+
name: bundler
|
22
|
+
prerelease: false
|
23
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
24
|
+
none: false
|
25
|
+
requirements:
|
26
|
+
- - ">="
|
27
|
+
- !ruby/object:Gem::Version
|
28
|
+
segments:
|
29
|
+
- 1
|
30
|
+
- 0
|
31
|
+
- 0
|
32
|
+
version: 1.0.0
|
33
|
+
type: :development
|
34
|
+
version_requirements: *id001
|
35
|
+
- !ruby/object:Gem::Dependency
|
36
|
+
name: rspec
|
37
|
+
prerelease: false
|
38
|
+
requirement: &id002 !ruby/object:Gem::Requirement
|
39
|
+
none: false
|
40
|
+
requirements:
|
41
|
+
- - ">="
|
42
|
+
- !ruby/object:Gem::Version
|
43
|
+
segments:
|
44
|
+
- 1
|
45
|
+
- 3
|
46
|
+
- 0
|
47
|
+
version: 1.3.0
|
48
|
+
type: :development
|
49
|
+
version_requirements: *id002
|
50
|
+
- !ruby/object:Gem::Dependency
|
51
|
+
name: rake
|
52
|
+
prerelease: false
|
53
|
+
requirement: &id003 !ruby/object:Gem::Requirement
|
54
|
+
none: false
|
55
|
+
requirements:
|
56
|
+
- - ">="
|
57
|
+
- !ruby/object:Gem::Version
|
58
|
+
segments:
|
59
|
+
- 0
|
60
|
+
- 8
|
61
|
+
- 7
|
62
|
+
version: 0.8.7
|
63
|
+
type: :development
|
64
|
+
version_requirements: *id003
|
65
|
+
description: "This project is still in early development. Only the mathematical side is complete. eg: Time.now + 3.years + 2.months"
|
66
|
+
email:
|
67
|
+
- clive@crous.co.za
|
68
|
+
executables: []
|
69
|
+
|
70
|
+
extensions: []
|
71
|
+
|
72
|
+
extra_rdoc_files: []
|
73
|
+
|
74
|
+
files:
|
75
|
+
- .gitignore
|
76
|
+
- Gemfile
|
77
|
+
- Gemfile.lock
|
78
|
+
- README.txt
|
79
|
+
- Rakefile
|
80
|
+
- lib/temporal.rb
|
81
|
+
- lib/temporal/anomaly.rb
|
82
|
+
- lib/temporal/helpers.rb
|
83
|
+
- lib/temporal/mathematics.rb
|
84
|
+
- lib/temporal/parser.rb
|
85
|
+
- lib/temporal/parser/afrikaans.rb
|
86
|
+
- lib/temporal/parser/english.rb
|
87
|
+
- lib/temporal/shift.rb
|
88
|
+
- lib/temporal/version.rb
|
89
|
+
- temporal.gemspec
|
90
|
+
- test/days.rb
|
91
|
+
- test/hours.rb
|
92
|
+
- test/minutes.rb
|
93
|
+
- test/months.rb
|
94
|
+
- test/seconds.rb
|
95
|
+
- test/weeks.rb
|
96
|
+
- test/years.rb
|
97
|
+
has_rdoc: true
|
98
|
+
homepage: http://www.darkarts.co.za/temporal
|
99
|
+
licenses: []
|
100
|
+
|
101
|
+
post_install_message:
|
102
|
+
rdoc_options: []
|
103
|
+
|
104
|
+
require_paths:
|
105
|
+
- lib
|
106
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
107
|
+
none: false
|
108
|
+
requirements:
|
109
|
+
- - ">="
|
110
|
+
- !ruby/object:Gem::Version
|
111
|
+
segments:
|
112
|
+
- 0
|
113
|
+
version: "0"
|
114
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
115
|
+
none: false
|
116
|
+
requirements:
|
117
|
+
- - ">="
|
118
|
+
- !ruby/object:Gem::Version
|
119
|
+
segments:
|
120
|
+
- 1
|
121
|
+
- 3
|
122
|
+
- 6
|
123
|
+
version: 1.3.6
|
124
|
+
requirements: []
|
125
|
+
|
126
|
+
rubyforge_project: temporal
|
127
|
+
rubygems_version: 1.3.7
|
128
|
+
signing_key:
|
129
|
+
specification_version: 3
|
130
|
+
summary: A natural language date and time parser
|
131
|
+
test_files: []
|
132
|
+
|