Class: Date

Inherits:
Object
  • Object
show all
Extended by:
Forwardable
Defined in:
lib/edtf/date.rb

Constant Summary collapse

PRECISION =
[:year, :month, :day].freeze
PRECISIONS =
Hash[*PRECISION.map { |p| [p, "#{p}s".to_sym] }.flatten].freeze
FORMATS =
%w{ %04d %02d %02d }.freeze
SYMBOLS =
{
  :uncertain   => '?',
  :approximate => '~',
  :calendar    => '^',
  :unspecified => 'u'
}.freeze
EXTENDED_ATTRIBUTES =
%w{
  calendar precision uncertain approximate unspecified
}.map(&:to_sym).freeze

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Instance Attribute Details

#approximateObject



97
98
99
# File 'lib/edtf/date.rb', line 97

def approximate
  @approximate ||= EDTF::Uncertainty.new(nil, nil, nil, 8)
end

#calendarObject

Returns the value of attribute calendar.



34
35
36
# File 'lib/edtf/date.rb', line 34

def calendar
  @calendar
end

#uncertainObject



93
94
95
# File 'lib/edtf/date.rb', line 93

def uncertain
  @uncertain ||= EDTF::Uncertainty.new
end

#unspecifiedObject



101
102
103
# File 'lib/edtf/date.rb', line 101

def unspecified
  @unspecified ||= EDTF::Unspecified.new
end

Class Method Details

.edtf(input, options = {}) ⇒ Object



23
24
25
26
27
# File 'lib/edtf/date.rb', line 23

def edtf(input, options = {})
  edtf!(input, options)
rescue
  nil
end

.edtf!(input, options = {}) ⇒ Object



29
30
31
# File 'lib/edtf/date.rb', line 29

def edtf!(input, options = {})
  ::EDTF::Parser.new(options).parse!(input)
end

Instance Method Details

#<=>(other) ⇒ Object



253
254
255
256
257
258
259
260
261
262
# File 'lib/edtf/date.rb', line 253

def <=>(other)
  case other
  when ::Date
    values <=> other.values
  when EDTF::Interval, EDTF::Season, EDTF::Epoch
    other.cover?(self) ? other.min <=> self : 0
  else
    nil
  end
end

#advance(options) ⇒ Object

Provides precise Date calculations for years, months, and days. The options parameter takes a hash with any of these keys: :years, :months, :weeks, :days.



63
64
65
# File 'lib/edtf/date.rb', line 63

def advance(options)
  original_advance(options).copy_extended_attributes(self)
end

#approximate!(arguments = precision_filter) ⇒ Object Also known as: approximately!



123
124
125
126
# File 'lib/edtf/date.rb', line 123

def approximate!(arguments = precision_filter)
  approximate.uncertain!(arguments)
  self
end

#approximate?(arguments = precision_filter) ⇒ Boolean Also known as: approximately?

Returns:

  • (Boolean)


117
118
119
# File 'lib/edtf/date.rb', line 117

def approximate?(arguments = precision_filter)
  approximate.uncertain?(arguments)
end

#calendar?Boolean

Returns true if the Date has an EDTF calendar string attached.

Returns:

  • (Boolean)


163
# File 'lib/edtf/date.rb', line 163

def calendar?; !!@calendar; end

#certain!(arguments = precision_filter) ⇒ Object



107
108
109
110
# File 'lib/edtf/date.rb', line 107

def certain!(arguments = precision_filter)
  uncertain.certain!(arguments)
  self
end

#change(options) ⇒ Object

Returns a new Date where one or more of the elements have been changed according to the options parameter.



71
72
73
74
75
76
77
# File 'lib/edtf/date.rb', line 71

def change(options)
  d = original_change(options)
  EXTENDED_ATTRIBUTES.each do |attribute|
    d.send("#{attribute}=", options[attribute] || send(attribute))
  end
  d
end

#edtfObject Also known as: to_edtf

Returns the Date’s EDTF string.



171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
# File 'lib/edtf/date.rb', line 171

def edtf
  return "y#{year}" if long_year?

  s = FORMATS.take(values.length).zip(values).map { |f,v| f % v }
  s = unspecified.mask(s)

  unless (h = ua_hash).zero?
    #
    # To efficiently calculate the uncertain/approximate state we use
    # the bitmask. The primary flags are:
    #
    # Uncertain:    1 - year,  2 - month,  4 - day
    # Approximate:  8 - year, 16 - month, 32 - day
    #
    # Invariant: assumes that uncertain/approximate are not set for values
    # not covered by precision!
    #
    y, m, d = s

    # ?/~ if true-false or true-true and other false-true
    y << SYMBOLS[:uncertain]   if  3&h==1 || 27&h==19
    y << SYMBOLS[:approximate] if 24&h==8 || 27&h==26


    # combine if false-true-true and other m == d 
    if 7&h==6 && (48&h==48 || 48&h==0)  || 56&h==48 && (6&h==6 || 6&h==0)
      m[0,0] = '('
      d << ')'
    else
      case
      # false-true
      when 3&h==2 || 24&h==16
        m[0,0] = '('
        m << ')'

      # *-false-true
      when 6&h==4 || 48&h==32
        d[0,0] = '('
        d << ')'
      end

      # ?/~ if *-true-false or *-true-true and other m != d
      m << SYMBOLS[:uncertain]   if h!=31 && (6&h==2  ||  6&h==6  && (48&h==16 || 48&h==32))
      m << SYMBOLS[:approximate] if h!=59 && (48&h==16 || 48&h==48 && (6&h==2 || 6&h==4))
    end

    # ?/~ if *-*-true
    d << SYMBOLS[:uncertain]   if  4&h==4
    d << SYMBOLS[:approximate] if 32&h==32
  end

  s = s.join('-')
  s << SYMBOLS[:calendar] << calendar if calendar?
  s
end

#initialize_copy(other) ⇒ Object



52
53
54
55
# File 'lib/edtf/date.rb', line 52

def initialize_copy(other)
  original_initialize_copy(other)
  copy_extended_attributes(other)
end

#long_year?Boolean

Returns true if this Date/Time has year precision and the year exceeds four digits.

Returns:

  • (Boolean)


279
280
281
# File 'lib/edtf/date.rb', line 279

def long_year?
  year_precision? && year.abs > 9999
end

#negateObject Also known as: -@

Returns the same date but with negated year.



272
273
274
# File 'lib/edtf/date.rb', line 272

def negate
  change(:year => year * -1)
end

#next(n = 1) ⇒ Object

Returns an array of the next n days, months, or years depending on the current Date/Time’s precision.



233
234
235
# File 'lib/edtf/date.rb', line 233

def next(n = 1)
  1.upto(n).map { |by| advance(PRECISIONS[precision] => by) }
end

#original_advanceObject

Alias advance method from Active Support.



59
# File 'lib/edtf/date.rb', line 59

alias original_advance advance

#original_changeObject

Alias change method from Active Support.



68
# File 'lib/edtf/date.rb', line 68

alias original_change change

#original_initialize_copyObject



50
# File 'lib/edtf/date.rb', line 50

alias original_initialize_copy initialize_copy

#precise!(arguments = precision_filter) ⇒ Object Also known as: precisely!



136
137
138
139
# File 'lib/edtf/date.rb', line 136

def precise!(arguments = precision_filter)
  approximate.certain!(arguments)
  self
end

#precise?(arguments = precision_filter) ⇒ Boolean Also known as: precisely?

Returns:

  • (Boolean)


130
131
132
# File 'lib/edtf/date.rb', line 130

def precise?(arguments = precision_filter)
  !approximate?(arguments)
end

#precisionObject

Returns this Date’s precision.



81
82
83
# File 'lib/edtf/date.rb', line 81

def precision
  @precision ||= :day
end

#precision=(precision) ⇒ Object

Sets this Date/Time’s precision to the passed-in value.

Raises:

  • (ArgumentError)


86
87
88
89
90
91
# File 'lib/edtf/date.rb', line 86

def precision=(precision)
  precision = precision.to_sym
  raise ArgumentError, "invalid precision #{precision.inspect}" unless PRECISION.include?(precision)
  @precision = precision
  update_precision_filter[-1]
end

#prev(n = 1) ⇒ Object

Returns the Date of the previous day, month, or year depending on the current Date/Time’s precision.



245
246
247
248
249
250
251
# File 'lib/edtf/date.rb', line 245

def prev(n = 1)
  if n > 1
    1.upto(n).map { |by| advance(PRECISIONS[precision] => -by) }
  else
    advance(PRECISIONS[precision] => -1)
  end
end

#seasonObject

Converts the Date into a season.



166
167
168
# File 'lib/edtf/date.rb', line 166

def season
  Season.new(self)
end

#season?Boolean

Returns false for Dates.

Returns:

  • (Boolean)


160
# File 'lib/edtf/date.rb', line 160

def season?; false; end

#specified!(arguments = precision_filter) ⇒ Object Also known as: specific!



152
153
154
155
# File 'lib/edtf/date.rb', line 152

def specified!(arguments = precision_filter)
  unspecified.specified!(arguments)
  self
end

#succObject



239
240
241
# File 'lib/edtf/date.rb', line 239

def succ
  advance(PRECISIONS[precision] => 1)
end

#uncertain!(arguments = precision_filter) ⇒ Object



112
113
114
115
# File 'lib/edtf/date.rb', line 112

def uncertain!(arguments = precision_filter)
  uncertain.uncertain!(arguments)
  self
end

#unspecified!(arguments = precision_filter) ⇒ Object Also known as: unspecific!



145
146
147
148
# File 'lib/edtf/date.rb', line 145

def unspecified!(arguments = precision_filter)
  unspecified.unspecified!(arguments)
  self
end

#valuesObject

Returns an array of the current year, month, and day values filtered by the Date/Time’s precision.



267
268
269
# File 'lib/edtf/date.rb', line 267

def values
  precision_filter.map { |p| send(p) }
end