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

Returns a new instance of 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