freq 0.1.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/.autotest +10 -0
- data/.gitignore +1 -0
- data/README.rdoc +3 -0
- data/README.textile +3 -0
- data/Rakefile +39 -0
- data/VERSION +1 -0
- data/lib/freq.rb +97 -0
- data/test/test_helper.rb +5 -0
- data/test/unit/freq_test.rb +82 -0
- metadata +65 -0
data/.autotest
ADDED
data/.gitignore
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
pkg
|
data/README.rdoc
ADDED
data/README.textile
ADDED
data/Rakefile
ADDED
@@ -0,0 +1,39 @@
|
|
1
|
+
require 'rake'
|
2
|
+
require 'rake/testtask'
|
3
|
+
require 'rake/rdoctask'
|
4
|
+
|
5
|
+
desc 'Default: run tests.'
|
6
|
+
task :default => [:test]
|
7
|
+
|
8
|
+
desc 'Run tests.'
|
9
|
+
Rake::TestTask.new(:test) do |t|
|
10
|
+
t.libs << 'lib'
|
11
|
+
t.pattern = 'test/**/*_test.rb'
|
12
|
+
t.verbose = true
|
13
|
+
end
|
14
|
+
|
15
|
+
desc 'Generate documentation.'
|
16
|
+
Rake::RDocTask.new(:rdoc) do |rdoc|
|
17
|
+
rdoc.rdoc_dir = 'rdoc'
|
18
|
+
rdoc.title = 'Freq'
|
19
|
+
rdoc.options << '--line-numbers' << '--inline-source'
|
20
|
+
rdoc.rdoc_files.include('README.rdoc')
|
21
|
+
rdoc.rdoc_files.include('lib/*.rb')
|
22
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
23
|
+
end
|
24
|
+
|
25
|
+
|
26
|
+
begin
|
27
|
+
require 'jeweler'
|
28
|
+
Jeweler::Tasks.new do |gemspec|
|
29
|
+
gemspec.name = "freq"
|
30
|
+
gemspec.summary = "Freq provides parsing of strings describing periodically occurring events."
|
31
|
+
gemspec.email = "anthonyeden@gmail.com"
|
32
|
+
gemspec.homepage = "http://github.com/aeden/freq"
|
33
|
+
gemspec.description = "Freq provides parsing of strings describing periodically occurring events."
|
34
|
+
gemspec.authors = ["Anthony Eden"]
|
35
|
+
gemspec.files.exclude 'docs/**/*'
|
36
|
+
end
|
37
|
+
rescue LoadError
|
38
|
+
puts "Jeweler not available. Install it with: sudo gem install technicalpickles-jeweler -s http://gems.github.com"
|
39
|
+
end
|
data/VERSION
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
0.1.0
|
data/lib/freq.rb
ADDED
@@ -0,0 +1,97 @@
|
|
1
|
+
# Class that defines a frequency for a recurring thing.
|
2
|
+
#
|
3
|
+
# Note: this class does not properly handle months and years.
|
4
|
+
class Freq
|
5
|
+
|
6
|
+
SECOND = 1 unless defined? SECOND
|
7
|
+
MINUTE = SECOND * 60 unless defined? MINUTE
|
8
|
+
HOUR = MINUTE * 60 unless defined? HOUR
|
9
|
+
DAY = HOUR * 24 unless defined? DAY
|
10
|
+
WEEK = DAY * 7 unless defined? WEEK
|
11
|
+
|
12
|
+
MONTH = DAY * 30 unless defined? MONTH
|
13
|
+
YEAR = DAY * 365 unless defined? YEAR
|
14
|
+
|
15
|
+
attr_accessor :period
|
16
|
+
attr_accessor :times
|
17
|
+
|
18
|
+
def initialize(period, times)
|
19
|
+
@period = period
|
20
|
+
@times = times
|
21
|
+
end
|
22
|
+
|
23
|
+
def to_seconds
|
24
|
+
return 0 if times == 0 || period == 0
|
25
|
+
period / times
|
26
|
+
end
|
27
|
+
|
28
|
+
# Apply the frequency to the given timestamp to get the next occurrence.
|
29
|
+
def next(t)
|
30
|
+
Time.at(t + to_seconds)
|
31
|
+
end
|
32
|
+
|
33
|
+
def self.parse(str)
|
34
|
+
times = 1
|
35
|
+
period = 0
|
36
|
+
multiplier = 1
|
37
|
+
|
38
|
+
words = str.downcase.split
|
39
|
+
words.each_with_index do |word, i|
|
40
|
+
case word
|
41
|
+
when 'every'
|
42
|
+
if words[i+1] == 'other'
|
43
|
+
multiplier = 2
|
44
|
+
end
|
45
|
+
if words[i+1] =~ /\d+/
|
46
|
+
multiplier = words[i+1].to_i
|
47
|
+
end
|
48
|
+
when 'twice' then times = 2
|
49
|
+
when /times?/
|
50
|
+
times = word_to_number(words[i-1])
|
51
|
+
when /seconds?/ then period = SECOND
|
52
|
+
when /minutes?/ then period = MINUTE
|
53
|
+
when /hours?/ then period = HOUR
|
54
|
+
when /days?/ then period = DAY
|
55
|
+
when /weeks?/ then period = WEEK
|
56
|
+
when /months?/ then period = MONTH
|
57
|
+
when /years?/ then period = YEAR
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
new(period * multiplier, times)
|
62
|
+
end
|
63
|
+
|
64
|
+
def self.word_to_number(word)
|
65
|
+
if n = word.to_i
|
66
|
+
if n == 0
|
67
|
+
return 0 if word == '0' || word == 'zero'
|
68
|
+
else
|
69
|
+
return n
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
irregular = {
|
74
|
+
'zero' => 0,
|
75
|
+
'one' => 1,
|
76
|
+
'two' => 2,
|
77
|
+
'three' => 3,
|
78
|
+
'four' => 4,
|
79
|
+
'five' => 5,
|
80
|
+
'six' => 6,
|
81
|
+
'seven' => 7,
|
82
|
+
'eight' => 8,
|
83
|
+
'nine' => 9,
|
84
|
+
'ten' => 10,
|
85
|
+
'eleven' => 11,
|
86
|
+
'twelve' => 12,
|
87
|
+
'thirteen' => 13,
|
88
|
+
'fourteen' => 14,
|
89
|
+
'fifteen' => 15,
|
90
|
+
'sixteen' => 16,
|
91
|
+
'seventeen' => 17,
|
92
|
+
'eighteen' => 18,
|
93
|
+
'nineteen' => 19
|
94
|
+
}
|
95
|
+
return irregular[word] if irregular[word]
|
96
|
+
end
|
97
|
+
end
|
data/test/test_helper.rb
ADDED
@@ -0,0 +1,82 @@
|
|
1
|
+
require File.dirname(__FILE__) + "/../test_helper"
|
2
|
+
|
3
|
+
class FreqTest < Test::Unit::TestCase
|
4
|
+
context "a frequency" do
|
5
|
+
context "when parsed as a string" do
|
6
|
+
should "construct the correct frequency" do
|
7
|
+
expectations.each do |s, expect|
|
8
|
+
assert_equal expect, Freq.parse(s).to_seconds
|
9
|
+
end
|
10
|
+
end
|
11
|
+
end
|
12
|
+
context "next" do
|
13
|
+
should "return the correct Time value" do
|
14
|
+
expectations.each do |s, expect|
|
15
|
+
t = Time.now
|
16
|
+
assert_equal t + expect, Freq.parse(s).next(t)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
def expectations
|
23
|
+
{
|
24
|
+
'every second' => Freq::SECOND,
|
25
|
+
'once a second' => Freq::SECOND,
|
26
|
+
'every minute' => Freq::MINUTE,
|
27
|
+
'once a minute' => Freq::MINUTE,
|
28
|
+
'every hour' => Freq::HOUR,
|
29
|
+
'once an hour' => Freq::HOUR,
|
30
|
+
'every day' => Freq::DAY,
|
31
|
+
'once a day' => Freq::DAY,
|
32
|
+
'every week' => Freq::WEEK,
|
33
|
+
'once a week' => Freq::WEEK,
|
34
|
+
'every month' => Freq::MONTH,
|
35
|
+
'once a month' => Freq::MONTH,
|
36
|
+
'every year' => Freq::YEAR,
|
37
|
+
'once a year' => Freq::YEAR,
|
38
|
+
|
39
|
+
'every other second' => Freq::SECOND * 2,
|
40
|
+
'every other minute' => Freq::MINUTE * 2,
|
41
|
+
'every other hour' => Freq::HOUR * 2,
|
42
|
+
'every other day' => Freq::DAY * 2,
|
43
|
+
'every other week' => Freq::WEEK * 2,
|
44
|
+
|
45
|
+
'every 2 seconds' => Freq::SECOND * 2,
|
46
|
+
'every 10 seconds' => Freq::SECOND * 10,
|
47
|
+
'every 2 minutes' => Freq::MINUTE * 2,
|
48
|
+
'every 10 minutes' => Freq::MINUTE * 10,
|
49
|
+
'every 2 hours' => Freq::HOUR * 2,
|
50
|
+
'every 10 hours' => Freq::HOUR * 10,
|
51
|
+
'every 2 days' => Freq::DAY * 2,
|
52
|
+
'every 10 days' => Freq::DAY * 10,
|
53
|
+
'every 2 weeks' => Freq::WEEK * 2,
|
54
|
+
'every 10 weeks' => Freq::WEEK * 10,
|
55
|
+
|
56
|
+
'once every 2 seconds' => Freq::SECOND * 2,
|
57
|
+
'twice every 2 seconds' => Freq::SECOND * 1,
|
58
|
+
|
59
|
+
'1 time every 2 seconds' => Freq::SECOND * 2,
|
60
|
+
'1 time every second' => Freq::SECOND * 1,
|
61
|
+
'10 times every minute' => Freq::SECOND * 6,
|
62
|
+
'5 times every other day' => Freq::DAY / 5 * 2,
|
63
|
+
|
64
|
+
'twice a minute' => Freq::MINUTE / 2,
|
65
|
+
'4 times a minute' => Freq::MINUTE / 4,
|
66
|
+
'four times a minute' => Freq::MINUTE / 4,
|
67
|
+
'ten times per minute' => Freq::MINUTE / 10,
|
68
|
+
'twice an hour' => Freq::HOUR / 2,
|
69
|
+
'4 times an hour' => Freq::HOUR / 4,
|
70
|
+
'four times an hour' => Freq::HOUR / 4,
|
71
|
+
'ten times per hour' => Freq::HOUR / 10,
|
72
|
+
'twice a day' => Freq::DAY / 2,
|
73
|
+
'4 times a day' => Freq::DAY / 4,
|
74
|
+
'four times a day' => Freq::DAY / 4,
|
75
|
+
'ten times per day' => Freq::DAY / 10,
|
76
|
+
'twice a week' => Freq::WEEK / 2,
|
77
|
+
'4 times a week' => Freq::WEEK / 4,
|
78
|
+
'four times a week' => Freq::WEEK / 4,
|
79
|
+
'ten times per week' => Freq::WEEK / 10,
|
80
|
+
}
|
81
|
+
end
|
82
|
+
end
|
metadata
ADDED
@@ -0,0 +1,65 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: freq
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Anthony Eden
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
|
12
|
+
date: 2009-12-20 00:00:00 -10:00
|
13
|
+
default_executable:
|
14
|
+
dependencies: []
|
15
|
+
|
16
|
+
description: Freq provides parsing of strings describing periodically occurring events.
|
17
|
+
email: anthonyeden@gmail.com
|
18
|
+
executables: []
|
19
|
+
|
20
|
+
extensions: []
|
21
|
+
|
22
|
+
extra_rdoc_files:
|
23
|
+
- README.rdoc
|
24
|
+
- README.textile
|
25
|
+
files:
|
26
|
+
- .autotest
|
27
|
+
- .gitignore
|
28
|
+
- README.rdoc
|
29
|
+
- README.textile
|
30
|
+
- Rakefile
|
31
|
+
- VERSION
|
32
|
+
- lib/freq.rb
|
33
|
+
- test/test_helper.rb
|
34
|
+
- test/unit/freq_test.rb
|
35
|
+
has_rdoc: true
|
36
|
+
homepage: http://github.com/aeden/freq
|
37
|
+
licenses: []
|
38
|
+
|
39
|
+
post_install_message:
|
40
|
+
rdoc_options:
|
41
|
+
- --charset=UTF-8
|
42
|
+
require_paths:
|
43
|
+
- lib
|
44
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
45
|
+
requirements:
|
46
|
+
- - ">="
|
47
|
+
- !ruby/object:Gem::Version
|
48
|
+
version: "0"
|
49
|
+
version:
|
50
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - ">="
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: "0"
|
55
|
+
version:
|
56
|
+
requirements: []
|
57
|
+
|
58
|
+
rubyforge_project:
|
59
|
+
rubygems_version: 1.3.5
|
60
|
+
signing_key:
|
61
|
+
specification_version: 3
|
62
|
+
summary: Freq provides parsing of strings describing periodically occurring events.
|
63
|
+
test_files:
|
64
|
+
- test/test_helper.rb
|
65
|
+
- test/unit/freq_test.rb
|