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

Parameters:

  • value (Duration, Hash, Numeric, #to_s)
  • options (Hash) (defaults to: {})

    a customizable set of options

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

Returns:

See Also:

Since:

  • 0.2.1


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

Returns:

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

Returns:

  • (Integer)

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.

Returns:

  • (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

Returns:

  • (Boolean)

Since:

  • 0.2.1


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

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