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

seconds[R]

instance methods

zone[R]

Public Class Methods

get_tzone(o) click to toggle source
# File lib/et-orbi/time.rb, line 30
def get_tzone(o)

  EtOrbi.get_tzone(o)
end
local(*a) click to toggle source
# File lib/et-orbi/time.rb, line 55
def local(*a)

  EtOrbi.send(:make_from_array, a, local_tzone)
end
local_tzone() click to toggle source
# File lib/et-orbi/time.rb, line 35
def local_tzone

  EtOrbi.determine_local_tzone
end
make(o) click to toggle source
# File lib/et-orbi/time.rb, line 45
def make(o)

  EtOrbi.make_time(o)
end
new(s, zone) click to toggle source
# 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
now(zone=nil) click to toggle source
# File lib/et-orbi/time.rb, line 20
def now(zone=nil)

  EtOrbi.now(zone)
end
parse(str, opts={}) click to toggle source
# File lib/et-orbi/time.rb, line 25
def parse(str, opts={})

  EtOrbi.parse(str, opts)
end
platform_info() click to toggle source
# File lib/et-orbi/time.rb, line 40
def platform_info

  EtOrbi.platform_info
end
utc(*a) click to toggle source
# 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

+(t) click to toggle source
# File lib/et-orbi/time.rb, line 236
def +(t); inc(t, 1); end
-(t) click to toggle source
# File lib/et-orbi/time.rb, line 237
def -(t); inc(t, -1); end
<(o) click to toggle source
# File lib/et-orbi/time.rb, line 229
def <(o); @seconds < _to_f(o); end
<=(o) click to toggle source
# File lib/et-orbi/time.rb, line 230
def <=(o); @seconds <= _to_f(o); end
<=>(o) click to toggle source
# File lib/et-orbi/time.rb, line 231
def <=>(o); @seconds <=> _to_f(o); end
==(o) click to toggle source
# 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
>(o) click to toggle source

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
>=(o) click to toggle source
# File lib/et-orbi/time.rb, line 228
def >=(o); @seconds >= _to_f(o); end
add(t) click to toggle source
# File lib/et-orbi/time.rb, line 233
def add(t); @time = nil; @seconds += t.to_f; self; end
ambiguous?() click to toggle source

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
getgm()
Alias for: utc
getutc()
Alias for: utc
in_time_zone(zone=nil)
Alias for: localtime
inc(t, dir=1) click to toggle source
# 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
is_dst?() click to toggle source
# File lib/et-orbi/time.rb, line 174
def is_dst?

  @zone.period_for_utc(utc).std_offset != 0
end
Also aliased as: isdst
isdst()
Alias for: is_dst?
iso8601(fraction_digits=0) click to toggle source
# 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
localtime(zone=nil) click to toggle source
# File lib/et-orbi/time.rb, line 319
def localtime(zone=nil)

  EoTime.new(self.to_f, zone)
end
Also aliased as: translate, in_time_zone
monthdays() click to toggle source
# 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
rday() click to toggle source
# 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
reach(points) click to toggle source
# 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
rweek() click to toggle source
# 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
seconds=(f) click to toggle source
# File lib/et-orbi/time.rb, line 95
def seconds=(f)

  @time = nil
  @seconds = f
end
strftime(format) click to toggle source
# 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
subtract(t) click to toggle source
# File lib/et-orbi/time.rb, line 234
def subtract(t); @time = nil; @seconds -= t.to_f; self; end
to_debug_s() click to toggle source
# 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
to_f() click to toggle source
# File lib/et-orbi/time.rb, line 145
def to_f

  @seconds
end
to_i() click to toggle source
# File lib/et-orbi/time.rb, line 150
def to_i

  @seconds.to_i
end
to_local_time() click to toggle source

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
Also aliased as: to_t
to_s() click to toggle source
# File lib/et-orbi/time.rb, line 267
def to_s

  strftime('%Y-%m-%d %H:%M:%S %z')
end
to_t()
Alias for: to_local_time
to_time_s() click to toggle source
# File lib/et-orbi/time.rb, line 297
def to_time_s

  strftime('%H:%M:%S.%6N')
end
to_utc_comparison_s() click to toggle source

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
to_utc_time()
Alias for: utc
to_zs() click to toggle source
# File lib/et-orbi/time.rb, line 272
def to_zs

  strftime('%Y-%m-%d %H:%M:%S %/Z')
end
translate(zone=nil)
Alias for: localtime
utc() click to toggle source

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
Also aliased as: getutc, getgm, to_utc_time
utc?() click to toggle source

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
utc_offset() click to toggle source
# File lib/et-orbi/time.rb, line 195
def utc_offset

  @zone.period_for_utc(utc).utc_total_offset
end
wday_in_month() click to toggle source
# 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
zone=(z) click to toggle source
# File lib/et-orbi/time.rb, line 101
def zone=(z)

  @time = nil
  @zone = self.class.get_tzone(zone || :current)
end

Protected Instance Methods

_to_f(o) click to toggle source
# 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
count_weeks(start, dir) click to toggle source
# 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
strfz(code) click to toggle source
# 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
to_time() click to toggle source

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