runt 0.7.0 → 0.9.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.
Files changed (49) hide show
  1. data/.gitignore +19 -0
  2. data/.travis.yml +5 -0
  3. data/{CHANGES → CHANGES.txt} +24 -8
  4. data/Gemfile +4 -0
  5. data/LICENSE.txt +22 -44
  6. data/README.md +79 -0
  7. data/Rakefile +6 -119
  8. data/doc/tutorial_schedule.md +365 -0
  9. data/doc/tutorial_sugar.md +170 -0
  10. data/doc/tutorial_te.md +155 -0
  11. data/lib/runt.rb +36 -21
  12. data/lib/runt/dprecision.rb +4 -2
  13. data/lib/runt/pdate.rb +101 -95
  14. data/lib/runt/schedule.rb +18 -0
  15. data/lib/runt/sugar.rb +41 -9
  16. data/lib/runt/temporalexpression.rb +246 -30
  17. data/lib/runt/version.rb +3 -0
  18. data/runt.gemspec +24 -0
  19. data/site/.cvsignore +1 -0
  20. data/site/dcl-small.gif +0 -0
  21. data/site/index-rubforge-www.html +72 -0
  22. data/site/index.html +75 -60
  23. data/site/runt-logo.gif +0 -0
  24. data/site/runt-logo.psd +0 -0
  25. data/test/baseexpressiontest.rb +10 -8
  26. data/test/combinedexpressionstest.rb +166 -158
  27. data/test/daterangetest.rb +4 -6
  28. data/test/diweektest.rb +32 -32
  29. data/test/dprecisiontest.rb +2 -4
  30. data/test/everytetest.rb +6 -0
  31. data/test/expressionbuildertest.rb +2 -3
  32. data/test/icalendartest.rb +3 -6
  33. data/test/minitest_helper.rb +7 -0
  34. data/test/pdatetest.rb +21 -6
  35. data/test/redaytest.rb +3 -0
  36. data/test/reyeartest.rb +1 -1
  37. data/test/runttest.rb +5 -8
  38. data/test/scheduletest.rb +13 -14
  39. data/test/sugartest.rb +28 -6
  40. data/test/{spectest.rb → temporaldatetest.rb} +14 -4
  41. data/test/{rspectest.rb → temporalrangetest.rb} +4 -4
  42. data/test/test_runt.rb +11 -0
  43. data/test/weekintervaltest.rb +106 -0
  44. metadata +161 -116
  45. data/README +0 -106
  46. data/doc/tutorial_schedule.rdoc +0 -393
  47. data/doc/tutorial_sugar.rdoc +0 -143
  48. data/doc/tutorial_te.rdoc +0 -190
  49. data/setup.rb +0 -1331
@@ -0,0 +1,3 @@
1
+ module Runt
2
+ VERSION = "0.9.0"
3
+ end
@@ -0,0 +1,24 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'runt/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "runt"
8
+ spec.version = Runt::VERSION
9
+ spec.authors = ["Matthew Lipper"]
10
+ spec.email = ["mlipper@gmail.com"]
11
+ spec.description = %q{Runt is a Ruby implementation of temporal patterns by Martin Fowler. Runt provides an API for working with recurring events using set expressions.}
12
+ spec.summary = %q{Ruby Temporal Expressions}
13
+ spec.homepage = "http://github.com/mlipper/runt"
14
+ spec.license = "MIT"
15
+
16
+ spec.files = `git ls-files`.split($/)
17
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
18
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
+ spec.require_paths = ["lib"]
20
+
21
+ spec.add_development_dependency "bundler", "~> 1.3"
22
+ spec.add_development_dependency "rake"
23
+ spec.add_development_dependency "minitest"
24
+ end
@@ -0,0 +1 @@
1
+ doc
File without changes
@@ -0,0 +1,72 @@
1
+ <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
2
+ "http://www.w3.org/TR/html4/strict.dtd">
3
+
4
+ <html>
5
+ <head>
6
+ <title>Runt - Ruby Temporal Expressions</title>
7
+ <style type="text/css" media="screen">@import "blue-robot3.css";</style>
8
+
9
+ </head>
10
+
11
+ <body>
12
+
13
+ <div class="content">
14
+ <h1><a href="http://runt.rubyforge.org"><img id="logo" src="runt-logo.gif" title="Choose your own damn acronym" alt="runt logo"></a>Ruby Temporal Expressions</h1>
15
+ <p><span class="keyword">Runt</span> is an implementation of select temporal patterns by <a href="http://www.martinfowler.com">Martin Fowler</a> in the super-fantastic <a href="http://ruby-lang.org"><span class="ruby-link">Ruby</span></a> language.
16
+ <span class="keyword">Runt</span> provides:
17
+ <ul>
18
+ <li>ability to define recurring events using simple, set-like expressions</li>
19
+ <li>an interfaced-based API for creating schedules for arbitrary events/objects</li>
20
+ <li>precisioned date types using <a href="http://martinfowler.com/ap2/timePoint.html">Time Point</a>s</li>
21
+ <li>date <a href="http://martinfowler.com/ap2/range.html">Range</a>s</li>
22
+ <li>everlasting peace and/or eternal life</li>
23
+ </ul>
24
+ </p>
25
+ <p>Visit our <a href="http://rubyforge.org/projects/runt/">project page</a> provided by the generous folks at <a href="http://rubyforge.org">Rubyforge</a>.</p>
26
+ </div>
27
+
28
+ <div class="content">
29
+
30
+ <h2>Getting Started</h2>
31
+ <p>
32
+ Check out the <a href="./doc/files/doc/tutorial_te_rdoc.html" title="TE Tutorial">temporal expressions tutorial</a>. Then try
33
+ <a href="./doc/files/doc/tutorial_schedule_rdoc.html" title="Schedule Tutorial">schedule tutorial</a> and finally,
34
+ <a href="./doc/files/doc/tutorial_sugar_rdoc.html" title="Sugar Tutorial">sugar tutorial</a> for some useful shortcuts.
35
+ </p>
36
+ </div>
37
+
38
+ <div id="contentFooter" class="content">
39
+ <a href="http://www.digitalclash.com">&lt;&lt;<img id="dcl-logo" src="dcl-small.gif" title="Digital Clash LLC" alt="Digital Clash logo">&copy;2008, Digital Clash LLC&gt;&gt;</a>
40
+ <br/><i>&quot;The weather is here, wish you were beautiful...&quot;</i>
41
+ </div>
42
+
43
+ <div id="navAlpha">
44
+ <h2>Links</h2>
45
+ <p>
46
+ <a href="http://rubyforge.org/projects/runt/" title="Download Runt">Download</a><br>
47
+ ----<br/>
48
+ <a href="./doc/index.html" title="RDoc for Runt">RDocs</a><br>
49
+ <a href="./doc/files/doc/tutorial_te_rdoc.html" title="TE Tutorial">Expression Tutorial</a><br>
50
+ <a href="./doc/files/doc/tutorial_schedule_rdoc.html" title="Schedule Tutorial">Schedule Tutorial</a><br>
51
+ <a href="./doc/files/doc/tutorial_sugar_rdoc.html" title="Sugar Tutorial">Sugar Tutorial</a><br>
52
+ ----<br/>
53
+ <a href="./doc/files/README.html">README</a><br/>
54
+ <a href="./doc/files/CHANGES.html">CHANGES</a><br/>
55
+ </p>
56
+ </div>
57
+
58
+ <div id="navBeta">
59
+ <h2>Suggested Reading</h2>
60
+ <p>Most of the usage and design patterns contained in this library are based on a series of articles by Martin Fowler. Some suggested reading:</p>
61
+ <p>
62
+ <a href="http://martinfowler.com/ap2/timeNarrative.html">Time Narrative</a><br/>
63
+ <a href="http://martinfowler.com/apsupp/recurring.pdf">Recurring Events</a><br/>
64
+ <a href="http://martinfowler.com/ap2/timePoint.html">Time Point</a><br/>
65
+ <a href="http://martinfowler.com/ap2/range.html">Range</a><br/>
66
+ </p>
67
+ </div>
68
+
69
+ <!-- BlueRobot was here. -->
70
+
71
+ </body>
72
+ </html>
@@ -1,72 +1,87 @@
1
- <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
2
- "http://www.w3.org/TR/html4/strict.dtd">
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="utf-8">
5
+ <title>We've moved!</title>
6
+ <style>
7
+ ::-moz-selection {
8
+ background: #b3d4fc;
9
+ text-shadow: none;
10
+ }
3
11
 
4
- <html>
5
- <head>
6
- <title>Runt - Ruby Temporal Expressions</title>
7
- <style type="text/css" media="screen">@import "blue-robot3.css";</style>
12
+ ::selection {
13
+ background: #b3d4fc;
14
+ text-shadow: none;
15
+ }
8
16
 
9
- </head>
17
+ html {
18
+ padding: 30px 10px;
19
+ font-size: 20px;
20
+ line-height: 1.4;
21
+ color: #737373;
22
+ background: #f0f0f0;
23
+ -webkit-text-size-adjust: 100%;
24
+ -ms-text-size-adjust: 100%;
25
+ }
10
26
 
11
- <body>
27
+ html,
28
+ input {
29
+ font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
30
+ }
12
31
 
13
- <div class="content">
14
- <h1><a href="http://runt.rubyforge.org"><img id="logo" src="runt-logo.gif" title="Choose your own damn acronym" alt="runt logo"></a>Ruby Temporal Expressions</h1>
15
- <p><span class="keyword">Runt</span> is an implementation of select temporal patterns by <a href="http://www.martinfowler.com">Martin Fowler</a> in the super-fantastic <a href="http://ruby-lang.org"><span class="ruby-link">Ruby</span></a> language.
16
- <span class="keyword">Runt</span> provides:
17
- <ul>
18
- <li>ability to define recurring events using simple, set-like expressions</li>
19
- <li>an interfaced-based API for creating schedules for arbitrary events/objects</li>
20
- <li>precisioned date types using <a href="http://martinfowler.com/ap2/timePoint.html">Time Point</a>s</li>
21
- <li>date <a href="http://martinfowler.com/ap2/range.html">Range</a>s</li>
22
- <li>everlasting peace and/or eternal life</li>
23
- </ul>
24
- </p>
25
- <p>Visit our <a href="http://rubyforge.org/projects/runt/">project page</a> provided by the generous folks at <a href="http://rubyforge.org">Rubyforge</a>.</p>
26
- </div>
32
+ body {
33
+ max-width: 500px;
34
+ _width: 500px;
35
+ padding: 30px 20px 50px;
36
+ border: 1px solid #b3b3b3;
37
+ border-radius: 4px;
38
+ margin: 0 auto;
39
+ box-shadow: 0 1px 10px #a7a7a7, inset 0 1px 0 #fff;
40
+ background: #fcfcfc;
41
+ }
27
42
 
28
- <div class="content">
43
+ h1 {
44
+ margin: 0 10px;
45
+ font-size: 50px;
46
+ text-align: center;
47
+ }
29
48
 
30
- <h2>Getting Started</h2>
31
- <p>
32
- Check out the <a href="./doc/files/doc/tutorial_te_rdoc.html" title="TE Tutorial">temporal expressions tutorial</a>. Then try
33
- <a href="./doc/files/doc/tutorial_schedule_rdoc.html" title="Schedule Tutorial">schedule tutorial</a> and finally,
34
- <a href="./doc/files/doc/tutorial_sugar_rdoc.html" title="Sugar Tutorial">sugar tutorial</a> for some useful shortcuts.
35
- </p>
36
- </div>
49
+ h1 span {
50
+ color: #bbb;
51
+ }
37
52
 
38
- <div id="contentFooter" class="content">
39
- <a href="http://www.digitalclash.com">&lt;&lt;<img id="dcl-logo" src="dcl-small.gif" title="Digital Clash LLC" alt="Digital Clash logo">&copy;2008, Digital Clash LLC&gt;&gt;</a>
40
- <br/><i>&quot;The weather is here, wish you were beautiful...&quot;</i>
41
- </div>
53
+ h3 {
54
+ margin: 1.5em 0 0.5em;
55
+ }
42
56
 
43
- <div id="navAlpha">
44
- <h2>Links</h2>
45
- <p>
46
- <a href="http://rubyforge.org/projects/runt/" title="Download Runt">Download</a><br>
47
- ----<br/>
48
- <a href="./doc/index.html" title="RDoc for Runt">RDocs</a><br>
49
- <a href="./doc/files/doc/tutorial_te_rdoc.html" title="TE Tutorial">Expression Tutorial</a><br>
50
- <a href="./doc/files/doc/tutorial_schedule_rdoc.html" title="Schedule Tutorial">Schedule Tutorial</a><br>
51
- <a href="./doc/files/doc/tutorial_sugar_rdoc.html" title="Sugar Tutorial">Sugar Tutorial</a><br>
52
- ----<br/>
53
- <a href="./doc/files/README.html">README</a><br/>
54
- <a href="./doc/files/CHANGES.html">CHANGES</a><br/>
55
- </p>
56
- </div>
57
+ p {
58
+ margin: 1em 0;
59
+ }
57
60
 
58
- <div id="navBeta">
59
- <h2>Suggested Reading</h2>
60
- <p>Most of the usage and design patterns contained in this library are based on a series of articles by Martin Fowler. Some suggested reading:</p>
61
- <p>
62
- <a href="http://martinfowler.com/ap2/timeNarrative.html">Time Narrative</a><br/>
63
- <a href="http://martinfowler.com/apsupp/recurring.pdf">Recurring Events</a><br/>
64
- <a href="http://martinfowler.com/ap2/timePoint.html">Time Point</a><br/>
65
- <a href="http://martinfowler.com/ap2/range.html">Range</a><br/>
66
- </p>
67
- </div>
61
+ ul {
62
+ padding: 0 0 0 40px;
63
+ margin: 1em 0;
64
+ }
68
65
 
69
- <!-- BlueRobot was here. -->
66
+ .container {
67
+ max-width: 380px;
68
+ _width: 380px;
69
+ margin: 0 auto;
70
+ }
70
71
 
71
- </body>
72
+ input::-moz-focus-inner {
73
+ padding: 0;
74
+ border: 0;
75
+ }
76
+ </style>
77
+ </head>
78
+ <body>
79
+ <div class="container">
80
+ <h1>We've moved!</h1>
81
+ <p>The Runt project is now hosted on <a href="https://github.com/mlipper/runt">GitHub</a>.</p>
82
+ <ul>
83
+ <li><a href="https://github.com/mlipper/runt">Official Runt Project Home</a></li>
84
+ </ul>
85
+ </div>
86
+ </body>
72
87
  </html>
File without changes
File without changes
@@ -1,16 +1,13 @@
1
1
  #!/usr/bin/env ruby
2
2
 
3
- require 'test/unit'
4
- require 'runt'
5
- require 'date'
6
- require 'time'
3
+ require 'minitest_helper.rb'
7
4
 
8
5
  $DEBUG=false
9
6
 
10
7
  # Base test case for refactored temporal expression unit tests
11
8
  # Author:: Matthew Lipper
12
9
 
13
- class BaseExpressionTest < Test::Unit::TestCase
10
+ class BaseExpressionTest < MiniTest::Unit::TestCase
14
11
 
15
12
  include Runt
16
13
  include DPrecision
@@ -28,6 +25,7 @@ class BaseExpressionTest < Test::Unit::TestCase
28
25
  @pdate_20071028 = PDate.day(2007,10,28) # Sunday, October 28th, 2007
29
26
  @pdate_20071030 = PDate.day(2007,10,30) # Tuesday, October 30th, 2007
30
27
  @pdate_20071114 = PDate.day(2007,11,14) # Wednesday, November 14th, 2007
28
+ @pdate_20081112 = PDate.day(2008,11,12) # Wednesday, November 12th, 2008
31
29
  @pdate_1922041816 = PDate.hour(1922,4,18,16) # 4pm, Tuesday, April 18th, 1922
32
30
  @pdate_1975060512 = PDate.hour(1975,6,5,12) # 12pm, Thursday, June 5th, 1975
33
31
  @pdate_2004090600 = PDate.hour(2004,9,6,0) # 12am, Monday, September 6th, 2004
@@ -80,10 +78,14 @@ class BaseExpressionTest < Test::Unit::TestCase
80
78
  @time_20070930235959 = Time.mktime(2007,9,30,23,59,59) # 11:59:59am, Sunday, September 30th, 2007
81
79
  end
82
80
 
83
- def test_nothing
84
- # Sigh...I should figure out how to tell TestUnit that this is an "abstract" class
85
- end
81
+ # override default_test keeps it from growling about no other tests in this file
82
+ def default_test; end
86
83
 
84
+ def assert_raise_message(types, matcher, message = nil, &block)
85
+ args = [types].flatten + [message]
86
+ exception = assert_raise(*args, &block)
87
+ assert_match matcher, exception.message, message
88
+ end
87
89
  end
88
90
 
89
91
  class StubExpression
@@ -1,158 +1,166 @@
1
-
2
- #!/usr/bin/env ruby
3
-
4
- require 'baseexpressiontest'
5
-
6
- # Unit tests for composite temporal expressions
7
- # Author:: Matthew Lipper
8
-
9
- class CombinedExpressionTest < BaseExpressionTest
10
-
11
- def test_dates_on_last_fri_or_first_tues
12
- date_range = @date_20050101..@date_20051231
13
- expr = DIMonth.new(Last, Friday) | DIMonth.new(First, Tuesday)
14
- dates = expr.dates(date_range)
15
- assert_equal 24, dates.size, "Expected 24 dates in 2005 which were either on the last Friday or first Tuesday of the month"
16
- month_days = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]
17
- dates.each do |d|
18
- unless (d.wday == 2 and d.day < 8) or \
19
- (d.wday == 5 and d.day > month_days[d.month-1] - 8)
20
- # Fail
21
- assert false, d.to_s
22
- end
23
- end
24
- end
25
-
26
- def test_january_except_from_7th_to_15th
27
- date_range = @date_20050101..@date_20050131
28
- dates = (REYear.new(1, 1, 1, 31) - REMonth.new(7, 15)).dates(date_range)
29
- assert_equal 22, dates.size, "Expected 22 dates: 1/1-1/6, 1/16-1/31"
30
- end
31
-
32
- def test_work_day
33
- # Should match for 9am to 5pm except for 12pm to 1pm
34
- expr = REDay.new(9,0,17,0) - REDay.new(12,0,13,0)
35
- assert expr.include?(@pdate_200405030906), "Expression #{expr.to_s} should include #{@pdate_200405030906.to_s}"
36
- assert !expr.include?(@pdate_1975060512), "Expression #{expr.to_s} should not include #{@pdate_1975060512.to_s}"
37
- end
38
-
39
- def test_monday_tuesday_8am_to_9am
40
- expr = REWeek.new(Mon,Fri) & REDay.new(8,0,9,0)
41
- assert expr.include?(@pdate_200405040806), "Expression #{expr.to_s} should include #{@pdate_200405040806.to_s}"
42
- assert !expr.include?(@pdate_200405010806), "Expression #{expr.to_s} should not include #{@pdate_200405010806.to_s}"
43
- assert !expr.include?(@pdate_200405030906), "Expression #{expr.to_s} should not include #{@pdate_200405030906.to_s}"
44
- end
45
-
46
-
47
- def test_midnight_to_9am_or_tuesday
48
- expr = REDay.new(0,0,9,0) | DIWeek.new(Tuesday)
49
- assert expr.include?(@pdate_20071030), "Expression #{expr.to_s} should include #{@pdate_20071030.to_s}"
50
- assert expr.include?(@pdate_2012050803), "Expression #{expr.to_s} should include #{@pdate_2012050803.to_s}"
51
- assert !expr.include?(@pdate_20071116100030), "Expression #{expr.to_s} should not include #{@pdate_20071116100030.to_s}"
52
- end
53
-
54
- def test_wednesday_thru_saturday_6_to_12am
55
- expr = REWeek.new(Wed, Sat) & REDay.new(6,0,12,00)
56
- assert !expr.include?(@time_20070926000000), "Expression #{expr.to_s} should include #{@time_20070926000000.to_s}"
57
- assert expr.include?(@time_20070927065959), "Expression #{expr.to_s} should include #{@time_20070927065959.to_s}"
58
- assert !expr.include?(@time_20070928000000), "Expression #{expr.to_s} should include #{@time_20070928000000.to_s}"
59
- assert expr.include?(@time_20070929110000), "Expression #{expr.to_s} should include #{@time_20070929110000.to_s}"
60
- end
61
-
62
- def test_memorial_day
63
- # Monday through Friday, from 9am to 5pm
64
- job = REWeek.new(Mon,Fri) & REDay.new(9,00,17,00)
65
- # Memorial Day (U.S.)
66
- memorial_day = REYear.new(5) & DIMonth.new(Last,Monday)
67
- # May 29th, 2006
68
- last_monday_in_may = @pdate_200605291012
69
- # Before
70
- assert job.include?(last_monday_in_may), "Expression #{job.to_s} should include #{last_monday_in_may.to_s}"
71
- assert job.include?(@pdate_200605301400), "Expression #{job.to_s} should include #{@pdate_200605301400.to_s}"
72
- # Add Diff expression
73
- job_with_holiday = job - last_monday_in_may
74
- assert !job_with_holiday.include?(last_monday_in_may), "Expression #{job_with_holiday.to_s} should not include #{last_monday_in_may.to_s}"
75
- # Still have to work on Tuesday
76
- assert job.include?(@pdate_200605301400), "Expression #{job.to_s} should include #{@pdate_200605301400.to_s}"
77
- end
78
-
79
- def test_summertime
80
- #This is a hack.....
81
- #In the U.S., Memorial Day begins the last Monday of May
82
- #
83
- #The month of May
84
- may=REYear.new(5)
85
- #Monday through Saturday
86
- monday_to_saturday = REWeek.new(1,6)
87
- #Last week of (any) month
88
- last_week_in = WIMonth.new(Last_of)
89
- #So, to say 'starting from the last Monday in May',
90
- #we need to select just that last week of May begining with
91
- #the Monday of that week
92
- last_week_of_may = may & monday_to_saturday & last_week_in
93
-
94
- #This is another hack similar to the above, except instead of selecting a range
95
- #starting at the begining of the month, we need to select only the time period in
96
- #September up until Labor Day.
97
- #
98
- #In the U.S., Labor Day is the first Monday in September
99
- #
100
- #The month of September
101
- september=REYear.new(9)
102
- #First week of (any) month
103
- first_week_in = WIMonth.new(First)
104
- entire_first_week_of_september = september & first_week_in
105
- #To exclude everything in the first week which occurs on or after Monday.
106
- first_week_of_september=entire_first_week_of_september - monday_to_saturday
107
- #June through August
108
- june_through_august=REYear.new(6, 1, 8)
109
- assert june_through_august.include?(@pdate_20040704), "Expression #{june_through_august.to_s} should include #{@pdate_20040704.to_s}"
110
- #Finally!
111
- summer_time = last_week_of_may | first_week_of_september | june_through_august
112
-
113
- #Will work, but will be incredibly slow:
114
- # assert(summer_time.include?(PDate.min(2004,5,31,0,0)))
115
- assert summer_time.include?(@pdate_20040531), "Expression #{summer_time.to_s} should include #{@pdate_20040704.to_s}"
116
- assert summer_time.include?(@pdate_20040704), "Expression #{summer_time.to_s} should include #{@pdate_20040704.to_s}"
117
- #also works...also slow:
118
- # assert(!summer_time.include?(PDate.min(2004,9,6,0,0)))
119
- assert !summer_time.include?(@pdate_2004090600), "Expression #{summer_time.to_s} should not include #{@pdate_2004090600.to_s}"
120
-
121
- end
122
- def test_nyc_parking_te
123
-
124
- #Monday, Wednesday, Friday
125
- mon_wed_fri = DIWeek.new(Mon) | \
126
- DIWeek.new(Wed) | \
127
- DIWeek.new(Fri)
128
-
129
- assert mon_wed_fri.include?(@datetime_200403101915), "Expression #{mon_wed_fri.to_s} should include #{@datetime_200403101915.to_s}"
130
- assert !mon_wed_fri.include?(@datetime_200403140900), "Expression #{mon_wed_fri.to_s} should not include #{@datetime_200403140900.to_s}"
131
- # 8am to 11am
132
- eight_to_eleven = REDay.new(8,00,11,00)
133
- # => Mon,Wed,Fri - 8am to 11am
134
- expr1 = mon_wed_fri & eight_to_eleven
135
- # Tuesdays, Thursdays
136
- tues_thurs = DIWeek.new(Tue) | DIWeek.new(Thu)
137
- # 11:30am to 2pm
138
- eleven_thirty_to_two = REDay.new(11,30,14,00)
139
- assert eleven_thirty_to_two.include?(@datetime_200403081200), "Expression #{eleven_thirty_to_two.to_s} should include #{@datetime_200403081200.to_s}"
140
- assert !eleven_thirty_to_two.include?(@datetime_200403110000), "Expression #{eleven_thirty_to_two.to_s} should not include #{@datetime_200403110000.to_s}"
141
- # => Tues,Thurs - 11:30am to 2pm
142
- expr2 = tues_thurs & eleven_thirty_to_two
143
- #
144
- # No parking: Mon Wed Fri, 8am - 11am
145
- # Tu Thu, 11:30am - 2pm
146
- parking_ticket = expr1 | expr2
147
- assert parking_ticket.include?(@datetime_200403111215), "Expression #{parking_ticket.to_s} should include #{@datetime_200403111215.to_s}"
148
- assert parking_ticket.include?(@datetime_200403100915), "Expression #{parking_ticket.to_s} should include #{@datetime_200403100915.to_s}"
149
- assert parking_ticket.include?(@datetime_200403100800), "Expression #{parking_ticket.to_s} should include #{@datetime_200403100800.to_s}"
150
- assert !parking_ticket.include?(@datetime_200403110115), "Expression #{parking_ticket.to_s} should not include #{@datetime_200403110115.to_s}"
151
-
152
- # The preceeding example can be condensed to:
153
- # e1 = (DIWeek.new(Mon) | DIWeek.new(Wed) | DIWeek.new(Fri)) & REDay.new(8,00,11,00)
154
- # e2 = (DIWeek.new(Tue) | DIWeek.new(Thu)) & REDay.new(11,30,14,00)
155
- # ticket = e1 | e2
156
- end
157
-
158
- end
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'baseexpressiontest'
4
+
5
+ # Unit tests for composite temporal expressions
6
+ # Author:: Matthew Lipper
7
+
8
+ class CombinedExpressionTest < BaseExpressionTest
9
+
10
+ def test_dates_on_last_fri_or_first_tues
11
+ date_range = @date_20050101..@date_20051231
12
+ expr = DIMonth.new(Last, Friday) | DIMonth.new(First, Tuesday)
13
+ dates = expr.dates(date_range)
14
+ assert_equal 24, dates.size, "Expected 24 dates in 2005 which were either on the last Friday or first Tuesday of the month"
15
+ month_days = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]
16
+ dates.each do |d|
17
+ unless (d.wday == 2 and d.day < 8) or \
18
+ (d.wday == 5 and d.day > month_days[d.month-1] - 8)
19
+ # Fail
20
+ assert false, d.to_s
21
+ end
22
+ end
23
+ end
24
+
25
+ def test_january_except_from_7th_to_15th
26
+ date_range = @date_20050101..@date_20050131
27
+ dates = (REYear.new(1, 1, 1, 31) - REMonth.new(7, 15)).dates(date_range)
28
+ assert_equal 22, dates.size, "Expected 22 dates: 1/1-1/6, 1/16-1/31"
29
+ end
30
+
31
+ def test_work_day
32
+ # Should match for 9am to 5pm except for 12pm to 1pm
33
+ expr = REDay.new(9,0,17,0) - REDay.new(12,0,13,0)
34
+ assert expr.include?(@pdate_200405030906), "Expression #{expr.to_s} should include #{@pdate_200405030906.to_s}"
35
+ assert !expr.include?(@pdate_1975060512), "Expression #{expr.to_s} should not include #{@pdate_1975060512.to_s}"
36
+ end
37
+
38
+ def test_monday_tuesday_8am_to_9am
39
+ expr = REWeek.new(Mon,Fri) & REDay.new(8,0,9,0)
40
+ assert expr.include?(@pdate_200405040806), "Expression #{expr.to_s} should include #{@pdate_200405040806.to_s}"
41
+ assert !expr.include?(@pdate_200405010806), "Expression #{expr.to_s} should not include #{@pdate_200405010806.to_s}"
42
+ assert !expr.include?(@pdate_200405030906), "Expression #{expr.to_s} should not include #{@pdate_200405030906.to_s}"
43
+ end
44
+
45
+
46
+ def test_midnight_to_9am_or_tuesday
47
+ expr = REDay.new(0,0,9,0) | DIWeek.new(Tuesday)
48
+ assert expr.include?(@pdate_20071030), "Expression #{expr.to_s} should include #{@pdate_20071030.to_s}"
49
+ assert expr.include?(@pdate_2012050803), "Expression #{expr.to_s} should include #{@pdate_2012050803.to_s}"
50
+ assert !expr.include?(@pdate_20071116100030), "Expression #{expr.to_s} should not include #{@pdate_20071116100030.to_s}"
51
+ end
52
+
53
+ def test_wednesday_thru_saturday_6_to_12am
54
+ expr = REWeek.new(Wed, Sat) & REDay.new(6,0,12,00)
55
+ assert !expr.include?(@time_20070926000000), "Expression #{expr.to_s} should include #{@time_20070926000000.to_s}"
56
+ assert expr.include?(@time_20070927065959), "Expression #{expr.to_s} should include #{@time_20070927065959.to_s}"
57
+ assert !expr.include?(@time_20070928000000), "Expression #{expr.to_s} should include #{@time_20070928000000.to_s}"
58
+ assert expr.include?(@time_20070929110000), "Expression #{expr.to_s} should include #{@time_20070929110000.to_s}"
59
+ end
60
+
61
+ def test_memorial_day
62
+ # Monday through Friday, from 9am to 5pm
63
+ job = REWeek.new(Mon,Fri) & REDay.new(9,00,17,00)
64
+ # Memorial Day (U.S.)
65
+ memorial_day = REYear.new(5) & DIMonth.new(Last,Monday)
66
+ # May 29th, 2006
67
+ last_monday_in_may = @pdate_200605291012
68
+ # Before
69
+ assert job.include?(last_monday_in_may), "Expression #{job.to_s} should include #{last_monday_in_may.to_s}"
70
+ assert job.include?(@pdate_200605301400), "Expression #{job.to_s} should include #{@pdate_200605301400.to_s}"
71
+ # Add Diff expression
72
+ job_with_holiday = job - last_monday_in_may
73
+ assert !job_with_holiday.include?(last_monday_in_may), "Expression #{job_with_holiday.to_s} should not include #{last_monday_in_may.to_s}"
74
+ # Still have to work on Tuesday
75
+ assert job.include?(@pdate_200605301400), "Expression #{job.to_s} should include #{@pdate_200605301400.to_s}"
76
+ end
77
+
78
+ def test_summertime
79
+ #This is a hack.....
80
+ #In the U.S., Memorial Day begins the last Monday of May
81
+ #
82
+ #The month of May
83
+ may=REYear.new(5)
84
+ #Monday through Saturday
85
+ monday_to_saturday = REWeek.new(1,6)
86
+ #Last week of (any) month
87
+ last_week_in = WIMonth.new(Last_of)
88
+ #So, to say 'starting from the last Monday in May',
89
+ #we need to select just that last week of May begining with
90
+ #the Monday of that week
91
+ last_week_of_may = may & monday_to_saturday & last_week_in
92
+
93
+ #This is another hack similar to the above, except instead of selecting a range
94
+ #starting at the begining of the month, we need to select only the time period in
95
+ #September up until Labor Day.
96
+ #
97
+ #In the U.S., Labor Day is the first Monday in September
98
+ #
99
+ #The month of September
100
+ september=REYear.new(9)
101
+ #First week of (any) month
102
+ first_week_in = WIMonth.new(First)
103
+ entire_first_week_of_september = september & first_week_in
104
+ #To exclude everything in the first week which occurs on or after Monday.
105
+ first_week_of_september=entire_first_week_of_september - monday_to_saturday
106
+ #June through August
107
+ june_through_august=REYear.new(6, 1, 8)
108
+ assert june_through_august.include?(@pdate_20040704), "Expression #{june_through_august.to_s} should include #{@pdate_20040704.to_s}"
109
+ #Finally!
110
+ summer_time = last_week_of_may | first_week_of_september | june_through_august
111
+
112
+ #Will work, but will be incredibly slow:
113
+ # assert(summer_time.include?(PDate.min(2004,5,31,0,0)))
114
+ assert summer_time.include?(@pdate_20040531), "Expression #{summer_time.to_s} should include #{@pdate_20040704.to_s}"
115
+ assert summer_time.include?(@pdate_20040704), "Expression #{summer_time.to_s} should include #{@pdate_20040704.to_s}"
116
+ #also works...also slow:
117
+ # assert(!summer_time.include?(PDate.min(2004,9,6,0,0)))
118
+ assert !summer_time.include?(@pdate_2004090600), "Expression #{summer_time.to_s} should not include #{@pdate_2004090600.to_s}"
119
+
120
+ end
121
+ def test_nyc_parking_te
122
+
123
+ #Monday, Wednesday, Friday
124
+ mon_wed_fri = DIWeek.new(Mon) | \
125
+ DIWeek.new(Wed) | \
126
+ DIWeek.new(Fri)
127
+
128
+ assert mon_wed_fri.include?(@datetime_200403101915), "Expression #{mon_wed_fri.to_s} should include #{@datetime_200403101915.to_s}"
129
+ assert !mon_wed_fri.include?(@datetime_200403140900), "Expression #{mon_wed_fri.to_s} should not include #{@datetime_200403140900.to_s}"
130
+ # 8am to 11am
131
+ eight_to_eleven = REDay.new(8,00,11,00)
132
+ # => Mon,Wed,Fri - 8am to 11am
133
+ expr1 = mon_wed_fri & eight_to_eleven
134
+ # Tuesdays, Thursdays
135
+ tues_thurs = DIWeek.new(Tue) | DIWeek.new(Thu)
136
+ # 11:30am to 2pm
137
+ eleven_thirty_to_two = REDay.new(11,30,14,00)
138
+ assert eleven_thirty_to_two.include?(@datetime_200403081200), "Expression #{eleven_thirty_to_two.to_s} should include #{@datetime_200403081200.to_s}"
139
+ assert !eleven_thirty_to_two.include?(@datetime_200403110000), "Expression #{eleven_thirty_to_two.to_s} should not include #{@datetime_200403110000.to_s}"
140
+ # => Tues,Thurs - 11:30am to 2pm
141
+ expr2 = tues_thurs & eleven_thirty_to_two
142
+ #
143
+ # No parking: Mon Wed Fri, 8am - 11am
144
+ # Tu Thu, 11:30am - 2pm
145
+ parking_ticket = expr1 | expr2
146
+ assert parking_ticket.include?(@datetime_200403111215), "Expression #{parking_ticket.to_s} should include #{@datetime_200403111215.to_s}"
147
+ assert parking_ticket.include?(@datetime_200403100915), "Expression #{parking_ticket.to_s} should include #{@datetime_200403100915.to_s}"
148
+ assert parking_ticket.include?(@datetime_200403100800), "Expression #{parking_ticket.to_s} should include #{@datetime_200403100800.to_s}"
149
+ assert !parking_ticket.include?(@datetime_200403110115), "Expression #{parking_ticket.to_s} should not include #{@datetime_200403110115.to_s}"
150
+
151
+ # The preceeding example can be condensed to:
152
+ # e1 = (DIWeek.new(Mon) | DIWeek.new(Wed) | DIWeek.new(Fri)) & REDay.new(8,00,11,00)
153
+ # e2 = (DIWeek.new(Tue) | DIWeek.new(Thu)) & REDay.new(11,30,14,00)
154
+ # ticket = e1 | e2
155
+ end
156
+
157
+ def test_dates_every_four_hours_on_tuesdays
158
+ # 3am, Tuesday, May 8th, 2012 to 3am Wednesday, May 9th, 2012
159
+ range = DateRange.new(@pdate_2012050803, PDate.new(2012,5,9,15))
160
+ every_four_hours = EveryTE.new(@pdate_2012050803,4)
161
+ tuesday = DIWeek.new(Tuesday)
162
+ every_four_hours_on_tuesday = every_four_hours & tuesday
163
+ result = every_four_hours_on_tuesday.dates(range)
164
+ end
165
+
166
+ end