class EtOrbi::EoTime
Our EoTime
class (which quacks like a ::Time).
An EoTime
instance should respond to most of the methods ::Time instances respond to. If a method is missing, feel free to open an issue to ask (politely) for it. If it makes sense, it'll get added, else a workaround will get suggested. The immediate workaround is to call to_t
on the EoTime
instance to get equivalent ::Time instance in the local, current, timezone.
Constants
- DAY_S
- WEEK_S
Attributes
instance methods
Public Class Methods
# File lib/et-orbi/time.rb, line 30 def get_tzone(o) EtOrbi.get_tzone(o) end
# File lib/et-orbi/time.rb, line 55 def local(*a) EtOrbi.send(:make_from_array, a, local_tzone) end
# File lib/et-orbi/time.rb, line 35 def local_tzone EtOrbi.determine_local_tzone end
# File lib/et-orbi/time.rb, line 45 def make(o) EtOrbi.make_time(o) end
# File lib/et-orbi/time.rb, line 67 def initialize(s, zone) z = zone z = nil if zone.is_a?(String) && zone.strip == '' # # happens with JRuby (and offset tzones like +04:00) # # $ jruby -r time -e "p Time.parse('2012-1-1 12:00 +04:00').zone" # # => "" # ruby -r time -e "p Time.parse('2012-1-1 12:00 +04:00').zone" # # => nil @seconds = s.to_f @zone = self.class.get_tzone(z || :local) fail ArgumentError.new( "Cannot determine timezone from #{zone.inspect}" + "\n#{EtOrbi.render_nozone_time(@seconds)}" + "\n#{EtOrbi.platform_info.sub(',debian:', ",\ndebian:")}" + "\nTry setting `ENV['TZ'] = 'Continent/City'` in your script " + "(see https://en.wikipedia.org/wiki/List_of_tz_database_time_zones)" + (defined?(TZInfo::Data) ? '' : "\nand adding gem 'tzinfo-data'") ) unless @zone @time = nil # cache for #to_time result end
# File lib/et-orbi/time.rb, line 20 def now(zone=nil) EtOrbi.now(zone) end
# File lib/et-orbi/time.rb, line 25 def parse(str, opts={}) EtOrbi.parse(str, opts) end
# File lib/et-orbi/time.rb, line 40 def platform_info EtOrbi.platform_info end
# File lib/et-orbi/time.rb, line 50 def utc(*a) EtOrbi.send(:make_from_array, a, EtOrbi.get_tzone('UTC')) end
Public Instance Methods
# File lib/et-orbi/time.rb, line 236 def +(t); inc(t, 1); end
# File lib/et-orbi/time.rb, line 237 def -(t); inc(t, -1); end
# File lib/et-orbi/time.rb, line 229 def <(o); @seconds < _to_f(o); end
# File lib/et-orbi/time.rb, line 230 def <=(o); @seconds <= _to_f(o); end
# File lib/et-orbi/time.rb, line 231 def <=>(o); @seconds <=> _to_f(o); end
# File lib/et-orbi/time.rb, line 206 def ==(o) if o.is_a?(EoTime) o.seconds == @seconds && (o.zone == @zone || o.zone.current_period == @zone.current_period) elsif o.is_a?(::Time) (to_f * 1000).to_i == (o.to_f * 1000).to_i else false end end
Nota Bene:
Unlike ==, the equal? method should never be overridden by subclasses as it is used to determine object identity (that is, a.equal?(b) if and only if a is the same object as b)
The eql? method returns true if obj and other refer to the same hash key. This is used by Hash to test members for equality.
# File lib/et-orbi/time.rb, line 227 def >(o); @seconds > _to_f(o); end
# File lib/et-orbi/time.rb, line 228 def >=(o); @seconds >= _to_f(o); end
# File lib/et-orbi/time.rb, line 233 def add(t); @time = nil; @seconds += t.to_f; self; end
Returns true if this EoTime
instance corresponds to 2 different UTC times. It happens when transitioning from DST to winter time.
www.timeanddate.com/time/change/usa/new-york?year=2018
# File lib/et-orbi/time.rb, line 113 def ambiguous? @zone.local_to_utc(@zone.utc_to_local(utc)) false rescue TZInfo::AmbiguousTime true end
# File lib/et-orbi/time.rb, line 302 def inc(t, dir=1) case t when Numeric nt = self.dup nt.seconds += dir * t.to_f nt when ::Time, ::EtOrbi::EoTime fail ArgumentError.new( "Cannot add #{t.class} to EoTime") if dir > 0 @seconds + dir * t.to_f else fail ArgumentError.new( "Cannot call add or subtract #{t.class} to EoTime instance") end end
# File lib/et-orbi/time.rb, line 174 def is_dst? @zone.period_for_utc(utc).std_offset != 0 end
# File lib/et-orbi/time.rb, line 277 def iso8601(fraction_digits=0) s = (fraction_digits || 0) > 0 ? ".%#{fraction_digits}N" : '' strftime("%Y-%m-%dT%H:%M:%S#{s}%:z") end
# File lib/et-orbi/time.rb, line 319 def localtime(zone=nil) EoTime.new(self.to_f, zone) end
# File lib/et-orbi/time.rb, line 242 def monthdays date = to_time pos = 1 d = self.dup loop do d.add(-WEEK_S) break if d.month != date.month pos = pos + 1 end neg = -1 d = self.dup loop do d.add(WEEK_S) break if d.month != date.month neg = neg - 1 end [ "#{date.wday}##{pos}", "#{date.wday}##{neg}" ] end
# File lib/et-orbi/time.rb, line 339 def rday ((self - EtOrbi.make_time('2019-01-01 00:00:00', @zone)) / DAY_S) .floor + 1 end
# File lib/et-orbi/time.rb, line 345 def reach(points) t = EoTime.new(self.to_f, @zone) step = 1 s = points[:second] || points[:sec] || points[:s] m = points[:minute] || points[:min] || points[:m] h = points[:hour] || points[:hou] || points[:h] fail ArgumentError.new("missing :second, :minute, and :hour") \ unless s || m || h if !s && !m step = 60 * 60 t -= t.sec t -= t.min * 60 elsif !s step = 60 t -= t.sec end loop do t += step next if s && t.sec != s next if m && t.min != m next if h && t.hour != h break end t end
# File lib/et-orbi/time.rb, line 333 def rweek ((self - EtOrbi.make_time('2019-01-01 00:00:00', @zone)) / WEEK_S) .floor + 1 end
# File lib/et-orbi/time.rb, line 95 def seconds=(f) @time = nil @seconds = f end
# File lib/et-orbi/time.rb, line 155 def strftime(format) format = format.gsub(/%(\/?Z|:{0,2}z)/) { |f| strfz(f) } to_time.strftime(format) end
# File lib/et-orbi/time.rb, line 234 def subtract(t); @time = nil; @seconds -= t.to_f; self; end
# File lib/et-orbi/time.rb, line 180 def to_debug_s uo = self.utc_offset uos = uo < 0 ? '-' : '+' uo = uo.abs uoh, uom = [ uo / 3600, uo % 3600 ] [ 'ot', self.strftime('%Y-%m-%d %H:%M:%S'), "%s%02d:%02d" % [ uos, uoh, uom ], "dst:#{self.isdst}" ].join(' ') end
# File lib/et-orbi/time.rb, line 145 def to_f @seconds end
# File lib/et-orbi/time.rb, line 150 def to_i @seconds.to_i end
Returns this ::EtOrbi::EoTime
as a ::Time instance in the current timezone.
Has a to_t
alias.
# File lib/et-orbi/time.rb, line 167 def to_local_time Time.at(@seconds) end
# File lib/et-orbi/time.rb, line 267 def to_s strftime('%Y-%m-%d %H:%M:%S %z') end
# File lib/et-orbi/time.rb, line 297 def to_time_s strftime('%H:%M:%S.%6N') end
Debug current time by showing local time / delta / utc time for example: “0120-7(0820)”
# File lib/et-orbi/time.rb, line 286 def to_utc_comparison_s per = @zone.period_for_utc(utc) off = per.utc_total_offset off = off / 3600 off = off >= 0 ? "+#{off}" : off.to_s strftime('%H%M') + off + utc.strftime('(%H%M)') end
# File lib/et-orbi/time.rb, line 272 def to_zs strftime('%Y-%m-%d %H:%M:%S %/Z') end
Returns this ::EtOrbi::EoTime
as a ::Time instance in the current UTC timezone.
# File lib/et-orbi/time.rb, line 127 def utc Time.utc(1970) + @seconds end
Returns true if this ::EtOrbi::EoTime
instance timezone is UTC. Returns false else.
# File lib/et-orbi/time.rb, line 135 def utc? %w[ gmt utc zulu etc/gmt etc/utc ].include?( @zone.canonical_identifier.downcase) end
# File lib/et-orbi/time.rb, line 195 def utc_offset @zone.period_for_utc(utc).utc_total_offset end
# File lib/et-orbi/time.rb, line 327 def wday_in_month [ count_weeks(EtOrbi.make_time(strftime('%F 12:00:00 %/Z')), -1), - count_weeks(EtOrbi.make_time(strftime('%F 12:00:00 %/Z')) , 1) ] end
# File lib/et-orbi/time.rb, line 101 def zone=(z) @time = nil @zone = self.class.get_tzone(zone || :current) end
Protected Instance Methods
# File lib/et-orbi/time.rb, line 428 def _to_f(o) fail ArgumentError( "Comparison of EoTime with #{o.inspect} failed" ) unless o.respond_to?(:to_f) o.to_f end
# File lib/et-orbi/time.rb, line 389 def count_weeks(start, dir) c = 0 t = start until t.month != self.month c += 1 t += dir * (7 * 24 * 3600) end c end
# File lib/et-orbi/time.rb, line 402 def strfz(code) return @zone.name if code == '%/Z' per = @zone.period_for_utc(utc) return per.abbreviation.to_s if code == '%Z' off = per.utc_total_offset # sn = off < 0 ? '-' : '+'; off = off.abs hr = off / 3600 mn = (off % 3600) / 60 sc = 0 if @zone.name == 'UTC' 'Z' # align on Ruby ::Time#iso8601 elsif code == '%z' '%s%02d%02d' % [ sn, hr, mn ] elsif code == '%:z' '%s%02d:%02d' % [ sn, hr, mn ] else '%s%02d:%02d:%02d' % [ sn, hr, mn, sc ] end end
Returns a Ruby Time instance.
Warning: the timezone of that Time instance will be UTC when used with TZInfo < 2.0.0.
# File lib/et-orbi/time.rb, line 384 def to_time @time ||= @zone.utc_to_local(utc) end