timeframes 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +5 -0
- data/.rvmrc +1 -0
- data/Gemfile +4 -0
- data/README.markdown +45 -0
- data/Rakefile +2 -0
- data/lib/timeframes.rb +9 -0
- data/lib/timeframes/frame.rb +67 -0
- data/lib/timeframes/series.rb +171 -0
- data/lib/timeframes/version.rb +3 -0
- data/spec/spec_helper.rb +2 -0
- data/spec/timeframe_series_spec.rb +74 -0
- data/spec/timeframe_spec.rb +45 -0
- data/timeframes.gemspec +25 -0
- metadata +92 -0
data/.gitignore
ADDED
data/.rvmrc
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
rvm use --create 1.9.2@date_series
|
data/Gemfile
ADDED
data/README.markdown
ADDED
@@ -0,0 +1,45 @@
|
|
1
|
+
Timeframes
|
2
|
+
====
|
3
|
+
|
4
|
+
Timeframes is a library to handle two points in time and easily parse and manipulate a series of timeframes. It provides two new classes, Timeframe and TimeframeSeries. Timeframes have a start and stop point in time and a series of common helpers to handle processing between those points in time. TimeframeSeries allows for the creation of multiple Timeframe options to do data processing, including the ability to determine common date pattern matching.
|
5
|
+
|
6
|
+
Install
|
7
|
+
----
|
8
|
+
|
9
|
+
gem install timeframes
|
10
|
+
|
11
|
+
Usage
|
12
|
+
----
|
13
|
+
Usage of the Timeframe object:
|
14
|
+
|
15
|
+
start = DateTime.new(2011, 2, 14, 4, 0)
|
16
|
+
stop = DateTime.new(2011, 2, 14, 5, 0)
|
17
|
+
timeframe = Timeframes::Frame.new(start, stop)
|
18
|
+
timeframe.duration(:seconds) # => 60
|
19
|
+
timeframe.time # => 4:00am-5:00am
|
20
|
+
|
21
|
+
Usage of the TimeframeSeries object to explain the timeframe in words:
|
22
|
+
|
23
|
+
timeframe1 = Timeframes::Frame.new(DateTime.new(2011, 02, 14, 4, 0), DateTime.new(2011, 02, 14, 5, 0))
|
24
|
+
timeframe2 = Timeframes::Frame.new(DateTime.new(2011, 02, 21, 4, 0), DateTime.new(2011, 02, 21, 5, 0))
|
25
|
+
timeframe3 = Timeframes::Frame.new(DateTime.new(2011, 02, 28, 4, 0), DateTime.new(2011, 02, 28, 5, 0))
|
26
|
+
series = Timeframes::Series.new([timeframe1, timeframe2, timeframe3])
|
27
|
+
series.series_in_words # => Every Monday, 4:00am-5:00am
|
28
|
+
|
29
|
+
TODO
|
30
|
+
----
|
31
|
+
|
32
|
+
* Improve more complex date patterns
|
33
|
+
* Add Timeframe manipulation methods
|
34
|
+
* Documentation
|
35
|
+
|
36
|
+
Contributing
|
37
|
+
----
|
38
|
+
|
39
|
+
Please feel free to fork and submit a pull request for features or improvements you'd like to see in this lib.
|
40
|
+
|
41
|
+
|
42
|
+
Author
|
43
|
+
----
|
44
|
+
|
45
|
+
Created by Andrew Nordman - cadwallion@gmail.com - @cadwallion
|
data/Rakefile
ADDED
data/lib/timeframes.rb
ADDED
@@ -0,0 +1,67 @@
|
|
1
|
+
module Timeframes
|
2
|
+
class Frame
|
3
|
+
attr_reader :start, :stop
|
4
|
+
class InvalidDateError < Exception ; end
|
5
|
+
|
6
|
+
include Enumerable
|
7
|
+
|
8
|
+
def initialize(start, stop)
|
9
|
+
@start = start.is_a?(DateTime) ? start : DateTime.parse(start)
|
10
|
+
@stop = stop.is_a?(DateTime) ? stop : DateTime.parse(stop)
|
11
|
+
if @stop < @start
|
12
|
+
raise InvalidDateError, "Stop cannot be before start"
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
def to_s
|
17
|
+
if @stop - @start < 24.hours
|
18
|
+
@start.strftime("%m/%d/%Y %I:%M:%S %p") + " - " + @stop.strftime("%I:%M:%S %p")
|
19
|
+
else
|
20
|
+
@start.strftime("%m/%d/%Y %I:%M:%S %p") + " - " + @stop.strftime("%m/%d/%Y %I:%M:%S %p")
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
def ==(other)
|
25
|
+
if other.respond_to?(:start) && other.respond_to?(:stop)
|
26
|
+
if other.start == @start && other.stop == @stop
|
27
|
+
true
|
28
|
+
else
|
29
|
+
false
|
30
|
+
end
|
31
|
+
else
|
32
|
+
raise NoMethodError
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
def <=>(other)
|
37
|
+
if other.respond_to?(:start) && other.respond_to?(:stop)
|
38
|
+
if @start.to_i < other.start.to_i
|
39
|
+
-1
|
40
|
+
elsif self == other
|
41
|
+
0
|
42
|
+
else
|
43
|
+
1
|
44
|
+
end
|
45
|
+
else
|
46
|
+
raise NoMethodError
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
def duration(format = :seconds)
|
51
|
+
unformatted_duration = @stop.to_i - @start.to_i
|
52
|
+
case format
|
53
|
+
when :seconds
|
54
|
+
duration_divisor = 1
|
55
|
+
when :minutes
|
56
|
+
duration_divisor = 60.0
|
57
|
+
when :hours
|
58
|
+
duration_divisor = 3600.0
|
59
|
+
when :days
|
60
|
+
duration_divisor = 86400.0
|
61
|
+
else
|
62
|
+
return "unknown format type."
|
63
|
+
end
|
64
|
+
return unformatted_duration / duration_divisor
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
@@ -0,0 +1,171 @@
|
|
1
|
+
module Timeframes
|
2
|
+
class Series
|
3
|
+
attr_reader :timeframes
|
4
|
+
|
5
|
+
def initialize(timeframes = [])
|
6
|
+
@timeframes = timeframes
|
7
|
+
@timeframes.sort!
|
8
|
+
end
|
9
|
+
|
10
|
+
def <<(other)
|
11
|
+
if other.class == Timeframes::Series
|
12
|
+
@timeframes << other.timeframes
|
13
|
+
elsif other.class == Timeframes::Frame
|
14
|
+
@timeframes << other
|
15
|
+
else
|
16
|
+
raise ArgumentError
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
def start
|
21
|
+
@timeframes.first.start
|
22
|
+
end
|
23
|
+
|
24
|
+
def stop
|
25
|
+
@timeframes.last.stop
|
26
|
+
end
|
27
|
+
|
28
|
+
def total_duration
|
29
|
+
@timeframes.map(&:duration).sum
|
30
|
+
end
|
31
|
+
|
32
|
+
def series_in_words
|
33
|
+
if check_sequential
|
34
|
+
sequential_output
|
35
|
+
elsif pattern = check_common_weekday
|
36
|
+
common_weekday_output(pattern)
|
37
|
+
elsif check_common_monthday
|
38
|
+
# stub
|
39
|
+
else
|
40
|
+
default_output
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
private
|
45
|
+
|
46
|
+
# offset per group. pattern_group 0 with dates_per_group 4 means comparing 0-3 to 4-7,
|
47
|
+
# then 4-7 to 8-11, through scan_occurrences times.
|
48
|
+
# pattern_group * dates_per_group is the base index
|
49
|
+
# (pattern_group + 1) * dates_per_group is the comparison index
|
50
|
+
# Do not need to compare the last pattern to anything, so we decrement by 1.
|
51
|
+
def check_common_weekday
|
52
|
+
weekdays = @timeframes.map { |t| t.start.wday }
|
53
|
+
scan = weekdays.join("").scan(/#{weekdays.first}/)
|
54
|
+
scan_occurrences = scan.size
|
55
|
+
if scan_occurrences > 1
|
56
|
+
result_count = weekdays.join("").split(/(0\d{0,})\1{#{scan_occurrences-1},}/)
|
57
|
+
if result_count.size == 1
|
58
|
+
weekday_patterns = result_count[0].split("")
|
59
|
+
total_distances = {}
|
60
|
+
dates_per_group = weekday_patterns.first.size
|
61
|
+
(scan_occurrences - 1).times do |pattern_group|
|
62
|
+
dates_per_group.times do |date_within_group|
|
63
|
+
base_index = (pattern_group * dates_per_group) + date_within_group
|
64
|
+
comparison_index = ((pattern_group + 1) * dates_per_group) + date_within_group
|
65
|
+
distance = @timeframes[comparison_index].start - @timeframes[base_index].start
|
66
|
+
if (@timeframes[base_index].start + distance) == @timeframes[comparison_index].start
|
67
|
+
total_distances[date_within_group] ||= []
|
68
|
+
total_distances[date_within_group] << distance
|
69
|
+
else
|
70
|
+
return false
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
total_distances.each do |day, distances|
|
76
|
+
if distances.uniq.size == 1
|
77
|
+
total_distances[day] = distances.first
|
78
|
+
else
|
79
|
+
return false
|
80
|
+
end
|
81
|
+
end
|
82
|
+
return total_distances
|
83
|
+
else
|
84
|
+
return false
|
85
|
+
end
|
86
|
+
else
|
87
|
+
return false
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
def check_common_monthday
|
92
|
+
false
|
93
|
+
end
|
94
|
+
|
95
|
+
def check_sequential
|
96
|
+
@timeframes.each_index do |k|
|
97
|
+
unless @timeframes[k+1].nil?
|
98
|
+
if same_day?(@timeframes[k+1].start, (@timeframes[k].start + 1.day)) && same_day?(@timeframes[k+1].stop, (@timeframes[k].stop + 1.day))
|
99
|
+
next
|
100
|
+
else
|
101
|
+
return false
|
102
|
+
end
|
103
|
+
end
|
104
|
+
end
|
105
|
+
true
|
106
|
+
end
|
107
|
+
|
108
|
+
def sequential_output
|
109
|
+
self.start.strftime("%m/%d") + "-" + self.stop.strftime("%m/%d") + " " + @timeframes.last.start.strftime("%l:%M%P").lstrip + "-" + @timeframes.last.stop.strftime("%l:%M%P").lstrip
|
110
|
+
end
|
111
|
+
|
112
|
+
def common_weekday_output(pattern)
|
113
|
+
output = ""
|
114
|
+
counter = 0
|
115
|
+
number_of_weekdays = pattern.size
|
116
|
+
pattern.each do |key, weekday|
|
117
|
+
case weekday.to_i
|
118
|
+
when 7
|
119
|
+
qualifier = "%As"
|
120
|
+
when 14
|
121
|
+
qualifier = "Every other %A"
|
122
|
+
else
|
123
|
+
# 1st & 3rd Tuesday
|
124
|
+
|
125
|
+
nth_days = @timeframes.map { |n| nth_dayname_of_month(n.start) }
|
126
|
+
groups = (@timeframes.size / pattern.size)
|
127
|
+
if groups > 2
|
128
|
+
default_output
|
129
|
+
else
|
130
|
+
qualifier = "#{nth_days[0]} and #{nth_days[(groups*1)+1]} %A"
|
131
|
+
end
|
132
|
+
end
|
133
|
+
output << @timeframes[counter].start.strftime("#{qualifier} %I:%M%P") << "-" << @timeframes[counter].stop.strftime("%I:%M%P")
|
134
|
+
counter += 1
|
135
|
+
end
|
136
|
+
output
|
137
|
+
end
|
138
|
+
|
139
|
+
def default_output
|
140
|
+
@timeframes.map(&:to_s).join(", ") # default (No pattern)
|
141
|
+
end
|
142
|
+
|
143
|
+
def same_time?(one, two)
|
144
|
+
one.strftime("%I:%M%p") == two.strftime("%I:%M%p")
|
145
|
+
end
|
146
|
+
|
147
|
+
def same_day?(one, two)
|
148
|
+
one.strftime("%m/%d/%Y") == two.strftime("%m/%d/%Y")
|
149
|
+
end
|
150
|
+
|
151
|
+
def nth_dayname_of_month(date)
|
152
|
+
first_day_of_month = Date.new(date.year, date.month, 1)
|
153
|
+
first_day_of_next_month = Date.new(date.year, date.next_month.month, 1)
|
154
|
+
first_dayname_offset = (7 - (first_day_of_month.wday - date.wday).abs)
|
155
|
+
if first_dayname_offset == 7
|
156
|
+
first_dayname_offset = 0
|
157
|
+
end
|
158
|
+
first_dayname_of_month = first_day_of_month + first_dayname_offset
|
159
|
+
current_date = first_dayname_of_month
|
160
|
+
counter = 1
|
161
|
+
while current_date < first_day_of_next_month
|
162
|
+
if current_date == date
|
163
|
+
break
|
164
|
+
end
|
165
|
+
current_date += 7
|
166
|
+
counter += 1
|
167
|
+
end
|
168
|
+
return counter
|
169
|
+
end
|
170
|
+
end
|
171
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,74 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Timeframes::Series do
|
4
|
+
it "should take an array of timeframes" do
|
5
|
+
timeframes = [
|
6
|
+
Timeframes::Frame.new("2011-01-01 01:00", "2011-01-02 01:00"),
|
7
|
+
Timeframes::Frame.new("2011-02-02 02:00", "2011-02-02 02:22")
|
8
|
+
]
|
9
|
+
|
10
|
+
t = Timeframes::Series.new(timeframes)
|
11
|
+
t.timeframes.should == timeframes
|
12
|
+
end
|
13
|
+
|
14
|
+
it "concatenates two TimeframeSeries together" do
|
15
|
+
timeframe1 = [
|
16
|
+
Timeframes::Frame.new("2011-01-01 01:00", "2011-01-02 01:00"),
|
17
|
+
Timeframes::Frame.new("2011-02-02 02:00", "2011-02-02 02:22")
|
18
|
+
]
|
19
|
+
|
20
|
+
timeframe2 = [
|
21
|
+
Timeframes::Frame.new("2011-03-01 01:00", "2011-03-02 01:00"),
|
22
|
+
Timeframes::Frame.new("2011-03-02 02:00", "2011-03-02 02:22")
|
23
|
+
]
|
24
|
+
t1 = Timeframes::Series.new(timeframe1)
|
25
|
+
t2 = Timeframes::Series.new(timeframe2)
|
26
|
+
t1 << t2
|
27
|
+
t1.timeframes == (timeframe1 + timeframe2)
|
28
|
+
end
|
29
|
+
|
30
|
+
it "concatenates a Timeframe into the TimeframeSeries" do
|
31
|
+
timeframes = [
|
32
|
+
Timeframes::Frame.new("2011-01-01 01:00", "2011-01-02 01:00"),
|
33
|
+
Timeframes::Frame.new("2011-02-02 02:00", "2011-02-02 02:22")
|
34
|
+
]
|
35
|
+
|
36
|
+
t = Timeframes::Series.new(timeframes)
|
37
|
+
|
38
|
+
new_timeframe = Timeframes::Frame.new("2011-03-01 01:55", "2011-03-01 02:00")
|
39
|
+
t << new_timeframe
|
40
|
+
t.timeframes.should == (timeframes << new_timeframe)
|
41
|
+
end
|
42
|
+
|
43
|
+
it "outputs sequential days as a range" do
|
44
|
+
timeframes = [
|
45
|
+
Timeframes::Frame.new("2011-02-14 04:00", "2011-02-14 05:00"),
|
46
|
+
Timeframes::Frame.new("2011-02-15 04:00", "2011-02-15 05:00"),
|
47
|
+
Timeframes::Frame.new("2011-02-16 04:00", "2011-02-16 05:00"),
|
48
|
+
]
|
49
|
+
series = Timeframes::Series.new(timeframes)
|
50
|
+
|
51
|
+
series.series_in_words.should == "02/14-02/16 4:00am-5:00am"
|
52
|
+
end
|
53
|
+
|
54
|
+
it "outputs days with a common day of the week" do
|
55
|
+
timeframes = [
|
56
|
+
Timeframes::Frame.new("2011-02-14 04:00", "2011-02-14 05:00"),
|
57
|
+
Timeframes::Frame.new("2011-02-21 04:00", "2011-02-21 05:00"),
|
58
|
+
Timeframes::Frame.new("2011-02-28 04:00", "2011-02-28 05:00")
|
59
|
+
]
|
60
|
+
series = Timeframes::Series.new(timeframes)
|
61
|
+
|
62
|
+
series.series_in_words.should == "Mondays 04:00am-05:00am"
|
63
|
+
end
|
64
|
+
|
65
|
+
it "outputs days for every other weekday" do
|
66
|
+
timeframes = [
|
67
|
+
Timeframes::Frame.new("2011-02-14 04:00", "2011-02-14 05:00"),
|
68
|
+
Timeframes::Frame.new("2011-02-28 04:00", "2011-02-28 05:00")
|
69
|
+
]
|
70
|
+
|
71
|
+
series = Timeframes::Series.new(timeframes)
|
72
|
+
series.series_in_words.should == "Every other Monday 04:00am-05:00am"
|
73
|
+
end
|
74
|
+
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Timeframes::Frame do
|
4
|
+
it "should not allow a stop date before its start date" do
|
5
|
+
expect { Timeframes::Frame.new("2011-01-02 01:00", "2011-01-01 01:00") }.to raise_exception(Timeframes::Frame::InvalidDateError, "Stop cannot be before start")
|
6
|
+
end
|
7
|
+
describe "#duration" do
|
8
|
+
before { @t = Timeframes::Frame.new("2011-01-01 01:00", "2011-01-01 02:00") }
|
9
|
+
|
10
|
+
it "outputs duration by default in seconds" do
|
11
|
+
@t.duration.should == 3600
|
12
|
+
end
|
13
|
+
|
14
|
+
it "can output durations in minutes" do
|
15
|
+
@t.duration(:minutes).should == 60.0
|
16
|
+
end
|
17
|
+
|
18
|
+
it "can output durations in hours" do
|
19
|
+
@t.duration(:hours).should == 1.0
|
20
|
+
end
|
21
|
+
|
22
|
+
it "can output durations in days" do
|
23
|
+
@t.duration(:days).should == (1/24.0)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
it "determines equality based on start and stop values" do
|
28
|
+
t1 = Timeframes::Frame.new("2011-01-01 01:00", "2011-01-01 02:00")
|
29
|
+
t2 = Timeframes::Frame.new("2011-01-01 01:00", "2011-01-01 02:00")
|
30
|
+
t3 = Timeframes::Frame.new("2011-01-01 01:00", "2011-01-01 03:00")
|
31
|
+
t4 = Timeframes::Frame.new("2011-01-01 03:00", "2011-01-01 04:00")
|
32
|
+
|
33
|
+
t1.should == t2
|
34
|
+
t1.should_not == t3
|
35
|
+
t3.should_not == t4
|
36
|
+
end
|
37
|
+
|
38
|
+
it "sorts based on start value, then stop value" do
|
39
|
+
t1 = Timeframes::Frame.new("2011-01-01 01:00", "2011-01-01 02:05")
|
40
|
+
t2 = Timeframes::Frame.new("2011-01-01 01:00", "2011-01-01 02:00")
|
41
|
+
t3 = Timeframes::Frame.new("2011-01-01 01:05", "2011-01-01 02:55")
|
42
|
+
t4 = Timeframes::Frame.new("2011-01-01 02:00", "2011-01-01 02:30")
|
43
|
+
[t4, t2, t3, t1].sort.should == [t2, t1, t3, t4]
|
44
|
+
end
|
45
|
+
end
|
data/timeframes.gemspec
ADDED
@@ -0,0 +1,25 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
$:.push File.expand_path("../lib", __FILE__)
|
3
|
+
require "timeframes/version"
|
4
|
+
|
5
|
+
Gem::Specification.new do |s|
|
6
|
+
s.name = "timeframes"
|
7
|
+
s.version = Timeframes::VERSION
|
8
|
+
s.platform = Gem::Platform::RUBY
|
9
|
+
s.authors = ["Andrew Nordman"]
|
10
|
+
s.email = ["cadwallion@gmail.com"]
|
11
|
+
s.homepage = "http://github.com/cadwallion/timeframes"
|
12
|
+
s.summary = %q{Manage timeframes easily}
|
13
|
+
s.description = %q{Manage start-stop timeframes and a series of timeframes for pattern matching and iterating.}
|
14
|
+
|
15
|
+
|
16
|
+
s.add_dependency("activesupport", "~> 3.0.0")
|
17
|
+
s.add_development_dependency("rspec")
|
18
|
+
|
19
|
+
s.rubyforge_project = "timeframes"
|
20
|
+
|
21
|
+
s.files = `git ls-files`.split("\n")
|
22
|
+
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
23
|
+
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
24
|
+
s.require_paths = ["lib"]
|
25
|
+
end
|
metadata
ADDED
@@ -0,0 +1,92 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: timeframes
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
prerelease:
|
5
|
+
version: 0.0.1
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Andrew Nordman
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
|
13
|
+
date: 2011-03-09 00:00:00 -06:00
|
14
|
+
default_executable:
|
15
|
+
dependencies:
|
16
|
+
- !ruby/object:Gem::Dependency
|
17
|
+
name: activesupport
|
18
|
+
prerelease: false
|
19
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
20
|
+
none: false
|
21
|
+
requirements:
|
22
|
+
- - ~>
|
23
|
+
- !ruby/object:Gem::Version
|
24
|
+
version: 3.0.0
|
25
|
+
type: :runtime
|
26
|
+
version_requirements: *id001
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: rspec
|
29
|
+
prerelease: false
|
30
|
+
requirement: &id002 !ruby/object:Gem::Requirement
|
31
|
+
none: false
|
32
|
+
requirements:
|
33
|
+
- - ">="
|
34
|
+
- !ruby/object:Gem::Version
|
35
|
+
version: "0"
|
36
|
+
type: :development
|
37
|
+
version_requirements: *id002
|
38
|
+
description: Manage start-stop timeframes and a series of timeframes for pattern matching and iterating.
|
39
|
+
email:
|
40
|
+
- cadwallion@gmail.com
|
41
|
+
executables: []
|
42
|
+
|
43
|
+
extensions: []
|
44
|
+
|
45
|
+
extra_rdoc_files: []
|
46
|
+
|
47
|
+
files:
|
48
|
+
- .gitignore
|
49
|
+
- .rvmrc
|
50
|
+
- Gemfile
|
51
|
+
- README.markdown
|
52
|
+
- Rakefile
|
53
|
+
- lib/timeframes.rb
|
54
|
+
- lib/timeframes/frame.rb
|
55
|
+
- lib/timeframes/series.rb
|
56
|
+
- lib/timeframes/version.rb
|
57
|
+
- spec/spec_helper.rb
|
58
|
+
- spec/timeframe_series_spec.rb
|
59
|
+
- spec/timeframe_spec.rb
|
60
|
+
- timeframes.gemspec
|
61
|
+
has_rdoc: true
|
62
|
+
homepage: http://github.com/cadwallion/timeframes
|
63
|
+
licenses: []
|
64
|
+
|
65
|
+
post_install_message:
|
66
|
+
rdoc_options: []
|
67
|
+
|
68
|
+
require_paths:
|
69
|
+
- lib
|
70
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
71
|
+
none: false
|
72
|
+
requirements:
|
73
|
+
- - ">="
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: "0"
|
76
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
77
|
+
none: false
|
78
|
+
requirements:
|
79
|
+
- - ">="
|
80
|
+
- !ruby/object:Gem::Version
|
81
|
+
version: "0"
|
82
|
+
requirements: []
|
83
|
+
|
84
|
+
rubyforge_project: timeframes
|
85
|
+
rubygems_version: 1.5.0
|
86
|
+
signing_key:
|
87
|
+
specification_version: 3
|
88
|
+
summary: Manage timeframes easily
|
89
|
+
test_files:
|
90
|
+
- spec/spec_helper.rb
|
91
|
+
- spec/timeframe_series_spec.rb
|
92
|
+
- spec/timeframe_spec.rb
|