timeshifter 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/README.md ADDED
@@ -0,0 +1,31 @@
1
+ Timeshifter
2
+ ===========
3
+
4
+ ## DESCRIPTION
5
+
6
+ Timeshifter is a library for shifting time around within a day. You can set
7
+ valid hour ranges and Timeshifter will spread a time out within those ranges.
8
+
9
+ For example, say your valid ranges are outside business hours (midnight until
10
+ 9am and 5pm until midnight). You can set those as your valid ranges and shift
11
+ your time within those ranges:
12
+
13
+ # Create a shifter for 12am-9am, 5pm-12am
14
+ shifter = Timeshifter.new([0..9, 17..24])
15
+ shifter.total_hours # => 16
16
+ shifter.shift(Time.utc(2010, 1, 1, 0, 0, 0)) # => "Fri Jan 01 00:00:00 UTC 2010"
17
+ shifter.shift(Time.utc(2010, 1, 1, 12, 0, 0)) # => "Fri Jan 01 08:00:00 UTC 2010"
18
+ shifter.shift(Time.utc(2010, 1, 1, 18, 0, 0)) # => "Fri Jan 01 20:00:00 UTC 2010"
19
+ shifter.shift(Time.utc(2010, 1, 1, 23, 59, 59)) # => "Fri Jan 01 23:59:59 UTC 2010"
20
+
21
+ Timeshifter follows the rules of [Semantic Versioning](http://semver.org/) and
22
+ uses [TomDoc](http://tomdoc.org/) for inline documentation.
23
+
24
+
25
+ ## CONTRIBUTE
26
+
27
+ Have a great idea for Timeshifter? Awesome. Fork the repository and add a
28
+ feature or fix a bug. There are a couple things I ask:
29
+
30
+ 1. You must have tests for all code you check in.
31
+ 1. Create an appropriately named topic branch that contains your change.
@@ -0,0 +1,97 @@
1
+ lib = File.expand_path('../lib', File.dirname(__FILE__))
2
+ $:.unshift lib unless $:.include?(lib)
3
+
4
+ require 'timeshifter/version'
5
+
6
+ class Timeshifter
7
+ ##############################################################################
8
+ #
9
+ # Constructor
10
+ #
11
+ ##############################################################################
12
+
13
+ # Initializes an object that will shift time within a valid set of ranges.
14
+ #
15
+ # ranges - A list of ranges to shift time within.
16
+ def initialize(ranges)
17
+ raise "Ranges are required" if ranges.nil?
18
+ @ranges = ranges.compact.sort {|x,y| x.begin <=> y.begin}
19
+ end
20
+
21
+
22
+ ##############################################################################
23
+ #
24
+ # Properties
25
+ #
26
+ ##############################################################################
27
+
28
+ # The list of valid ranges.
29
+ def ranges
30
+ Array.new(@ranges)
31
+ end
32
+
33
+
34
+ ##############################################################################
35
+ #
36
+ # Methods
37
+ #
38
+ ##############################################################################
39
+
40
+ # Shifts the time to a valid time in the day based on the ranges provided.
41
+ #
42
+ # time - The time to shift.
43
+ #
44
+ # Returns a time that is within the valid ranges.
45
+ def shift(time)
46
+ return nil if time.nil?
47
+
48
+ # Check if it's UTC
49
+ is_utc = time.utc?
50
+
51
+ # Determine the total available seconds from the ranges.
52
+ tsec = (total_hours * 3600).to_f
53
+ raise "No hours available to shift within" if tsec == 0
54
+
55
+ # Determine original seconds in time for the day
56
+ osec = ((time.hour*3600) + (time.min*60) + time.sec).to_f
57
+
58
+ # Determine time shifted seconds in time for the day
59
+ sec = osec * (tsec/86400)
60
+
61
+ # Work through ranges and compact time
62
+ current = 0.0
63
+ ranges.each do |range|
64
+ rsec = ((range.end - range.begin) * 3600).to_f
65
+
66
+ # If time time is within this range calculate the position
67
+ if sec < current+rsec
68
+ shifted_time = Time.at(time.to_i - osec.to_i + (range.begin*3600)+(sec-current).to_i)
69
+
70
+ # Return UTC if that's what was passed in
71
+ if is_utc
72
+ shifted_time = shifted_time.getutc()
73
+ end
74
+
75
+ return shifted_time
76
+ end
77
+
78
+ # Add range second total to current seconds
79
+ current += rsec
80
+ end
81
+
82
+ # We should have been able to shift within a range by now
83
+ raise "Time could not be shifted inside range: #{osec} #{sec} #{current}"
84
+ end
85
+
86
+ # Calculates the total hours available based on the ranges provided.
87
+ def total_hours
88
+ total = 0
89
+
90
+ # Calculate total
91
+ ranges.each do |range|
92
+ total += range.end - range.begin
93
+ end
94
+
95
+ return total
96
+ end
97
+ end
@@ -0,0 +1,3 @@
1
+ class Timeshifter
2
+ VERSION = "0.1.0"
3
+ end
data/test/helper.rb ADDED
@@ -0,0 +1,6 @@
1
+ lib = File.expand_path('../lib', File.dirname(__FILE__))
2
+ $:.unshift lib unless $:.include?(lib)
3
+
4
+ require 'rubygems'
5
+ require 'minitest/autorun'
6
+ require 'timeshifter'
@@ -0,0 +1,71 @@
1
+ require File.dirname(__FILE__) + '/helper'
2
+
3
+ class TimeshifterTestCase < MiniTest::Unit::TestCase
4
+ ## Initialization ############################################################
5
+
6
+ def test_raise_error_for_nil_ranges
7
+ assert_raises RuntimeError do
8
+ shifter = Timeshifter.new(nil)
9
+ end
10
+ end
11
+
12
+
13
+ ## Total Hours ###############################################################
14
+
15
+ def test_should_calculate_total_hours_simple
16
+ shifter = Timeshifter.new([0..12])
17
+ assert_equal 12, shifter.total_hours
18
+ end
19
+
20
+ def test_should_calculate_total_hours_complex
21
+ shifter = Timeshifter.new([0..8, 18..24])
22
+ assert_equal 14, shifter.total_hours
23
+ end
24
+
25
+ def test_should_calculate_total_hours_for_empty_ranges
26
+ shifter = Timeshifter.new([])
27
+ assert_equal 0, shifter.total_hours
28
+ end
29
+
30
+
31
+ ## Shifting ##################################################################
32
+
33
+ def test_should_shift_to_original_time
34
+ shifter = Timeshifter.new([0..24])
35
+ assert_equal 'Fri Jan 01 12:00:00 UTC 2010', shifter.shift(Time.utc(2010, 1, 1, 12, 0, 0)).to_s
36
+ end
37
+
38
+ def test_should_shift_simple
39
+ shifter = Timeshifter.new([0..12])
40
+ assert_equal 'Fri Jan 01 04:00:00 UTC 2010', shifter.shift(Time.utc(2010, 1, 1, 8, 0, 0)).to_s
41
+ end
42
+
43
+ def test_should_shift_complex
44
+ shifter = Timeshifter.new([0..8, 16..24])
45
+ assert_equal 'Fri Jan 01 06:00:00 UTC 2010', shifter.shift(Time.utc(2010, 1, 1, 9, 0, 0)).to_s
46
+ end
47
+
48
+ def test_should_shift_to_secondary_range
49
+ shifter = Timeshifter.new([0..8, 16..24])
50
+ assert_equal 'Fri Jan 01 16:00:00 UTC 2010', shifter.shift(Time.utc(2010, 1, 1, 12, 0, 0)).to_s
51
+ end
52
+
53
+ def test_should_shift_to_secondary_range2
54
+ shifter = Timeshifter.new([0..8, 16..24])
55
+ assert_equal 'Fri Jan 01 20:00:00 UTC 2010', shifter.shift(Time.utc(2010, 1, 1, 18, 0, 0)).to_s
56
+ end
57
+
58
+ def test_should_shift_to_end_of_ranges
59
+ shifter = Timeshifter.new([0..8, 16..24])
60
+ assert_equal 'Fri Jan 01 23:59:59 UTC 2010', shifter.shift(Time.utc(2010, 1, 1, 23, 59, 59)).to_s
61
+ end
62
+
63
+
64
+ def test_should_shift_ranges_specified_in_readme
65
+ shifter = Timeshifter.new([0..9, 17..24])
66
+ assert_equal 'Fri Jan 01 00:00:00 UTC 2010', shifter.shift(Time.utc(2010, 1, 1, 0, 0, 0)).to_s
67
+ assert_equal 'Fri Jan 01 08:00:00 UTC 2010', shifter.shift(Time.utc(2010, 1, 1, 12, 0, 0)).to_s
68
+ assert_equal 'Fri Jan 01 20:00:00 UTC 2010', shifter.shift(Time.utc(2010, 1, 1, 18, 0, 0)).to_s
69
+ assert_equal 'Fri Jan 01 23:59:59 UTC 2010', shifter.shift(Time.utc(2010, 1, 1, 23, 59, 59)).to_s
70
+ end
71
+ end
metadata ADDED
@@ -0,0 +1,73 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: timeshifter
3
+ version: !ruby/object:Gem::Version
4
+ hash: 27
5
+ prerelease: false
6
+ segments:
7
+ - 0
8
+ - 1
9
+ - 0
10
+ version: 0.1.0
11
+ platform: ruby
12
+ authors:
13
+ - Ben Johnson
14
+ autorequire:
15
+ bindir: bin
16
+ cert_chain: []
17
+
18
+ date: 2010-09-30 00:00:00 -06:00
19
+ default_executable:
20
+ dependencies: []
21
+
22
+ description:
23
+ email:
24
+ - benbjohnson@yahoo.com
25
+ executables: []
26
+
27
+ extensions: []
28
+
29
+ extra_rdoc_files: []
30
+
31
+ files:
32
+ - lib/timeshifter/version.rb
33
+ - lib/timeshifter.rb
34
+ - README.md
35
+ - test/helper.rb
36
+ - test/test_timeshifter.rb
37
+ has_rdoc: true
38
+ homepage:
39
+ licenses: []
40
+
41
+ post_install_message:
42
+ rdoc_options: []
43
+
44
+ require_paths:
45
+ - lib
46
+ required_ruby_version: !ruby/object:Gem::Requirement
47
+ none: false
48
+ requirements:
49
+ - - ">="
50
+ - !ruby/object:Gem::Version
51
+ hash: 3
52
+ segments:
53
+ - 0
54
+ version: "0"
55
+ required_rubygems_version: !ruby/object:Gem::Requirement
56
+ none: false
57
+ requirements:
58
+ - - ">="
59
+ - !ruby/object:Gem::Version
60
+ hash: 3
61
+ segments:
62
+ - 0
63
+ version: "0"
64
+ requirements: []
65
+
66
+ rubyforge_project:
67
+ rubygems_version: 1.3.7
68
+ signing_key:
69
+ specification_version: 3
70
+ summary: A library for shifting time.
71
+ test_files:
72
+ - test/helper.rb
73
+ - test/test_timeshifter.rb