blob: 3d25a64039873a099250b03b6cac28a9089662a8 [file] [log] [blame]
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
module Arrow
class Time
attr_reader :unit
attr_reader :value
def initialize(unit, value)
@unit = unit
@value = value
@unconstructed = false
end
def ==(other)
other.is_a?(self.class) and
positive? == other.positive? and
hour == other.hour and
minute == other.minute and
second == other.second and
nano_second == other.nano_second
end
def cast(target_unit)
return self.class.new(@unit, @value) if @unit == target_unit
target_value = (hour * 60 * 60) + (minute * 60) + second
case target_unit
when TimeUnit::MILLI
target_value *= 1000
target_value += nano_second / 1000 / 1000
when TimeUnit::MICRO
target_value *= 1000 * 1000
target_value += nano_second / 1000
when TimeUnit::NANO
target_value *= 1000 * 1000 * 1000
target_value += nano_second
end
target_value = -target_value if negative?
self.class.new(target_unit, target_value)
end
def to_f
case @unit
when TimeUnit::SECOND
@value.to_f
when TimeUnit::MILLI
@value.to_f / 1000.0
when TimeUnit::MICRO
@value.to_f / 1000.0 / 1000.0
when TimeUnit::NANO
@value.to_f / 1000.0 / 1000.0 / 1000.0
end
end
def positive?
@value.positive?
end
def negative?
@value.negative?
end
def hour
unconstruct
@hour
end
def minute
unconstruct
@minute
end
alias_method :min, :minute
def second
unconstruct
@second
end
alias_method :sec, :second
def nano_second
unconstruct
@nano_second
end
alias_method :nsec, :nano_second
def to_s
unconstruct
if @nano_second.zero?
nano_second_string = ""
else
nano_second_string = (".%09d" % @nano_second).gsub(/0+\z/, "")
end
"%s%02d:%02d:%02d%s" % [
@value.negative? ? "-" : "",
@hour,
@minute,
@second,
nano_second_string,
]
end
private
def unconstruct
return if @unconstructed
abs_value = @value.abs
case unit
when TimeUnit::SECOND
unconstruct_second(abs_value)
@nano_second = 0
when TimeUnit::MILLI
unconstruct_second(abs_value / 1000)
@nano_second = (abs_value % 1000) * 1000 * 1000
when TimeUnit::MICRO
unconstruct_second(abs_value / 1000 / 1000)
@nano_second = (abs_value % (1000 * 1000)) * 1000
when TimeUnit::NANO
unconstruct_second(abs_value / 1000 / 1000 / 1000)
@nano_second = abs_value % (1000 * 1000 * 1000)
else
raise ArgumentError, "invalid unit: #{@unit.inspect}"
end
@unconstructed = true
end
def unconstruct_second(abs_value_in_second)
if abs_value_in_second < 60
hour = 0
minute = 0
second = abs_value_in_second
elsif abs_value_in_second < (60 * 60)
hour = 0
minute = abs_value_in_second / 60
second = abs_value_in_second % 60
else
in_minute = abs_value_in_second / 60
hour = in_minute / 60
minute = in_minute % 60
second = abs_value_in_second % 60
end
@hour = hour
@minute = minute
@second = second
end
end
end