Class: Chronos::Interval::Gregorian

Inherits:
Chronos::Interval show all
Defined in:
lib/chronos/interval/gregorian.rb

Overview

A Gregorian Interval extens Interval by months. Unlike in Gregorian Durations, months exactly defined in seconds (and therefore minutes, hours, days, weeks). Internally a gregorian interval is stored as total picoseconds after days + days between the two dates and additionally the months + days after months + picoseconds after days. For

Constant Summary collapse

ValidFixed =
[:begin, :end].freeze

Constants inherited from Chronos::Interval

InspectFixedBegin, InspectFixedEnd

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Methods inherited from Chronos::Interval

#+, #-, #days, #fixed_begin, #fixed_end, #format, #inspect, #picoseconds, #to_duration, #to_hash, #values_at

Constructor Details

#initialize(limit_a, limit_b, fixed = nil) ⇒ Gregorian



36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
# File 'lib/chronos/interval/gregorian.rb', line 36

def initialize(limit_a, limit_b, fixed=nil)
  super(limit_a, limit_b, fixed)
  picoseconds       = @end.ps_number - @begin.ps_number if @begin.time?
  days, picoseconds = *picoseconds.divmod(PS_IN_DAY) if @begin.time?
  months            = 0
  
  if @begin.date? then
    a                 = Datetime.new(@begin.day_number, @begin.ps_number, ::Chronos::UTC)
    b                 = Datetime.new(@end.day_number,   @end.ps_number,   ::Chronos::UTC)
    days_after_months = days+b.day_of_month-a.day_of_month
    months            = b.year*12+b.month-a.year*12-a.month

    # move 1 month forward
    if days_after_months < 0 then
      days_after_months += a.days_in_month
      months            -= 1
    end

    days    += b.day_number - a.day_number
    bsd      = a.day_of_month > b.day_of_month ||
               (start_date.time? && a.day_of_month == b.day_of_month && seconds < 0)
    month1   = a.year*12+a.month+(bsd ? 1 : 0)
    month2   = b.year*12+b.month
    months   = month2 - month1
    a2y,a2m  = *(month1-1).divmod(12)
    a, b     = Datetime.civil(a2y, a2m+1, 1), Datetime.civil(b.year, b.month, 1)
  
    seconds_in_months = (b.day_number-a.day_number)*86400
    p [seconds, seconds_in_months]
    seconds -= seconds_in_months
  
    b2y,b2m  = *(month1+(months.div(12)*12)).divmod(12)
    b        = Datetime.civil(b2y, b2m+1, 1)
    seconds_in_years = (b.day_number-a.day_number)*86400
  end
  
  @gregorian_duration = Duration::Gregorian.new(months, days+overflow, picoseconds, @language)
end

Instance Attribute Details

#beginObject (readonly)

The smaller of the two datetimes



21
22
23
# File 'lib/chronos/interval/gregorian.rb', line 21

def begin
  @begin
end

#endObject (readonly)

The bigger of the two datetimes



24
25
26
# File 'lib/chronos/interval/gregorian.rb', line 24

def end
  @end
end

#fixedObject (readonly)

Which end is fixed, plays a role when adding, subtracting, multiplying, dividing, …



27
28
29
# File 'lib/chronos/interval/gregorian.rb', line 27

def fixed
  @fixed
end

Class Method Details

.between(limit_a, limit_b) ⇒ Object

unlike new, between always creates a positive interval it will switch limit_a and limit_b if limit_a > limit_b it always fixates :begin



32
33
34
# File 'lib/chronos/interval/gregorian.rb', line 32

def self.between(limit_a, limit_b)
  limit_a > limit_b ? new(limit_b, limit_a, false, :begin) : new(limit_a, limit_b, false, :begin)
end

Instance Method Details

#to_gregorian_durationObject



75
76
77
# File 'lib/chronos/interval/gregorian.rb', line 75

def to_gregorian_duration
  @gregorian_duration
end