Class: RDF::Literal::Duration
- Inherits:
-
RDF::Literal
- Object
- RDF::Literal
- RDF::Literal::Duration
- Defined in:
- lib/rdf/xsd/duration.rb
Overview
A duration literal.
duration
is a datatype that represents durations of time. The concept of duration being captured is drawn from those of ISO 8601, specifically durations without fixed endpoints.
Direct Known Subclasses
Constant Summary collapse
- DATATYPE =
RDF::XSD.duration
- GRAMMAR =
%r(\A (?<si>-)? P(?:(?:(?:(?:(?<yr>\d+)Y)(?:(?<mo>\d+)M)?(?:(?<da>\d+)D)?) | (?:(?:(?<mo>\d+)M)(?:(?<da>\d+)D)?) | (?:(?<da>\d+)D) ) (?:T(?:(?:(?:(?<hr>\d+)H)(?:(?<mi>\d+)M)?(?:(?<se>\d+(?:\.\d+)?)S)?) | (?:(?:(?<mi>\d+)M)(?:(?<se>\d+(?:\.\d+)?)S)?) | (?:(?<se>\d+(?:\.\d+)?)S) ) )? |(?:T(?:(?:(?:(?<hr>\d+)H)(?:(?<mi>\d+)M)?(?:(?<se>\d+(?:\.\d+)?)S)?) | (?:(?:(?<mi>\d+)M)(?:(?<se>\d+(?:\.\d+)?)S)?) | (?:(?<se>\d+(?:\.\d+)?)S) ) ) ) \z)x.freeze
Instance Method Summary collapse
-
#==(other) ⇒ Object
Returns
true
ifself
andother
are durations of the same length. -
#canonicalize! ⇒ Literal
Converts this literal into its canonical lexical representation.
-
#days ⇒ Integer
Days.
-
#hours ⇒ Integer
Hours.
-
#humanize(lang = :en) ⇒ Object
Returns a human-readable value for the interval.
-
#initialize(value, datatype: nil, lexical: nil, **options) ⇒ Duration
constructor
Creates a new Duration instance.
-
#minutes ⇒ Integer
Minutes.
-
#months ⇒ Integer
Months.
- #plural(v, str) ⇒ Object
-
#seconds ⇒ Decimal
Seconds.
-
#to_h ⇒ Hash
Returns a hash representation.
-
#to_s ⇒ String
Returns the value as a string.
-
#valid? ⇒ Boolean
Returns
true
if the value adheres to the defined grammar of the datatype. -
#years ⇒ Integer
Years.
Constructor Details
#initialize(value, datatype: nil, lexical: nil, **options) ⇒ Duration
Creates a new Duration instance.
-
Given a
String
, parse asxsd:duration
into months and seconds -
Given a
Hash
containing any of:yr
,:mo
, :da,
:hr,
:miand
:si`, it is transformed into months and seconds -
Given a Rational, the result is interpreted as days, hours, minutes, and seconds.
-
Given an Integer, the result is interpreted as years and months.
-
Object representation is the
Array(months, seconds)
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 |
# File 'lib/rdf/xsd/duration.rb', line 50 def initialize(value, datatype: nil, lexical: nil, **) super @object = case value when Hash months = value[:yr].to_i * 12 + value[:mo].to_i seconds = value[:da].to_i * 3600 * 24 + value[:hr].to_i * 3600 + value[:mi].to_i * 60 + value[:se].to_f if value[:si] if months != 0 months = -months else seconds = -seconds end end [months, seconds] when Rational [0, value * 24 * 3600] when Integer, ::Integer [value.to_i, 0] when Literal::Duration then value.object when Array then value else parse(value.to_s) end end |
Instance Method Details
#==(other) ⇒ Object
Returns true
if self
and other
are durations of the same length.
From the XQuery function op:duration-equal.
174 175 176 177 178 179 |
# File 'lib/rdf/xsd/duration.rb', line 174 def ==(other) # If lexically invalid, use regular literal testing return super unless self.valid? other.is_a?(Literal::Duration) && other.valid? ? @object == other.object : super end |
#canonicalize! ⇒ Literal
Converts this literal into its canonical lexical representation.
83 84 85 86 87 |
# File 'lib/rdf/xsd/duration.rb', line 83 def canonicalize! @string = @humanize = @hash = nil self.to_s # side-effect self end |
#days ⇒ Integer
Days
From the XQuery function fn:days-from-duration.
203 |
# File 'lib/rdf/xsd/duration.rb', line 203 def days; Integer.new(to_h[:da] * (to_h[:si] ? -1 : 1)); end |
#hours ⇒ Integer
Hours
From the XQuery function fn:hours-from-duration.
211 |
# File 'lib/rdf/xsd/duration.rb', line 211 def hours; Integer.new(to_h[:hr] * (to_h[:si] ? -1 : 1)); end |
#humanize(lang = :en) ⇒ Object
Returns a human-readable value for the interval
147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 |
# File 'lib/rdf/xsd/duration.rb', line 147 def humanize(lang = :en) @humanize ||= {} @humanize[lang] ||= begin # Just english, for now return "Invalid duration #{value.to_s.inspect}" unless valid? md = value.match(GRAMMAR) ar = [] ar << plural(md[:yr], "year") if md[:yr] ar << plural(md[:mo], "month") if md[:mo] ar << plural(md[:da], "day") if md[:da] ar << plural(md[:hr], "hour") if md[:hr] ar << plural(md[:mi], "minute") if md[:mi] ar << plural(md[:se], "second") if md[:se] last = ar.pop first = ar.join(" ") res = first.empty? ? last : "#{first} and #{last}" md[:si] == '-' ? "#{res} ago" : res end end |
#minutes ⇒ Integer
Minutes
From the XQuery function fn:minutes-from-duration.
219 |
# File 'lib/rdf/xsd/duration.rb', line 219 def minutes; Integer.new(to_h[:mi] * (to_h[:si] ? -1 : 1)); end |
#months ⇒ Integer
Months
From the XQuery function fn:months-from-duration.
195 |
# File 'lib/rdf/xsd/duration.rb', line 195 def months; Integer.new(to_h[:mo] * (to_h[:si] ? -1 : 1)); end |
#plural(v, str) ⇒ Object
141 142 143 |
# File 'lib/rdf/xsd/duration.rb', line 141 def plural(v, str) "#{v} #{str}#{v.to_i == 1 ? '' : 's'}" if v end |
#seconds ⇒ Decimal
Seconds
From the XQuery function fn:seconds-from-duration.
227 |
# File 'lib/rdf/xsd/duration.rb', line 227 def seconds; Decimal.new(to_h[:se] * (to_h[:si] ? -1 : 1)); end |
#to_h ⇒ Hash
Returns a hash representation.
104 105 106 107 108 109 110 111 112 113 114 |
# File 'lib/rdf/xsd/duration.rb', line 104 def to_h @hash ||= { si: ('-' if (@object.first == 0 ? @object.last : @object.first) < 0), yr: (@object.first.abs / 12), mo: (@object.first.abs % 12), da: (@object.last.abs.to_i / (3600 * 24)), hr: ((@object.last.abs.to_i / 3600) % 24), mi: ((@object.last.abs.to_i / 60) % 60), se: sec_str.to_f } end |
#to_s ⇒ String
Returns the value as a string.
120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 |
# File 'lib/rdf/xsd/duration.rb', line 120 def to_s @string ||= begin hash = to_h str = (@object.first == 0 ? @object.last : @object.first) < 0 ? '-P' : 'P' hash = to_h str << "%dY" % hash[:yr] if hash[:yr] > 0 str << "%dM" % hash[:mo] if hash[:mo] > 0 str << "%dD" % hash[:da] if hash[:da] > 0 str << "T" if (hash[:hr] + hash[:mi] + hash[:se]) > 0 str << "%dH" % hash[:hr] if hash[:hr] > 0 str << "%dM" % hash[:mi] if hash[:mi] > 0 str << sec_str + 'S' if hash[:se] > 0 # Ensure some legal representation if str.end_with?('P') is_a?(Literal::YearMonthDuration) ? 'P0M' : 'PT0S' else str end 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
96 97 98 |
# File 'lib/rdf/xsd/duration.rb', line 96 def valid? !!value.match?(self.class.const_get(:GRAMMAR)) end |
#years ⇒ Integer
Years
From the XQuery function fn:years-from-duration.
187 |
# File 'lib/rdf/xsd/duration.rb', line 187 def years; Integer.new(to_h[:yr] * (to_h[:si] ? -1 : 1)); end |