ice_cube_chosko 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/config/locales/en.yml +178 -0
- data/config/locales/es.yml +176 -0
- data/config/locales/ja.yml +107 -0
- data/lib/ice_cube.rb +92 -0
- data/lib/ice_cube/builders/hash_builder.rb +27 -0
- data/lib/ice_cube/builders/ical_builder.rb +59 -0
- data/lib/ice_cube/builders/string_builder.rb +76 -0
- data/lib/ice_cube/deprecated.rb +36 -0
- data/lib/ice_cube/errors/count_exceeded.rb +7 -0
- data/lib/ice_cube/errors/until_exceeded.rb +7 -0
- data/lib/ice_cube/flexible_hash.rb +40 -0
- data/lib/ice_cube/i18n.rb +24 -0
- data/lib/ice_cube/null_i18n.rb +28 -0
- data/lib/ice_cube/occurrence.rb +101 -0
- data/lib/ice_cube/parsers/hash_parser.rb +91 -0
- data/lib/ice_cube/parsers/ical_parser.rb +91 -0
- data/lib/ice_cube/parsers/yaml_parser.rb +19 -0
- data/lib/ice_cube/rule.rb +123 -0
- data/lib/ice_cube/rules/daily_rule.rb +16 -0
- data/lib/ice_cube/rules/hourly_rule.rb +16 -0
- data/lib/ice_cube/rules/minutely_rule.rb +16 -0
- data/lib/ice_cube/rules/monthly_rule.rb +16 -0
- data/lib/ice_cube/rules/secondly_rule.rb +15 -0
- data/lib/ice_cube/rules/weekly_rule.rb +16 -0
- data/lib/ice_cube/rules/yearly_rule.rb +16 -0
- data/lib/ice_cube/schedule.rb +529 -0
- data/lib/ice_cube/single_occurrence_rule.rb +28 -0
- data/lib/ice_cube/time_util.rb +328 -0
- data/lib/ice_cube/validated_rule.rb +184 -0
- data/lib/ice_cube/validations/count.rb +61 -0
- data/lib/ice_cube/validations/daily_interval.rb +54 -0
- data/lib/ice_cube/validations/day.rb +71 -0
- data/lib/ice_cube/validations/day_of_month.rb +55 -0
- data/lib/ice_cube/validations/day_of_week.rb +77 -0
- data/lib/ice_cube/validations/day_of_year.rb +61 -0
- data/lib/ice_cube/validations/fixed_value.rb +95 -0
- data/lib/ice_cube/validations/hour_of_day.rb +55 -0
- data/lib/ice_cube/validations/hourly_interval.rb +54 -0
- data/lib/ice_cube/validations/lock.rb +95 -0
- data/lib/ice_cube/validations/minute_of_hour.rb +54 -0
- data/lib/ice_cube/validations/minutely_interval.rb +54 -0
- data/lib/ice_cube/validations/month_of_year.rb +54 -0
- data/lib/ice_cube/validations/monthly_interval.rb +53 -0
- data/lib/ice_cube/validations/schedule_lock.rb +46 -0
- data/lib/ice_cube/validations/second_of_minute.rb +54 -0
- data/lib/ice_cube/validations/secondly_interval.rb +51 -0
- data/lib/ice_cube/validations/until.rb +57 -0
- data/lib/ice_cube/validations/weekly_interval.rb +67 -0
- data/lib/ice_cube/validations/yearly_interval.rb +53 -0
- data/lib/ice_cube/version.rb +5 -0
- data/spec/spec_helper.rb +64 -0
- metadata +166 -0
data/lib/ice_cube.rb
ADDED
@@ -0,0 +1,92 @@
|
|
1
|
+
require 'date'
|
2
|
+
require 'ice_cube/deprecated'
|
3
|
+
require 'ice_cube/i18n'
|
4
|
+
|
5
|
+
IceCube::I18n.detect_backend!
|
6
|
+
|
7
|
+
module IceCube
|
8
|
+
|
9
|
+
autoload :VERSION, 'ice_cube/version'
|
10
|
+
|
11
|
+
autoload :TimeUtil, 'ice_cube/time_util'
|
12
|
+
autoload :FlexibleHash, 'ice_cube/flexible_hash'
|
13
|
+
|
14
|
+
autoload :Rule, 'ice_cube/rule'
|
15
|
+
autoload :Schedule, 'ice_cube/schedule'
|
16
|
+
autoload :Occurrence, 'ice_cube/occurrence'
|
17
|
+
|
18
|
+
autoload :IcalBuilder, 'ice_cube/builders/ical_builder'
|
19
|
+
autoload :HashBuilder, 'ice_cube/builders/hash_builder'
|
20
|
+
autoload :StringBuilder, 'ice_cube/builders/string_builder'
|
21
|
+
|
22
|
+
autoload :HashParser, 'ice_cube/parsers/hash_parser'
|
23
|
+
autoload :YamlParser, 'ice_cube/parsers/yaml_parser'
|
24
|
+
autoload :IcalParser, 'ice_cube/parsers/ical_parser'
|
25
|
+
|
26
|
+
autoload :CountExceeded, 'ice_cube/errors/count_exceeded'
|
27
|
+
autoload :UntilExceeded, 'ice_cube/errors/until_exceeded'
|
28
|
+
|
29
|
+
autoload :ValidatedRule, 'ice_cube/validated_rule'
|
30
|
+
autoload :SingleOccurrenceRule, 'ice_cube/single_occurrence_rule'
|
31
|
+
|
32
|
+
autoload :SecondlyRule, 'ice_cube/rules/secondly_rule'
|
33
|
+
autoload :MinutelyRule, 'ice_cube/rules/minutely_rule'
|
34
|
+
autoload :HourlyRule, 'ice_cube/rules/hourly_rule'
|
35
|
+
autoload :DailyRule, 'ice_cube/rules/daily_rule'
|
36
|
+
autoload :WeeklyRule, 'ice_cube/rules/weekly_rule'
|
37
|
+
autoload :MonthlyRule, 'ice_cube/rules/monthly_rule'
|
38
|
+
autoload :YearlyRule, 'ice_cube/rules/yearly_rule'
|
39
|
+
|
40
|
+
module Validations
|
41
|
+
autoload :FixedValue, 'ice_cube/validations/fixed_value'
|
42
|
+
autoload :ScheduleLock, 'ice_cube/validations/schedule_lock'
|
43
|
+
|
44
|
+
autoload :Count, 'ice_cube/validations/count'
|
45
|
+
autoload :Until, 'ice_cube/validations/until'
|
46
|
+
|
47
|
+
autoload :SecondlyInterval, 'ice_cube/validations/secondly_interval'
|
48
|
+
autoload :MinutelyInterval, 'ice_cube/validations/minutely_interval'
|
49
|
+
autoload :DailyInterval, 'ice_cube/validations/daily_interval'
|
50
|
+
autoload :WeeklyInterval, 'ice_cube/validations/weekly_interval'
|
51
|
+
autoload :MonthlyInterval, 'ice_cube/validations/monthly_interval'
|
52
|
+
autoload :YearlyInterval, 'ice_cube/validations/yearly_interval'
|
53
|
+
autoload :HourlyInterval, 'ice_cube/validations/hourly_interval'
|
54
|
+
|
55
|
+
autoload :HourOfDay, 'ice_cube/validations/hour_of_day'
|
56
|
+
autoload :MonthOfYear, 'ice_cube/validations/month_of_year'
|
57
|
+
autoload :MinuteOfHour, 'ice_cube/validations/minute_of_hour'
|
58
|
+
autoload :SecondOfMinute, 'ice_cube/validations/second_of_minute'
|
59
|
+
autoload :DayOfMonth, 'ice_cube/validations/day_of_month'
|
60
|
+
autoload :DayOfWeek, 'ice_cube/validations/day_of_week'
|
61
|
+
autoload :Day, 'ice_cube/validations/day'
|
62
|
+
autoload :DayOfYear, 'ice_cube/validations/day_of_year'
|
63
|
+
end
|
64
|
+
|
65
|
+
# Define some useful constants
|
66
|
+
ONE_SECOND = 1
|
67
|
+
ONE_MINUTE = ONE_SECOND * 60
|
68
|
+
ONE_HOUR = ONE_MINUTE * 60
|
69
|
+
ONE_DAY = ONE_HOUR * 24
|
70
|
+
ONE_WEEK = ONE_DAY * 7
|
71
|
+
|
72
|
+
# Defines the format used by IceCube when printing out Schedule#to_s.
|
73
|
+
# Defaults to '%B %e, %Y'
|
74
|
+
def self.to_s_time_format
|
75
|
+
IceCube::I18n.t("ice_cube.date.formats.default")
|
76
|
+
end
|
77
|
+
|
78
|
+
# Sets the format used by IceCube when printing out Schedule#to_s.
|
79
|
+
def self.to_s_time_format=(format)
|
80
|
+
@to_s_time_format = format
|
81
|
+
end
|
82
|
+
|
83
|
+
# Retain backwards compatibility for schedules exported from older versions
|
84
|
+
# This represents the version number, 11 = 0.11, 1.0 will be 100
|
85
|
+
def self.compatibility
|
86
|
+
@compatibility ||= IceCube::VERSION.scan(/\d+/)[0..1].join.to_i
|
87
|
+
end
|
88
|
+
|
89
|
+
def self.compatibility=(version)
|
90
|
+
@compatibility = version
|
91
|
+
end
|
92
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
module IceCube
|
2
|
+
|
3
|
+
class HashBuilder
|
4
|
+
|
5
|
+
def initialize(rule = nil)
|
6
|
+
@hash = { :validations => {}, :rule_type => rule.class.name }
|
7
|
+
end
|
8
|
+
|
9
|
+
def validations
|
10
|
+
@hash[:validations]
|
11
|
+
end
|
12
|
+
|
13
|
+
def []=(key, value)
|
14
|
+
@hash[key] = value
|
15
|
+
end
|
16
|
+
|
17
|
+
def validations_array(type)
|
18
|
+
validations[type] ||= []
|
19
|
+
end
|
20
|
+
|
21
|
+
def to_hash
|
22
|
+
@hash
|
23
|
+
end
|
24
|
+
|
25
|
+
end
|
26
|
+
|
27
|
+
end
|
@@ -0,0 +1,59 @@
|
|
1
|
+
module IceCube
|
2
|
+
|
3
|
+
class IcalBuilder
|
4
|
+
|
5
|
+
ICAL_DAYS = ['SU', 'MO', 'TU', 'WE', 'TH', 'FR', 'SA']
|
6
|
+
|
7
|
+
def initialize
|
8
|
+
@hash = {}
|
9
|
+
end
|
10
|
+
|
11
|
+
def self.fixnum_to_ical_day(num)
|
12
|
+
ICAL_DAYS[num]
|
13
|
+
end
|
14
|
+
|
15
|
+
def [](key)
|
16
|
+
@hash[key] ||= []
|
17
|
+
end
|
18
|
+
|
19
|
+
# Build for a single rule entry
|
20
|
+
def to_s
|
21
|
+
arr = []
|
22
|
+
if freq = @hash.delete('FREQ')
|
23
|
+
arr << "FREQ=#{freq.join(',')}"
|
24
|
+
end
|
25
|
+
arr.concat(@hash.map do |key, value|
|
26
|
+
if value.is_a?(Array)
|
27
|
+
"#{key}=#{value.join(',')}"
|
28
|
+
end
|
29
|
+
end.compact)
|
30
|
+
arr.join(';')
|
31
|
+
end
|
32
|
+
|
33
|
+
def self.ical_utc_format(time)
|
34
|
+
time = time.dup.utc
|
35
|
+
IceCube::I18n.l(time, format: '%Y%m%dT%H%M%SZ') # utc time
|
36
|
+
end
|
37
|
+
|
38
|
+
def self.ical_format(time, force_utc)
|
39
|
+
time = time.dup.utc if force_utc
|
40
|
+
if time.utc?
|
41
|
+
":#{IceCube::I18n.l(time, format: '%Y%m%dT%H%M%SZ')}" # utc time
|
42
|
+
else
|
43
|
+
";TZID=#{IceCube::I18n.l(time, format: '%Z:%Y%m%dT%H%M%S')}" # local time specified
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
def self.ical_duration(duration)
|
48
|
+
hours = duration / 3600; duration %= 3600
|
49
|
+
minutes = duration / 60; duration %= 60
|
50
|
+
repr = ''
|
51
|
+
repr << "#{hours}H" if hours > 0
|
52
|
+
repr << "#{minutes}M" if minutes > 0
|
53
|
+
repr << "#{duration}S" if duration > 0
|
54
|
+
"PT#{repr}"
|
55
|
+
end
|
56
|
+
|
57
|
+
end
|
58
|
+
|
59
|
+
end
|
@@ -0,0 +1,76 @@
|
|
1
|
+
module IceCube
|
2
|
+
|
3
|
+
class StringBuilder
|
4
|
+
|
5
|
+
attr_writer :base
|
6
|
+
|
7
|
+
def initialize
|
8
|
+
@types = {}
|
9
|
+
end
|
10
|
+
|
11
|
+
def piece(type, prefix = nil, suffix = nil)
|
12
|
+
@types[type] ||= []
|
13
|
+
end
|
14
|
+
|
15
|
+
def to_s
|
16
|
+
string = @base || ''
|
17
|
+
@types.each do |type, segments|
|
18
|
+
if f = self.class.formatter(type)
|
19
|
+
current = f.call(segments)
|
20
|
+
else
|
21
|
+
next if segments.empty?
|
22
|
+
current = self.class.sentence(segments)
|
23
|
+
end
|
24
|
+
f = IceCube::I18n.t('ice_cube.string.format')[type] ? type : 'default'
|
25
|
+
string = IceCube::I18n.t("ice_cube.string.format.#{f}", rest: string, current: current)
|
26
|
+
end
|
27
|
+
string
|
28
|
+
end
|
29
|
+
|
30
|
+
def self.formatter(type)
|
31
|
+
@formatters[type]
|
32
|
+
end
|
33
|
+
|
34
|
+
def self.register_formatter(type, &formatter)
|
35
|
+
@formatters ||= {}
|
36
|
+
@formatters[type] = formatter
|
37
|
+
end
|
38
|
+
|
39
|
+
module Helpers
|
40
|
+
|
41
|
+
# influenced by ActiveSupport's to_sentence
|
42
|
+
def sentence(array)
|
43
|
+
case array.length
|
44
|
+
when 0 ; ''
|
45
|
+
when 1 ; array[0].to_s
|
46
|
+
when 2 ; "#{array[0]}#{IceCube::I18n.t('ice_cube.array.two_words_connector')}#{array[1]}"
|
47
|
+
else ; "#{array[0...-1].join(IceCube::I18n.t('ice_cube.array.words_connector'))}#{IceCube::I18n.t('ice_cube.array.last_word_connector')}#{array[-1]}"
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
def nice_number(number)
|
52
|
+
literal_ordinal(number) || ordinalize(number)
|
53
|
+
end
|
54
|
+
|
55
|
+
def ordinalize(number)
|
56
|
+
IceCube::I18n.t('ice_cube.integer.ordinal', number: number, ordinal: ordinal(number))
|
57
|
+
end
|
58
|
+
|
59
|
+
def literal_ordinal(number)
|
60
|
+
IceCube::I18n.t("ice_cube.integer.literal_ordinals")[number]
|
61
|
+
end
|
62
|
+
|
63
|
+
def ordinal(number)
|
64
|
+
ord = IceCube::I18n.t("ice_cube.integer.ordinals")[number] ||
|
65
|
+
IceCube::I18n.t("ice_cube.integer.ordinals")[number % 10] ||
|
66
|
+
IceCube::I18n.t('ice_cube.integer.ordinals')[:default]
|
67
|
+
number >= 0 ? ord : IceCube::I18n.t("ice_cube.integer.negative", ordinal: ord)
|
68
|
+
end
|
69
|
+
|
70
|
+
end
|
71
|
+
|
72
|
+
extend Helpers
|
73
|
+
|
74
|
+
end
|
75
|
+
|
76
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
module IceCube
|
2
|
+
module Deprecated
|
3
|
+
|
4
|
+
# Define a deprecated alias for a method
|
5
|
+
# @param [Symbol] name - name of method to define
|
6
|
+
# @param [Symbol] replacement - name of method to replace (alias)
|
7
|
+
def deprecated_alias(name, replacement)
|
8
|
+
# Create a wrapped version
|
9
|
+
define_method(name) do |*args, &block|
|
10
|
+
warn "IceCube: #{self.class}##{name} is deprecated, please use ##{replacement} at: #{ caller[0] }"
|
11
|
+
send replacement, *args, &block
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
# Deprecate a defined method
|
16
|
+
# @param [Symbol] name - name of deprecated method
|
17
|
+
# @param [Symbol] replacement - name of the desired replacement
|
18
|
+
def deprecated(name, replacement)
|
19
|
+
# Replace old method
|
20
|
+
old_name = :"#{name}_without_deprecation"
|
21
|
+
alias_method old_name, name
|
22
|
+
# And replace it with a wrapped version
|
23
|
+
define_method(name) do |*args, &block|
|
24
|
+
warn "IceCube: #{self.class}##{name} is deprecated, please use ##{replacement} at: #{ caller[0] }"
|
25
|
+
send old_name, *args, &block
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
def self.schedule_options(schedule, options)
|
30
|
+
if options[:start_date_override]
|
31
|
+
warn "IceCube: :start_date_override option is deprecated, please use a block {|s| s.start_time = override }. at: #{ caller[0] }"
|
32
|
+
schedule.start_time = options[:start_date_override]
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
require 'delegate'
|
2
|
+
|
3
|
+
module IceCube
|
4
|
+
|
5
|
+
# Find keys by symbol or string without symbolizing user input
|
6
|
+
# Due to the serialization format of ice_cube, this limited implementation
|
7
|
+
# is entirely sufficient
|
8
|
+
|
9
|
+
class FlexibleHash < SimpleDelegator
|
10
|
+
|
11
|
+
def [](key)
|
12
|
+
key = _match_key(key)
|
13
|
+
super
|
14
|
+
end
|
15
|
+
|
16
|
+
def fetch(key)
|
17
|
+
key = _match_key(key)
|
18
|
+
super
|
19
|
+
end
|
20
|
+
|
21
|
+
def delete(key)
|
22
|
+
key = _match_key(key)
|
23
|
+
super
|
24
|
+
end
|
25
|
+
|
26
|
+
private
|
27
|
+
|
28
|
+
def _match_key(key)
|
29
|
+
return key if __getobj__.has_key? key
|
30
|
+
if Symbol == key.class
|
31
|
+
__getobj__.keys.detect { |k| return k if k == key.to_s }
|
32
|
+
elsif String == key.class
|
33
|
+
__getobj__.keys.detect { |k| return k if k.to_s == key }
|
34
|
+
end
|
35
|
+
key
|
36
|
+
end
|
37
|
+
|
38
|
+
end
|
39
|
+
|
40
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
module IceCube
|
2
|
+
module I18n
|
3
|
+
def self.t(*args)
|
4
|
+
backend.t(*args)
|
5
|
+
end
|
6
|
+
|
7
|
+
def self.l(*args)
|
8
|
+
backend.l(*args)
|
9
|
+
end
|
10
|
+
|
11
|
+
def self.backend
|
12
|
+
@backend
|
13
|
+
end
|
14
|
+
|
15
|
+
def self.detect_backend!
|
16
|
+
require 'i18n'
|
17
|
+
::I18n.load_path += Dir[File.expand_path('../../../config/locales/*{rb,yml}', __FILE__)]
|
18
|
+
@backend = ::I18n
|
19
|
+
rescue LoadError
|
20
|
+
require 'ice_cube/null_i18n'
|
21
|
+
@backend = NullI18n
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
require 'yaml'
|
2
|
+
|
3
|
+
module IceCube
|
4
|
+
module NullI18n
|
5
|
+
def self.t(key, options = {})
|
6
|
+
base = key.to_s.split('.').reduce(config) { |hash, current_key| hash[current_key] }
|
7
|
+
|
8
|
+
base = base[options[:count] == 1 ? "one" : "other"] if options[:count]
|
9
|
+
|
10
|
+
if base.is_a?(Hash)
|
11
|
+
return base.each_with_object({}) do |(key, value), hash|
|
12
|
+
hash[key.is_a?(String) ? key.to_sym : key] = value
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
options.reduce(base) { |result, (find, replace)| result.gsub("%{#{find}}", "#{replace}") }
|
17
|
+
end
|
18
|
+
|
19
|
+
def self.l(date_or_time, options = {})
|
20
|
+
return date_or_time.strftime(options[:format]) if options[:format]
|
21
|
+
date_or_time.strftime(t('ice_cube.date.formats.default'))
|
22
|
+
end
|
23
|
+
|
24
|
+
def self.config
|
25
|
+
@config ||= YAML.load(File.read(File.join(File.dirname(__FILE__), '..', '..', 'config', 'locales', 'en.yml')))['en']
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,101 @@
|
|
1
|
+
require 'forwardable'
|
2
|
+
require 'delegate'
|
3
|
+
|
4
|
+
module IceCube
|
5
|
+
|
6
|
+
# Wraps start_time and end_time in a single concept concerning the duration.
|
7
|
+
# This delegates to the enclosed start_time so it behaves like a normal Time
|
8
|
+
# in almost all situations, however:
|
9
|
+
#
|
10
|
+
# Without ActiveSupport, it's necessary to cast the occurrence using
|
11
|
+
# +#to_time+ before doing arithmetic, else Time will try to subtract it
|
12
|
+
# using +#to_i+ and return a new time instead.
|
13
|
+
#
|
14
|
+
# Time.now - Occurrence.new(start_time) # => 1970-01-01 01:00:00
|
15
|
+
# Time.now - Occurrence.new(start_time).to_time # => 3600
|
16
|
+
#
|
17
|
+
# When ActiveSupport::Time core extensions are loaded, it's possible to
|
18
|
+
# subtract an Occurrence object directly from a Time to get the difference:
|
19
|
+
#
|
20
|
+
# Time.now - Occurrence.new(start_time) # => 3600
|
21
|
+
#
|
22
|
+
class Occurrence < SimpleDelegator
|
23
|
+
|
24
|
+
# Report class name as 'Time' to thwart type checking.
|
25
|
+
def self.name
|
26
|
+
'Time'
|
27
|
+
end
|
28
|
+
|
29
|
+
# Optimize for common methods to avoid method_missing
|
30
|
+
extend Forwardable
|
31
|
+
def_delegators :start_time, :to_i, :<=>, :==
|
32
|
+
def_delegators :to_range, :cover?, :include?, :each, :first, :last
|
33
|
+
|
34
|
+
attr_reader :start_time, :end_time
|
35
|
+
|
36
|
+
def initialize(start_time, end_time=nil)
|
37
|
+
@start_time = start_time
|
38
|
+
@end_time = end_time || start_time
|
39
|
+
__setobj__ @start_time
|
40
|
+
end
|
41
|
+
|
42
|
+
def is_a?(klass)
|
43
|
+
klass == ::Time || super
|
44
|
+
end
|
45
|
+
alias_method :kind_of?, :is_a?
|
46
|
+
|
47
|
+
def intersects? other
|
48
|
+
if other.is_a?(Occurrence) || other.is_a?(Range)
|
49
|
+
lower_bound_1 = first + 1
|
50
|
+
upper_bound_1 = last # exclude end
|
51
|
+
lower_bound_2 = other.first + 1
|
52
|
+
upper_bound_2 = other.last + 1
|
53
|
+
if (lower_bound_2 <=> upper_bound_2) > 0
|
54
|
+
false
|
55
|
+
elsif (lower_bound_1 <=> upper_bound_1) > 0
|
56
|
+
false
|
57
|
+
else
|
58
|
+
(upper_bound_1 <=> lower_bound_2) >= 0 and
|
59
|
+
(upper_bound_2 <=> lower_bound_1) >= 0
|
60
|
+
end
|
61
|
+
else
|
62
|
+
cover? other
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
def comparable_time
|
67
|
+
start_time
|
68
|
+
end
|
69
|
+
|
70
|
+
def duration
|
71
|
+
end_time - start_time
|
72
|
+
end
|
73
|
+
|
74
|
+
def to_range
|
75
|
+
start_time..end_time
|
76
|
+
end
|
77
|
+
|
78
|
+
def to_time
|
79
|
+
start_time
|
80
|
+
end
|
81
|
+
|
82
|
+
# Shows both the start and end time if there is a duration.
|
83
|
+
# Optional format argument (e.g. :long, :short) supports Rails
|
84
|
+
# time formats and is only used when ActiveSupport is available.
|
85
|
+
#
|
86
|
+
def to_s(format=nil)
|
87
|
+
if format && to_time.public_method(:to_s).arity != 0
|
88
|
+
t0, t1 = start_time.to_s(format), end_time.to_s(format)
|
89
|
+
else
|
90
|
+
t0, t1 = start_time.to_s, end_time.to_s
|
91
|
+
end
|
92
|
+
duration > 0 ? "#{t0} - #{t1}" : t0
|
93
|
+
end
|
94
|
+
|
95
|
+
def overnight?
|
96
|
+
offset = start_time + 3600 * 24
|
97
|
+
midnight = Time.new(offset.year, offset.month, offset.day)
|
98
|
+
midnight < end_time
|
99
|
+
end
|
100
|
+
end
|
101
|
+
end
|