Class: CiteProc::Date

Inherits:
Variable show all
Includes:
Attributes
Defined in:
lib/citeproc/date.rb

Overview

Represents a Variable wrapping a date value. A date value is a hybrid object in that it can represent either an atomic date or a date range, depending on whether or not the ‘date-parts’ attribute contains one or two lists of date parts.

Dates can be constructed from a wide range of input values, including Ruby date objects, integers, date ranges, ISO 8601 and CiteProc JSON strings or hashes, and - provided you have the respective gems installed - EDTF strings all strings supported by Chronic.

Date instances are typically manipulated by a cite processor. Therefore, the API is optimized for easy information extraction and formatting. Additionally, Dates can be serialized as CiteProc JSON data.

Examples:

Initialization

CiteProc::Date.new
#-> #<CiteProc::Date "[]">

CiteProc::Date.today
#-> #<CiteProc::Date "[2012, 6, 10]">

CiteProc::Date.new('Yesterday')
#-> #<CiteProc::Date "[[2012, 6, 9]]">

CiteProc::Date.new(1966)
#-> #<CiteProc::Date "[1966]">

CiteProc::Date.new(1999..2003)
#-> #<CiteProc::Date "[[1999], [2003]]">

CiteProc::Date.new(Date.new(1900)...Date.new(2000))
#-> #<CiteProc::Date "[[1900, 1, 1], [1999, 12, 31]]">

CiteProc::Date.new('2009-03?')
#-> #<CiteProc::Date "[[2009, 3]]">

CiteProc::Date.new('2001-02/2007')
#-> #<CiteProc::Date "[[2001, 2, 1], [2007, 12, 31]]">

Serialization

CiteProc::Date.new('2009-03?').to_citeproc
#-> {"date-parts"=>[[2009, 3]], "circa"=>true}

CiteProc::Date.new(1999..2003).to_json
#-> '{"date-parts":[[1999],[2003]]}'

Defined Under Namespace

Classes: DateParts

Class Attribute Summary collapse

Instance Attribute Summary collapse

Attributes inherited from Variable

#value

Class Method Summary collapse

Instance Method Summary collapse

Methods included from Attributes

#attribute?, #eql?, #hash, #read_attribute, #reverse_merge, #to_hash, #to_json, #write_attribute

Methods inherited from Variable

create, create!, #inspect, #romanize, #strip_markup, #strip_markup!, #to_f, #to_i, #to_json, #tokenize, #type

Constructor Details

#initialize(value = {}) {|_self| ... } ⇒ Date

Returns a new instance of Date.

Yields:

  • (_self)

Yield Parameters:



286
287
288
289
# File 'lib/citeproc/date.rb', line 286

def initialize(value = {})
  super
  yield self if block_given?
end

Class Attribute Details

.parsersArray (readonly)

A list of available date parsers. Each parser must respond to a #parse method that converts a date string into a Ruby date object. By default, the list will include Ruby’s date parser from the standard library, as well as the parsers of the Chronic and EDTF gems if they are available; to install the latter on your system make sure to ‘gem install chronic edtf`.



237
238
239
# File 'lib/citeproc/date.rb', line 237

def parsers
  @parsers
end

Instance Attribute Details

#dayFixnum



380
381
382
383
384
385
386
387
388
389
390
391
# File 'lib/citeproc/date.rb', line 380

[:year, :month, :day].each do |reader|
  writer = "#{reader}="

  define_method(reader) do
    d = parts[0] and d.send(reader)
  end

  define_method(writer) do |v|
    parts[0] ||= DateParts.new
    parts[0].send(writer, v.to_i)
  end
end

#monthFixnum



# File 'lib/citeproc/date.rb', line 375

#yearFixnum



# File 'lib/citeproc/date.rb', line 372

Class Method Details

.parse(date_string) ⇒ CiteProc::Date?

Parses the passed-in string with all available date parsers. Creates a new CiteProc Date from the first valid date returned by a parser; returns nil if no parser was able to parse the string successfully.

For an equivalent method that raises an error on invalid input

See Also:

  • #parse!


248
249
250
251
252
# File 'lib/citeproc/date.rb', line 248

def parse(date_string)
  parse!(date_string)
rescue ParseError
  nil
end

.parse!(date_string) ⇒ CiteProc::Date

Like #parse but raises a ParseError if the input failed to be parsed.

Raises:

  • (ParseError)

    when the string cannot be parsed



260
261
262
263
264
265
266
267
268
# File 'lib/citeproc/date.rb', line 260

def parse!(date_string)
  @parsers.each do |p|
    date = p.parse(date_string) rescue nil
    return new(date) unless date.nil?
  end

  # Subtle: if we get here it means all parsers failed to create a date
  raise ParseError, "failed to parse #{date_string.inspect}"
end

.todayCiteProc::Date Also known as: now



271
272
273
# File 'lib/citeproc/date.rb', line 271

def today
  new(::Date.today)
end

Instance Method Details

#-@Date



394
395
396
397
398
# File 'lib/citeproc/date.rb', line 394

def -@
  d = dup
  d.year = -1 * year
  d
end

#<=>(other) ⇒ Object



516
517
518
519
520
521
522
523
524
525
526
# File 'lib/citeproc/date.rb', line 516

def <=>(other)
  case other
  when CiteProc::Date
    return nil if season? || other.season?
    parts <=> other.parts
  when ::Date
    parts <=> [other]
  else
    nil
  end
end

#ad?Boolean?

A date is said to be AD when it is in the first millennium, i.e., between 1 and 1000 AD



486
487
488
# File 'lib/citeproc/date.rb', line 486

def ad?
  date = parts[0] and date.ad?
end

#bc?Boolean?

A date is said to be BC when the year is defined and less than zero.



478
479
480
# File 'lib/citeproc/date.rb', line 478

def bc?
  date = parts[0] and date.bc?
end

#certain!self

Marks the date as a certain date



461
462
463
464
# File 'lib/citeproc/date.rb', line 461

def certain!
  value[:circa] = false
  self
end

#certain?Boolean



466
467
468
# File 'lib/citeproc/date.rb', line 466

def certain?
  !uncertain?
end

#closed_range?Boolean Also known as: closed?



444
445
446
# File 'lib/citeproc/date.rb', line 444

def closed_range?
  range? && !open_range?
end

#date?true



368
369
370
# File 'lib/citeproc/date.rb', line 368

def date?
  true
end

#date_partsArray<DateParts> Also known as: parts



354
355
356
# File 'lib/citeproc/date.rb', line 354

def date_parts
  value[:'date-parts'] ||= []
end

#empty?Boolean



363
364
365
# File 'lib/citeproc/date.rb', line 363

def empty?
  parts.all?(&:empty?) && !literal? && !season?
end

#end_date::Date?



424
425
426
# File 'lib/citeproc/date.rb', line 424

def end_date
  d = parts[1] and d.to_date
end

#end_date=(date) ⇒ Object



409
410
411
# File 'lib/citeproc/date.rb', line 409

def end_date=(date)
  parts[1] = DateParts.new(date.nil? ? 0 : date.strftime('%Y-%m-%d').split(/-/))
end

#has_end_date?Boolean Also known as: range?, plural?



429
430
431
# File 'lib/citeproc/date.rb', line 429

def has_end_date?
  parts[1] && !parts[1].empty?
end

#initialize_copy(other) ⇒ Object



291
292
293
# File 'lib/citeproc/date.rb', line 291

def initialize_copy(other)
  @value = other.value.deep_copy
end

#marshal_dumpObject



295
296
297
# File 'lib/citeproc/date.rb', line 295

def marshal_dump
  to_citeproc
end

#marshal_load(value) ⇒ Object



299
300
301
# File 'lib/citeproc/date.rb', line 299

def marshal_load(value)
  replace(value)
end

#merge(other) ⇒ Object



303
304
305
306
# File 'lib/citeproc/date.rb', line 303

def merge(other)
  super
  convert_parts!
end

#numeric?Boolean



471
472
473
# File 'lib/citeproc/date.rb', line 471

def numeric?
  false
end

#open_range?Boolean Also known as: open?



437
438
439
# File 'lib/citeproc/date.rb', line 437

def open_range?
  range? && parts[1].open?
end

#replace(value) ⇒ Object

Replaces the date’s value. Typically called by the constructor, this method intelligently converts various input values.



310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
# File 'lib/citeproc/date.rb', line 310

def replace(value)
  case
  when value.is_a?(CiteProc::Date)
    initialize_copy(value)
  when value.is_a?(::Date) && Object.const_defined?(:EDTF)
    @value = { :'date-parts' => [DateParts.new(*value.values)] }
    uncertain! if value.uncertain?
  when value.respond_to?(:strftime)
    @value = { :'date-parts' => [DateParts.new(*value.strftime('%Y-%m-%d').split(/-/))] }
  when value.is_a?(Numeric)
    @value = { :'date-parts' => [DateParts.new(value)] }
  when value.is_a?(Hash)
    attributes = value.symbolize_keys

    if attributes.has_key?(:raw)
      @value = Date.parse(attributes.delete(:raw)).value
      @value.merge!(attributes)
    else
      @value = attributes.deep_copy
    end
    convert_parts!

  when value.is_a?(Array)
    @value = { :'date-parts' => value[0].is_a?(Array) ? value : [value] }
    convert_parts!
  when !value.is_a?(String) && value.respond_to?(:min) && value.respond_to?(:max)
    @value = { :'date-parts' => [
        DateParts.new(value.min),
        DateParts.new(value.max)
      ]}
  when value.is_a?(String) && /^\s*\{/ =~ value
    return replace(::JSON.parse(value, :symbolize_names => true))
  when value.respond_to?(:to_s)
    @value = Date.parse!(value.to_s).value
  else
    raise TypeError, "failed to create date from #{value.inspect}"
  end

  self
end

#start_date::Date?



401
402
403
# File 'lib/citeproc/date.rb', line 401

def start_date
  d = parts[0] and d.to_date
end

#start_date=(date) ⇒ Object



405
406
407
# File 'lib/citeproc/date.rb', line 405

def start_date=(date)
  parts[0] = DateParts.new(date.strftime('%Y-%m-%d').split(/-/))
end

#to_citeprocHash



491
492
493
494
495
496
497
498
499
500
501
502
# File 'lib/citeproc/date.rb', line 491

def to_citeproc
  cp = value.stringify_keys

  # Convert (or suppress empty) date-parts
  if parts.all?(&:empty?)
    cp.delete('date-parts')
  else
    cp['date-parts'] = cp['date-parts'].map(&:to_citeproc)
  end

  cp
end

#to_rubyDate, Range



415
416
417
418
419
420
421
# File 'lib/citeproc/date.rb', line 415

def to_ruby
  if closed_range?
    start_date..end_date
  else
    start_date
  end
end

#to_sString



505
506
507
508
509
510
511
512
513
514
# File 'lib/citeproc/date.rb', line 505

def to_s
  case
  when literal?
    literal
  when season?
    season
  else
    parts.map(&:to_citeproc).inspect
  end
end

#uncertain!self

Marks the date as uncertain



454
455
456
457
# File 'lib/citeproc/date.rb', line 454

def uncertain!
  value[:circa] = true
  self
end