Class: RDF::Literal::Duration

Inherits:
RDF::Literal show all
Defined in:
lib/rdf/xsd/duration.rb

Overview

A duration literal.

Constant Summary collapse

DATATYPE =

Since:

  • 0.2.1

XSD.duration
GRAMMAR =

Since:

  • 0.2.1

%r(\A(-?)P(\d+Y)?(\d+M)?(\d+D)?T?(\d+H)?(\d+M)?([\d\.]+S)?\Z).freeze

Instance Method Summary collapse

Constructor Details

#initialize(value, options = {}) ⇒ Duration

  • Given a Numeric, assumes that it is milliseconds
  • Given a String, parse as xsd:duration
  • Hash form is used for internal representation

Options Hash (options):

  • :lexical (String) — default: nil

Since:

  • 0.2.1


20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
# File 'lib/rdf/xsd/duration.rb', line 20

def initialize(value, options = {})
  super
  @object   = case value
  when Hash
    value = value.dup
    value[:yr] ||= value[:years]
    value[:mo] ||= value[:months]
    value[:da] ||= value[:days]
    value[:hr] ||= value[:hours]
    value[:mi] ||= value[:minutes]
    value[:se] ||= value[:seconds]
    
    value
  when Duration, Numeric
    {:se => value.to_f}
  else
    parse(value.to_s) rescue { }
  end
  @object[:si] ||= 1
end

Instance Method Details

#==(other) ⇒ Object

Equal compares as DateTime objects

Since:

  • 0.2.1


135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
# File 'lib/rdf/xsd/duration.rb', line 135

def ==(other)
  # If lexically invalid, use regular literal testing
  return super unless self.valid?

  case other
  when Duration
    return super unless other.valid?
    self.to_f == other.to_f
  when String
    self.to_s(:xml) == other
  when Numeric
    self.to_f == other
  when Literal::DateTime, Literal::Time, Literal::Date
    false
  else
    super
  end
end

#canonicalize!RDF::Literal

Converts this literal into its canonical lexical representation.

Also normalizes elements


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
74
75
76
77
# File 'lib/rdf/xsd/duration.rb', line 48

def canonicalize!
  @string = @humanize = nil
  if @object[:se].to_i > 60
    m_r = (@object[:se].to_i / 60) - 1
    @object[:se] -=  m_r * 60
    @object[:mi] = @object[:mi].to_i + m_r
  end
  if @object[:mi].to_i > 60
    h_r = (@object[:mi].to_i / 60) - 1
    @object[:mi] -=  h_r * 60
    @object[:hr] = @object[:hr].to_i +  h_r
  end
  if @object[:hr].to_i > 24
    d_r = (@object[:hr].to_i / 24) - 1
    @object[:hr] -=  d_r * 24
    @object[:da] = @object[:da].to_i + d_r
  end
  if @object[:da].to_i > 30
    m_r = (@object[:da].to_i / 30) - 1
    @object[:da] -=  m_r * 30
    @object[:mo] = @object[:mo].to_i + m_r
  end
  if @object[:mo].to_i > 12
    y_r = (@object[:mo].to_i / 12) - 1
    @object[:mo] -=  y_r * 12
    @object[:yr] = @object[:yr].to_i + y_r
  end
  @object.to_s  # site-effect
  self
end

#humanize(lang = :en) ⇒ Object

Returns a human-readable value for the interval

Since:

  • 0.2.1


114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
# File 'lib/rdf/xsd/duration.rb', line 114

def humanize(lang = :en)
  @humanize ||= {}
  @humanize[lang] ||= begin
    # Just english, for now
    ar = []
    ar << plural(@object[:yr], "year")
    ar << plural(@object[:mo], "month")
    ar << plural(@object[:da], "day")
    ar << plural(@object[:hr], "hour")
    ar << plural(@object[:mi], "minute")
    ar << plural(sec_str, "second") if @object[:se]
    ar = ar.compact
    last = ar.pop
    first = ar.join(" ")
    res = first.empty? ? last : "#{first} and #{last}"
    @object[:si] < 0 ? "#{res} ago" : res
  end
end

#plural(v, str) ⇒ Object

Since:

  • 0.2.1


108
109
110
# File 'lib/rdf/xsd/duration.rb', line 108

def plural(v, str)
  "#{v} #{str}#{v == 1 ? '' : 's'}" if v
end

#to_fFloat

Since:

  • 0.2.1


155
156
157
158
159
160
161
162
163
# File 'lib/rdf/xsd/duration.rb', line 155

def to_f
  ( @object[:yr].to_i * 365 * 24 * 3600 +
    @object[:mo].to_i * 30 * 24 * 3600 +
    @object[:da].to_i * 24 * 3600 +
    @object[:hr].to_i * 3600 +
    @object[:mi].to_i * 60 +
    @object[:se].to_f
  ) * @object[:si]
end

#to_iInteger

Since:

  • 0.2.1


166
# File 'lib/rdf/xsd/duration.rb', line 166

def to_i; Integer(self.to_f); end

#to_sString

Returns the value as a string.

Since:

  • 0.2.1


95
96
97
98
99
100
101
102
103
104
105
106
# File 'lib/rdf/xsd/duration.rb', line 95

def to_s
  @string ||= begin
    str = @object[:si] < 0 ? "-P" : "P"
    str << "%dY" % @object[:yr].to_i if @object[:yr]
    str << "%dM" % @object[:mo].to_i if @object[:mo]
    str << "%dD" % @object[:da].to_i if @object[:da]
    str << "T" if @object[:hr] || @object[:mi] || @object[:se]
    str << "%dH" % @object[:hr].to_i if @object[:hr]
    str << "%dM" % @object[:mi].to_i if @object[:mi]
    str << "#{sec_str}S" if @object[:se]
  end
end

#valid?Boolean

Returns true if the value adheres to the defined grammar of the datatype.

Special case for date and dateTime, for which '0000' is not a valid year

Since:

  • 0.2.1


87
88
89
# File 'lib/rdf/xsd/duration.rb', line 87

def valid?
  !!(value =~ GRAMMAR)
end