runt 0.7.0 → 0.9.0

Sign up to get free protection for your applications and to get access to all the features.
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