metra_schedule 0.2.1.2 → 0.2.2

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore ADDED
@@ -0,0 +1,2 @@
1
+ *.swp
2
+ *.gem
data/README.rdoc CHANGED
@@ -1,5 +1,7 @@
1
1
  = metra_schedule: A library to access the Chicago Metra schedule information as Ruby objects.
2
2
 
3
+ This is the data library that powers http://metra.blakesmith.me
4
+
3
5
  Supported Lines:
4
6
  Union Pacific Northwest => :up_nw
5
7
  Union Pacific North => :up_n
data/Rakefile CHANGED
@@ -21,3 +21,19 @@ Rake::TestTask.new(:test_integrations) do |t|
21
21
  t.test_files = FileList['test/integration/test*.rb']
22
22
  t.warning = false
23
23
  end
24
+
25
+ begin
26
+ require 'jeweler'
27
+ Jeweler::Tasks.new do |gemspec|
28
+ gemspec.name = "metra_schedule"
29
+ gemspec.summary = "Chicago Metra parser and scheduler"
30
+ gemspec.description = "metra_schedule provides a ruby object interface to the Chicago metra train schedule"
31
+ gemspec.email = "blakesmith0@gmail.com"
32
+ gemspec.homepage = "http://github.com/blakesmith/metra_schedule"
33
+ gemspec.authors = ["Blake Smith"]
34
+ gemspec.add_dependency('nokogiri', '>=1.4.1')
35
+ end
36
+ rescue LoadError
37
+ puts "Jeweler not available. Install it with: gem install jeweler"
38
+ end
39
+
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.2.2
@@ -0,0 +1,9 @@
1
+ module MetraSchedule
2
+ module Extensions
3
+ module TimeExtension
4
+ def to_today
5
+ Time.local(Time.now.year, Time.now.month, Time.now.day, self.hour, self.min, self.sec)
6
+ end
7
+ end
8
+ end
9
+ end
data/lib/metra/train.rb CHANGED
@@ -36,7 +36,7 @@ module MetraSchedule
36
36
  def departure_and_arrival(start, destination)
37
37
  departure = @stops.find {|s| s.station == start}.time
38
38
  arrival = @stops.find {|s| s.station == destination}.time
39
- {:departure => departure, :arrival => arrival}
39
+ {:departure => departure.to_today, :arrival => arrival.to_today}
40
40
  end
41
41
 
42
42
  def my_travel_time
@@ -88,6 +88,5 @@ module MetraSchedule
88
88
  return "#{my_travel_minutes} minutes" if my_travel_minutes > 1
89
89
  end
90
90
 
91
-
92
91
  end
93
92
  end
data/lib/metra.rb CHANGED
@@ -4,7 +4,10 @@ require File.join(File.dirname(__FILE__), 'metra', 'train')
4
4
  require File.join(File.dirname(__FILE__), 'metra', 'stop')
5
5
  require File.join(File.dirname(__FILE__), 'metra', 'parser')
6
6
  require File.join(File.dirname(__FILE__), 'metra', 'cacher')
7
+ require File.join(File.dirname(__FILE__), 'metra', 'extensions', 'time_extension')
7
8
 
8
9
  class Metra
9
10
  include MetraSchedule::InstanceMethods
10
11
  end
12
+
13
+ Time.send(:include, MetraSchedule::Extensions::TimeExtension)
@@ -0,0 +1,91 @@
1
+ # Generated by jeweler
2
+ # DO NOT EDIT THIS FILE DIRECTLY
3
+ # Instead, edit Jeweler::Tasks in Rakefile, and run the gemspec command
4
+ # -*- encoding: utf-8 -*-
5
+
6
+ Gem::Specification.new do |s|
7
+ s.name = %q{metra_schedule}
8
+ s.version = "0.2.2"
9
+
10
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
+ s.authors = ["Blake Smith"]
12
+ s.date = %q{2010-01-05}
13
+ s.description = %q{metra_schedule provides a ruby object interface to the Chicago metra train schedule}
14
+ s.email = %q{blakesmith0@gmail.com}
15
+ s.extra_rdoc_files = [
16
+ "LICENSE",
17
+ "README.rdoc"
18
+ ]
19
+ s.files = [
20
+ ".gitignore",
21
+ "LICENSE",
22
+ "README.rdoc",
23
+ "Rakefile",
24
+ "VERSION",
25
+ "lib/metra.rb",
26
+ "lib/metra/cacher.rb",
27
+ "lib/metra/classmethods.rb",
28
+ "lib/metra/extensions/time_extension.rb",
29
+ "lib/metra/line.rb",
30
+ "lib/metra/parser.rb",
31
+ "lib/metra/stop.rb",
32
+ "lib/metra/train.rb",
33
+ "lib/metra/train_data.rb",
34
+ "metra_schedule.gemspec",
35
+ "test/fixture/UP_NW.html",
36
+ "test/functional/test_all_filters.rb",
37
+ "test/integration/test_line_integration.rb",
38
+ "test/test_helper.rb",
39
+ "test/timecop/History.rdoc",
40
+ "test/timecop/LICENSE",
41
+ "test/timecop/README.rdoc",
42
+ "test/timecop/Rakefile",
43
+ "test/timecop/VERSION.yml",
44
+ "test/timecop/lib/timecop.rb",
45
+ "test/timecop/lib/timecop/time_extensions.rb",
46
+ "test/timecop/lib/timecop/time_stack_item.rb",
47
+ "test/timecop/lib/timecop/timecop.rb",
48
+ "test/unit/test_cacher.rb",
49
+ "test/unit/test_line.rb",
50
+ "test/unit/test_metra.rb",
51
+ "test/unit/test_parser.rb",
52
+ "test/unit/test_stop.rb",
53
+ "test/unit/test_time_extension.rb",
54
+ "test/unit/test_train.rb"
55
+ ]
56
+ s.homepage = %q{http://github.com/blakesmith/metra_schedule}
57
+ s.rdoc_options = ["--charset=UTF-8"]
58
+ s.require_paths = ["lib"]
59
+ s.rubygems_version = %q{1.3.5}
60
+ s.summary = %q{Chicago Metra parser and scheduler}
61
+ s.test_files = [
62
+ "test/integration/test_line_integration.rb",
63
+ "test/functional/test_all_filters.rb",
64
+ "test/timecop/lib/timecop/time_stack_item.rb",
65
+ "test/timecop/lib/timecop/timecop.rb",
66
+ "test/timecop/lib/timecop/time_extensions.rb",
67
+ "test/timecop/lib/timecop.rb",
68
+ "test/unit/test_time_extension.rb",
69
+ "test/unit/test_train.rb",
70
+ "test/unit/test_line.rb",
71
+ "test/unit/test_metra.rb",
72
+ "test/unit/test_stop.rb",
73
+ "test/unit/test_parser.rb",
74
+ "test/unit/test_cacher.rb",
75
+ "test/test_helper.rb"
76
+ ]
77
+
78
+ if s.respond_to? :specification_version then
79
+ current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
80
+ s.specification_version = 3
81
+
82
+ if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
83
+ s.add_runtime_dependency(%q<nokogiri>, [">= 1.4.1"])
84
+ else
85
+ s.add_dependency(%q<nokogiri>, [">= 1.4.1"])
86
+ end
87
+ else
88
+ s.add_dependency(%q<nokogiri>, [">= 1.4.1"])
89
+ end
90
+ end
91
+
@@ -0,0 +1,91 @@
1
+ === 0.3.4 / unreleased (RC2 released 2009-11-28)
2
+
3
+ * Maintenance
4
+ * Fix various timezone-related issues. Notably, when traveling to a DateTime
5
+ instance specified in a non-local timezone, convert provided DateTime
6
+ instance to a local instance and return that from DateTime.now.
7
+ Code contributed by Michaël Witrant [piglop]
8
+ * Fix bug that would not allow Timecop to be used when Ruby's 'date'
9
+ library had not been previously loaded.
10
+ Code contributed by Tuomas Kareinen [tuomas]
11
+ * Fix bug when traveling to a DateTime across a DST boundary that
12
+ resulted in DateTime's being off by an hour.
13
+ * Migrate argument parsing into Timecop::TimeStackItem to reduce the
14
+ responsibility of the Timecop class.
15
+
16
+ === 0.3.3 2009-10-30
17
+
18
+ * Revoked due to regression.
19
+
20
+ === 0.3.2 / 2009-10-24
21
+
22
+ * Revoked due to regression.
23
+
24
+ === 0.3.1 / 2009-09-30
25
+
26
+ * Maintenance
27
+ * DRY up the Timecop class internals.
28
+
29
+ === 0.3.0 / 2009-09-20
30
+
31
+ * API
32
+ * Completely remove Timecop#unset_all (deprecated by Timecop#return in 0.2.0)
33
+ * Return Time.now from #freeze, #travel and #return -- code contributed by Keith Bennett [keithrbennett]
34
+
35
+ * Maintenance
36
+ * Fix bug that left Time#mock_time set in some instances
37
+ * Upped build dependency to jeweler ~> 1.2.1
38
+ * Don't pollute top-level namespace with classes/constants
39
+
40
+ * Documentation
41
+ * Clearer examples in the README, better description in the gemspec
42
+ * Improve RDoc
43
+
44
+ === 0.2.1 / 2009-03-06
45
+ * API Changes
46
+
47
+ * Introduced a 5th style of arguments to be passed into #travel and #freeze. Now, if you pass in a single integer value,
48
+ it will be interpreted as a relative offset in seconds from the current Time.now. Previously this was interpreted as
49
+ only the year, similar to calling Time.local(2008) --> Jan. 1, 2008. This is no longer the case.
50
+
51
+ * Documentation
52
+
53
+ * Moved to Textile for the README.
54
+
55
+ * Added documentation for the new feature, and fixed a few typos.
56
+
57
+ === 0.2.0 / 2008-12-23
58
+
59
+ * API Changes
60
+
61
+ * Timecop#travel no longer freezes time. Rather, it computes the current offset between the new "now" and the real "now", and
62
+ returns times as if Time had continued to move forward
63
+
64
+ * Timecop#freeze now behaves exactly as the old Timecop#travel behaved. Unless you depended on the actual freezing of time
65
+ (which I think would be rare), you should be able to continue to use #travel without worry.
66
+
67
+ * Timecop#return is now exposed (previously Timecop#unset_all, but not well advertised). It will completely unmock time,
68
+ and will probably be rarely used outside of the actual implementation of this library.
69
+
70
+ * More Test Coverage
71
+
72
+ * Tests now explicitly cover the cases when the Date and DateTime objects are not loaded, and ensures proper functionality
73
+ in their absence and existence.
74
+
75
+ * Still haven't done regression testing against anything other than a few version of 1.8.6 (including REE). We should
76
+ probably try to get this tested on both 1.8.7 and 1.9.1.
77
+
78
+ * Documentation
79
+
80
+ * Fixed up a lot of the poorly-formatted rdoc syntax. The public API should now be properly published in the rdoc,
81
+ and the internals are omitted.
82
+
83
+ === 0.1.0 / 2008-11-09
84
+
85
+ * Initial Feature Set
86
+
87
+ * Temporarily (or permanently if you prefer) change the concept of Time.now, DateTime.now (if defined), and Date.today (if defined)
88
+ * Timecop#travel api allows an argument to be passed in as one of: 1) Time instance, 2) DateTime instance, 3) Date instance,
89
+ 4) individual arguments (year, month, day, hour, minute, second)
90
+ * Nested calls to Timecop#travel are supported -- each block will maintain it's interpretation of now.
91
+
@@ -0,0 +1,22 @@
1
+ (The MIT License)
2
+
3
+ Copyright (c) 2008
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ 'Software'), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
19
+ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
20
+ CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
21
+ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
22
+ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,68 @@
1
+ = timecop
2
+
3
+ * Source[http://github.com/jtrupiano/timecop]
4
+ * Documentation[http://johntrupiano.rubyforge.org/timecop]
5
+
6
+ == DESCRIPTION
7
+
8
+ A gem providing "time travel" and "time freezing" capabilities, making it dead simple to test time-dependent code. It provides a unified method to mock Time.now, Date.today, and DateTime.now in a single call.
9
+
10
+ == INSTALL
11
+
12
+ gem install timecop
13
+
14
+ == FEATURES
15
+
16
+ * Freeze time to a specific point.
17
+ * Travel back to a specific point in time, but allow time to continue moving forward from there.
18
+ * No dependencies, can be used with _any_ ruby project
19
+ * Timecop api allows arguments to be passed into #freeze and #travel as one of the following:
20
+ * Time instance
21
+ * DateTime instance
22
+ * Date instance
23
+ * individual arguments (year, month, day, hour, minute, second)
24
+ * a single integer argument that is interpreted as an offset in seconds from Time.now
25
+ * Nested calls to Timecop#travel and Timecop#freeze are supported -- each block will maintain its interpretation of now.
26
+
27
+ == USAGE
28
+
29
+ Run a time-sensitive test
30
+
31
+ joe = User.find(1)
32
+ joe.purchase_home()
33
+ assert !joe.mortgage_due?
34
+ # move ahead a month and assert that the mortgage is due
35
+ Timecop.freeze(Date.today + 30) do
36
+ assert joe.mortgage_due?
37
+ end
38
+
39
+ Set the time for the test environment of a rails app -- this is particularly helpful if your whole application is time-sensitive. It allows you to build your test data at a single point in time, and to move in/out of that time as appropriate (within your tests)
40
+
41
+ in config/environments/test.rb
42
+
43
+ config.after_initialize do
44
+ # Set Time.now to September 1, 2008 10:05:00 AM (at this instant), but allow it to move forward
45
+ t = Time.local(2008, 9, 1, 10, 5, 0)
46
+ Timecop.travel(t)
47
+ end
48
+
49
+ === The difference between Timecop.freeze and Timecop.travel
50
+
51
+ #freeze is used to statically mock the concept of now. As your program executes, Time.now will not change unless you make subsequent calls into the Timecop API. #travel, on the other hand, computes an offset between what we currently think Time.now is (recall that we support nested traveling) and the time passed in. It uses this offset to simulate the passage of time. To demonstrate, consider the following code snippets:
52
+
53
+ new_time = Time.local(2008, 9, 1, 12, 0, 0)
54
+ Timecop.freeze(new_time)
55
+ sleep(10)
56
+ new_time == Time.now # ==> true
57
+
58
+ Timecop.return # "turn off" Timecop
59
+ Timecop.travel(new_time)
60
+ sleep(10)
61
+ new_time == Time.now # ==> false
62
+
63
+ == REFERENCES
64
+
65
+ * {0.3.4 release}[http://blog.smartlogicsolutions.com/2009/12/07/timecop-0-3-4-released/]
66
+ * {0.3.0 release}[http://blog.smartlogicsolutions.com/2009/09/20/timecop-0-3-0-released/]
67
+ * {0.2.0 release}[http://blog.smartlogicsolutions.com/2008/12/24/timecop-2-released-freeze-and-rebase-time-ruby/]
68
+ * {0.1.0 release}[http://blog.smartlogicsolutions.com/2008/11/19/timecop-freeze-time-in-ruby-for-better-testing/]
@@ -0,0 +1,55 @@
1
+ require 'rake'
2
+ require 'rake/testtask'
3
+ require 'rake/rdoctask'
4
+
5
+ gem 'jeweler', '~> 1.3.0'
6
+
7
+ begin
8
+ require 'jeweler'
9
+ Jeweler::Tasks.new do |s|
10
+ s.name = "timecop"
11
+ s.rubyforge_project = 'johntrupiano' # if different than lowercase project name
12
+ s.description = %q(A gem providing "time travel" and "time freezing" capabilities, making it dead simple to test time-dependent code. It provides a unified method to mock Time.now, Date.today, and DateTime.now in a single call.)
13
+ s.summary = s.description # More details later??
14
+ s.email = "jtrupiano@gmail.com"
15
+ s.homepage = "http://github.com/jtrupiano/timecop"
16
+ s.authors = ["John Trupiano"]
17
+ s.files = FileList["[A-Z]*", "{bin,lib,test}/**/*"]
18
+ end
19
+ Jeweler::GemcutterTasks.new
20
+ Jeweler::RubyforgeTasks.new do |rubyforge|
21
+ rubyforge.doc_task = "rdoc"
22
+ rubyforge.remote_doc_path = "timecop"
23
+ end
24
+ rescue LoadError
25
+ puts "Jeweler, or one of its dependencies, is not available. Install it with: sudo gem install technicalpickles-jeweler -s http://gems.github.com"
26
+ end
27
+
28
+ # Override the test task and instruct them how to actually run the tests.
29
+ Rake.application.send(:eval, "@tasks.delete('test')")
30
+ desc "Does not execute tests. Manually run shell script ./run_tests.sh to execute tests."
31
+ task :test do
32
+ puts <<-MSG
33
+ In order to run the test suite, run: cd test && ./run_tests.sh
34
+ The tests need to be run with different libraries loaded, which rules out using Rake
35
+ to automate them.
36
+ MSG
37
+ end
38
+
39
+ require 'rake/rdoctask'
40
+ Rake::RDocTask.new do |rdoc|
41
+ if File.exist?('VERSION')
42
+ version = File.read('VERSION')
43
+ else
44
+ version = ""
45
+ end
46
+
47
+ rdoc.rdoc_dir = 'rdoc'
48
+ rdoc.options << '--line-numbers' << '--inline-source'
49
+ rdoc.title = "timecop #{version}"
50
+ rdoc.rdoc_files.include('README*')
51
+ rdoc.rdoc_files.include('History.rdoc')
52
+ rdoc.rdoc_files.include('lib/**/*.rb')
53
+ end
54
+
55
+ task :default => :test
@@ -0,0 +1,4 @@
1
+ ---
2
+ :patch: 5
3
+ :major: 0
4
+ :minor: 3
@@ -0,0 +1,72 @@
1
+
2
+ class Time #:nodoc:
3
+ class << self
4
+ # Time we are behaving as
5
+ def mock_time
6
+ mocked_time_stack_item = Timecop.top_stack_item
7
+ mocked_time_stack_item.nil? ? nil : mocked_time_stack_item.time
8
+ end
9
+
10
+ # Alias the original now
11
+ alias_method :now_without_mock_time, :now
12
+
13
+ # Define now_with_mock_time
14
+ def now_with_mock_time
15
+ mock_time || now_without_mock_time
16
+ end
17
+
18
+ # Alias now to now_with_mock_time
19
+ alias_method :now, :now_with_mock_time
20
+ end
21
+ end
22
+
23
+ if Object.const_defined?(:Date) && Date.respond_to?(:today)
24
+ class Date #:nodoc:
25
+ class << self
26
+ # Date we are behaving as
27
+ def mock_date
28
+ mocked_time_stack_item = Timecop.top_stack_item
29
+ mocked_time_stack_item.nil? ? nil : mocked_time_stack_item.date
30
+ end
31
+
32
+ # Alias the original today
33
+ alias_method :today_without_mock_date, :today
34
+
35
+ # Define today_with_mock_date
36
+ def today_with_mock_date
37
+ mock_date || today_without_mock_date
38
+ end
39
+
40
+ # Alias today to today_with_mock_date
41
+ alias_method :today, :today_with_mock_date
42
+ end
43
+ end
44
+ end
45
+
46
+ if Object.const_defined?(:DateTime) && DateTime.respond_to?(:now)
47
+ class DateTime #:nodoc:
48
+ class << self
49
+ # Time we are behaving as
50
+ def mock_time
51
+ mocked_time_stack_item = Timecop.top_stack_item
52
+ mocked_time_stack_item.nil? ? nil : mocked_time_stack_item.datetime
53
+ end
54
+
55
+ # Fake alias :now_without_mock_time :now
56
+ # It appears that the DateTime library itself references Time.now
57
+ # for it's interpretation of now which caused
58
+ # DateTime.now_without_mock_time to incorrectly return the frozen time.
59
+ def now_without_mock_time
60
+ Time.now_without_mock_time.send :to_datetime
61
+ end
62
+
63
+ # Define now_with_mock_time
64
+ def now_with_mock_time
65
+ mock_time || now_without_mock_time
66
+ end
67
+
68
+ # Alias now to now_with_mock_time
69
+ alias_method :now, :now_with_mock_time
70
+ end
71
+ end
72
+ end
@@ -0,0 +1,113 @@
1
+
2
+ class Timecop
3
+ # A data class for carrying around "time movement" objects. Makes it easy to keep track of the time
4
+ # movements on a simple stack.
5
+ class TimeStackItem #:nodoc:
6
+
7
+ attr_reader :mock_type
8
+ def initialize(mock_type, *args)
9
+ raise "Unknown mock_type #{mock_type}" unless [:freeze, :travel].include?(mock_type)
10
+ @mock_type = mock_type
11
+ @time = parse_time(*args)
12
+ @travel_offset = compute_travel_offset
13
+ @dst_adjustment = compute_dst_adjustment
14
+ end
15
+
16
+ def year
17
+ time.year
18
+ end
19
+
20
+ def month
21
+ time.month
22
+ end
23
+
24
+ def day
25
+ time.day
26
+ end
27
+
28
+ def hour
29
+ time.hour
30
+ end
31
+
32
+ def min
33
+ time.min
34
+ end
35
+
36
+ def sec
37
+ time.sec
38
+ end
39
+
40
+ def utc_offset
41
+ time.utc_offset
42
+ end
43
+
44
+ def travel_offset
45
+ @travel_offset
46
+ end
47
+
48
+ def time #:nodoc:
49
+ if travel_offset.nil?
50
+ @time
51
+ else
52
+ Time.now_without_mock_time + travel_offset
53
+ end
54
+ end
55
+
56
+ def date
57
+ time.send(:to_date)
58
+ end
59
+
60
+ def datetime
61
+ # DateTime doesn't know about DST, so let's remove its presence
62
+ our_offset = utc_offset + dst_adjustment
63
+ DateTime.new(year, month, day, hour, min, sec, utc_offset_to_rational(our_offset))
64
+ end
65
+
66
+ def dst_adjustment
67
+ @dst_adjustment
68
+ end
69
+
70
+ private
71
+ def rational_to_utc_offset(rational)
72
+ ((24.0 / rational.denominator) * rational.numerator) * (60 * 60)
73
+ end
74
+
75
+ def utc_offset_to_rational(utc_offset)
76
+ Rational(utc_offset, 24 * 60 * 60)
77
+ end
78
+
79
+ def parse_time(*args)
80
+ arg = args.shift
81
+ if arg.is_a?(Time)
82
+ arg.getlocal
83
+ elsif Object.const_defined?(:DateTime) && arg.is_a?(DateTime)
84
+ offset_difference = Time.now.utc_offset - rational_to_utc_offset(arg.offset)
85
+ Time.local(arg.year, arg.month, arg.day, arg.hour, arg.min, arg.sec) + offset_difference
86
+ elsif Object.const_defined?(:Date) && arg.is_a?(Date)
87
+ Time.local(arg.year, arg.month, arg.day, 0, 0, 0)
88
+ elsif args.empty? && arg.kind_of?(Integer)
89
+ Time.now + arg
90
+ else # we'll just assume it's a list of y/m/d/h/m/s
91
+ year = arg || 0
92
+ month = args.shift || 1
93
+ day = args.shift || 1
94
+ hour = args.shift || 0
95
+ minute = args.shift || 0
96
+ second = args.shift || 0
97
+ Time.local(year, month, day, hour, minute, second)
98
+ end
99
+ end
100
+
101
+ def compute_dst_adjustment
102
+ return 0 if !(time.dst? ^ Time.now.dst?)
103
+ return -1 * 60 * 60 if time.dst?
104
+ return 60 * 60
105
+ end
106
+
107
+ def compute_travel_offset
108
+ return nil if mock_type == :freeze
109
+ @time - Time.now_without_mock_time
110
+ end
111
+
112
+ end
113
+ end
@@ -0,0 +1,103 @@
1
+ require 'singleton'
2
+ require File.join(File.dirname(__FILE__), 'time_extensions')
3
+ require File.join(File.dirname(__FILE__), 'time_stack_item')
4
+
5
+ # Timecop
6
+ # * Wrapper class for manipulating the extensions to the Time, Date, and DateTime objects
7
+ # * Allows us to "freeze" time in our Ruby applications.
8
+ # * Optionally allows time travel to simulate a running clock, such time is not technically frozen.
9
+ #
10
+ # This is very useful when your app's functionality is dependent on time (e.g.
11
+ # anything that might expire). This will allow us to alter the return value of
12
+ # Date.today, Time.now, and DateTime.now, such that our application code _never_ has to change.
13
+ class Timecop
14
+ include Singleton
15
+
16
+ # Allows you to run a block of code and "fake" a time throughout the execution of that block.
17
+ # This is particularly useful for writing test methods where the passage of time is critical to the business
18
+ # logic being tested. For example:
19
+ #
20
+ # joe = User.find(1)
21
+ # joe.purchase_home()
22
+ # assert !joe.mortgage_due?
23
+ # Timecop.freeze(2008, 10, 5) do
24
+ # assert joe.mortgage_due?
25
+ # end
26
+ #
27
+ # freeze and travel will respond to several different arguments:
28
+ # 1. Timecop.freeze(time_inst)
29
+ # 2. Timecop.freeze(datetime_inst)
30
+ # 3. Timecop.freeze(date_inst)
31
+ # 4. Timecop.freeze(offset_in_seconds)
32
+ # 5. Timecop.freeze(year, month, day, hour=0, minute=0, second=0)
33
+ #
34
+ # When a block is also passed, Time.now, DateTime.now and Date.today are all reset to their
35
+ # previous values after the block has finished executing. This allows us to nest multiple
36
+ # calls to Timecop.travel and have each block maintain it's concept of "now."
37
+ #
38
+ # * Note: Timecop.freeze will actually freeze time. This can cause unanticipated problems if
39
+ # benchmark or other timing calls are executed, which implicitly expect Time to actually move
40
+ # forward.
41
+ #
42
+ # * Rails Users: Be especially careful when setting this in your development environment in a
43
+ # rails project. Generators will load your environment, including the migration generator,
44
+ # which will lead to files being generated with the timestamp set by the Timecop.freeze call
45
+ # in your dev environment
46
+ #
47
+ # Returns the frozen time.
48
+ def self.freeze(*args, &block)
49
+ instance().send(:travel, :freeze, *args, &block)
50
+ Time.now
51
+ end
52
+
53
+ # Allows you to run a block of code and "fake" a time throughout the execution of that block.
54
+ # See Timecop#freeze for a sample of how to use (same exact usage syntax)
55
+ #
56
+ # * Note: Timecop.travel will not freeze time (as opposed to Timecop.freeze). This is a particularly
57
+ # good candidate for use in environment files in rails projects.
58
+ #
59
+ # Returns the 'new' current Time.
60
+ def self.travel(*args, &block)
61
+ instance().send(:travel, :travel, *args, &block)
62
+ Time.now
63
+ end
64
+
65
+ # Reverts back to system's Time.now, Date.today and DateTime.now (if it exists).
66
+ #
67
+ # Returns Time.now, which is now the real current time.
68
+ def self.return
69
+ instance().send(:unmock!)
70
+ Time.now
71
+ end
72
+
73
+ def self.top_stack_item #:nodoc:
74
+ instance().instance_variable_get(:@_stack).last
75
+ end
76
+
77
+ protected
78
+
79
+ def initialize #:nodoc:
80
+ @_stack = []
81
+ end
82
+
83
+ def travel(mock_type, *args, &block) #:nodoc:
84
+ stack_item = TimeStackItem.new(mock_type, *args)
85
+
86
+ # store this time traveling on our stack...
87
+ @_stack << stack_item
88
+
89
+ if block_given?
90
+ begin
91
+ yield
92
+ ensure
93
+ # pull it off the stack...
94
+ @_stack.pop
95
+ end
96
+ end
97
+ end
98
+
99
+ def unmock! #:nodoc:
100
+ @_stack = []
101
+ end
102
+
103
+ end
@@ -0,0 +1,2 @@
1
+ # Require Timecop
2
+ require File.join(File.dirname(__FILE__), 'timecop', 'timecop')
@@ -0,0 +1,12 @@
1
+ require File.join(File.dirname(__FILE__), "../", "test_helper.rb")
2
+
3
+ class TestTimeExtension < Test::Unit::TestCase
4
+
5
+ def test_to_today
6
+ sample = Time.local(2009, 5, 5, 7, 30, 45)
7
+ today = Time.now
8
+ expected = Time.local(today.year, today.month, today.day, sample.hour, sample.min, sample.sec)
9
+ assert_equal(expected, sample.to_today)
10
+ end
11
+
12
+ end
@@ -82,6 +82,20 @@ class TestLine < Test::Unit::TestCase
82
82
  assert_equal(Time.parse("12:40"), train.my_arrival)
83
83
  end
84
84
 
85
+ def test_my_departure_and_my_arrival_with_cached_from_another_day
86
+ Timecop.freeze(2010, 1, 5)
87
+ stop1 = MetraSchedule::Stop.new :station => :barrington, :time => Time.parse("12:30")
88
+ stop2 = MetraSchedule::Stop.new :station => :arlington_heights, :time => Time.parse("12:40")
89
+ @@t = MetraSchedule::Train.new :train_num => 651, :bike_limit => 12, :schedule => :weekday, :direction => :inbound, :stops => [stop1, stop2]
90
+
91
+ Timecop.freeze(2010, 1, 6)
92
+ l = Metra.new.line(:up_nw).from(:barrington).to(:arlington_heights)
93
+ l.engines = [@@t]
94
+ train = l.trains.first
95
+ assert_equal(Time.parse("12:30"), train.my_departure)
96
+ assert_equal(Time.parse("12:40"), train.my_arrival)
97
+ end
98
+
85
99
  def test_my_departure_and_my_arrival_with_no_start_or_destination
86
100
  stop1 = MetraSchedule::Stop.new :station => :barrington, :time => Time.parse("12:30")
87
101
  stop2 = MetraSchedule::Stop.new :station => :arlington_heights, :time => Time.parse("12:40")
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: metra_schedule
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.1.2
4
+ version: 0.2.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Blake Smith
@@ -9,7 +9,7 @@ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
 
12
- date: 2009-12-31 00:00:00 -06:00
12
+ date: 2010-01-05 00:00:00 -06:00
13
13
  default_executable:
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
@@ -22,43 +22,58 @@ dependencies:
22
22
  - !ruby/object:Gem::Version
23
23
  version: 1.4.1
24
24
  version:
25
- description: metra_schedule provides a ruby object interface to the Chicago metra train schedule.
25
+ description: metra_schedule provides a ruby object interface to the Chicago metra train schedule
26
26
  email: blakesmith0@gmail.com
27
27
  executables: []
28
28
 
29
29
  extensions: []
30
30
 
31
- extra_rdoc_files: []
32
-
31
+ extra_rdoc_files:
32
+ - LICENSE
33
+ - README.rdoc
33
34
  files:
34
- - Rakefile
35
+ - .gitignore
35
36
  - LICENSE
36
37
  - README.rdoc
38
+ - Rakefile
39
+ - VERSION
37
40
  - lib/metra.rb
38
41
  - lib/metra/cacher.rb
39
42
  - lib/metra/classmethods.rb
43
+ - lib/metra/extensions/time_extension.rb
40
44
  - lib/metra/line.rb
41
45
  - lib/metra/parser.rb
42
46
  - lib/metra/stop.rb
43
47
  - lib/metra/train.rb
44
48
  - lib/metra/train_data.rb
45
- - test/test_helper.rb
49
+ - metra_schedule.gemspec
46
50
  - test/fixture/UP_NW.html
51
+ - test/functional/test_all_filters.rb
52
+ - test/integration/test_line_integration.rb
53
+ - test/test_helper.rb
54
+ - test/timecop/History.rdoc
55
+ - test/timecop/LICENSE
56
+ - test/timecop/README.rdoc
57
+ - test/timecop/Rakefile
58
+ - test/timecop/VERSION.yml
59
+ - test/timecop/lib/timecop.rb
60
+ - test/timecop/lib/timecop/time_extensions.rb
61
+ - test/timecop/lib/timecop/time_stack_item.rb
62
+ - test/timecop/lib/timecop/timecop.rb
47
63
  - test/unit/test_cacher.rb
48
64
  - test/unit/test_line.rb
49
65
  - test/unit/test_metra.rb
50
66
  - test/unit/test_parser.rb
51
67
  - test/unit/test_stop.rb
68
+ - test/unit/test_time_extension.rb
52
69
  - test/unit/test_train.rb
53
- - test/functional/test_all_filters.rb
54
- - test/integration/test_line_integration.rb
55
70
  has_rdoc: true
56
71
  homepage: http://github.com/blakesmith/metra_schedule
57
72
  licenses: []
58
73
 
59
74
  post_install_message:
60
- rdoc_options: []
61
-
75
+ rdoc_options:
76
+ - --charset=UTF-8
62
77
  require_paths:
63
78
  - lib
64
79
  required_ruby_version: !ruby/object:Gem::Requirement
@@ -79,6 +94,19 @@ rubyforge_project:
79
94
  rubygems_version: 1.3.5
80
95
  signing_key:
81
96
  specification_version: 3
82
- summary: metra_schedule provides a ruby object interface to the Chicago metra train schedule.
83
- test_files: []
84
-
97
+ summary: Chicago Metra parser and scheduler
98
+ test_files:
99
+ - test/integration/test_line_integration.rb
100
+ - test/functional/test_all_filters.rb
101
+ - test/timecop/lib/timecop/time_stack_item.rb
102
+ - test/timecop/lib/timecop/timecop.rb
103
+ - test/timecop/lib/timecop/time_extensions.rb
104
+ - test/timecop/lib/timecop.rb
105
+ - test/unit/test_time_extension.rb
106
+ - test/unit/test_train.rb
107
+ - test/unit/test_line.rb
108
+ - test/unit/test_metra.rb
109
+ - test/unit/test_stop.rb
110
+ - test/unit/test_parser.rb
111
+ - test/unit/test_cacher.rb
112
+ - test/test_helper.rb