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 +31 -0
- data/lib/timeshifter.rb +97 -0
- data/lib/timeshifter/version.rb +3 -0
- data/test/helper.rb +6 -0
- data/test/test_timeshifter.rb +71 -0
- metadata +73 -0
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.
|
data/lib/timeshifter.rb
ADDED
@@ -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
|
data/test/helper.rb
ADDED
@@ -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
|