ruby-rdf/rdf

View on GitHub
lib/rdf/model/literal/datetime.rb

Summary

Maintainability
A
1 hr
Test Coverage
module RDF; class Literal
  ##
  # A date/time literal.
  #
  # @see   http://www.w3.org/TR/xmlschema11-2/#dateTime
  # @see   https://www.w3.org/TR/xmlschema11-2/#rf-lexicalMappings-datetime
  # @since 0.2.1
  class DateTime < Temporal
    DATATYPE = RDF::URI("http://www.w3.org/2001/XMLSchema#dateTime")
    GRAMMAR  = %r(\A
      (#{YEARFRAG}
      -#{MONTHFRAG}
      -#{DAYFRAG}
      T
      (?:
       (?:
        #{HOURFRAG}
       :#{MINUTEFRAG}
       :#{SECONDFRAG})
      | #{EODFRAG}))
     (#{TZFRAG})?\z)x.freeze
    FORMAT   = '%Y-%m-%dT%H:%M:%S.%L'.freeze

    ##
    # Internally, a `DateTime` is represented using a native `::DateTime`. If initialized from a `::Date`, there is no timezone component, If initialized from a `::DateTime`, the timezone is taken from that native object, otherwise, a timezone (or no timezone) is taken from the string representation having a matching `zzzzzz` component.
    #
    # @param  [DateTime] value
    # @option options [String] :lexical (nil)
    def initialize(value, datatype: nil, lexical: nil, **options)
      @datatype = RDF::URI(datatype || self.class.const_get(:DATATYPE))
      @string   = lexical || (value if value.is_a?(String))
      @object   = case
        when value.is_a?(::DateTime)
          @zone = value.zone
          value
        when value.respond_to?(:to_datetime) 
          @zone = value.to_datetime.zone
          value.to_datetime
        else
          md = value.to_s.match(GRAMMAR)
          _, _, tz = Array(md)
          if tz
            @zone = tz == 'Z' ? '+00:00' : tz
          else
            @zone = nil # No timezone
          end
          ::DateTime.parse(value.to_s)
      end rescue ::DateTime.new
    end

    ##
    # Returns a human-readable value for the literal
    #
    # @return [String]
    # @since 1.1.6
    def humanize(lang = :en)
      d = object.strftime("%r on %A, %d %B %Y")
      if timezone?
        z = @zone == '+00:00' ? "UTC" : @zone
        d.sub!(" on ", " #{z} on ")
      end
      d
    end
  end # DateTime
end; end # RDF::Literal