lib/datacite/mapping/date.rb in datacite-mapping-0.1.17.2 vs lib/datacite/mapping/date.rb in datacite-mapping-0.2.0

- old
+ new

@@ -1,7 +1,9 @@ require 'xml/mapping_extensions' +require 'datacite/mapping/date_value' + module Datacite module Mapping # Controlled vocabulary of date types. class DateType < TypesafeEnum::Base @@ -33,36 +35,27 @@ new :VALID, 'Valid' end # Represents a DataCite `<date/>` field, which can be a year, date (year-month-day or just year-month), - # or ISO8601 datetime. + # ISO8601 datetime, or [RKMS-ISO8601](http://www.ukoln.ac.uk/metadata/dcmi/collection-RKMS-ISO8601/) date range. # - # @!attribute [r] year - # @return [Integer] The year. - # @!attribute [r] month - # @return [Integer, nil] The month. Can be `nil` if no month was specified. - # @!attribute [r] day - # @return [Integer, nil] The day. Can be `nil` if no day was specified. - # @!attribute [r] hour - # @return [Integer, nil] The hour. Can be `nil` if no hour was specified. - # @!attribute [r] minute - # @return [Integer, nil] The minutes. Can be `nil` if no minutes were specified. - # @!attribute [r] sec - # @return [Integer, nil] The seconds. Can be `nil` if no seconds were specified. - # @!attribute [r] nsec - # @return [Integer, nil] The nanoseconds. Can be `nil` if no nanoseconds were specified. + # @!attribute [r] date_value + # @return [DateValue, nil] the single date/time represented by this `<date/>` field, + # if it does not represent a ragne + # @!attribute [r] range_start + # @return [DateValue, nil] the start of the date range represented by this `<date/> field`, + # if it represents a range, and the range is not open on the lower end + # @!attribute [r] range_end + # @return [DateValue, nil] the end of the date range represented by this `<date/> field`, + # if it represents a range, and the range is not open on the upper end class Date include XML::Mapping - attr_reader :year - attr_reader :month - attr_reader :day - attr_reader :hour - attr_reader :minute - attr_reader :sec - attr_reader :nsec + attr_reader :date_value + attr_reader :range_start + attr_reader :range_end # Initializes a new `Date` # # @param type [DateType] the type of date. Cannot be nil. # @param value [DateTime, Date, Integer, String] The value, as a `DateTime`, `Date`, or `Integer`, @@ -75,74 +68,33 @@ def type=(val) fail ArgumentError, 'Date type cannot be nil' unless val @type = val end - # Sets the value. - # - # @param val [DateTime, Date, Integer, String] The value, as a `DateTime`, `Date`, or `Integer`, - # or as a `String` in any [W3C DateTime format](http://www.w3.org/TR/NOTE-datetime) - def value=(val) # rubocop:disable Metrics/MethodLength, Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity - @date_time = to_datetime(val) - @date = @date_time ? @date_time.to_date : to_date(val) - @year = to_year(val) - @month = to_month(val) - @day = to_day(val) - new_value = val.respond_to?(:iso8601) ? val.iso8601 : val.to_s - if new_value.include?('T') - @hour = @date_time.hour if @date_time - @minute = @date_time.minute if @date_time - @sec = @date_time.sec if @date_time - @nsec = @date_time.to_time.nsec if @date_time + def value=(val) # rubocop:disable Metrics/AbcSize + parts = val.to_s.split('/', -1) # negative limit so we don't drop trailing empty string + @date_value, @range_start, @range_end = nil + if parts.size == 1 + @date_value = DateValue.new(val) + elsif parts.size == 2 + @range_start, @range_end = parts.map(&:strip).map { |part| DateValue.new(part) unless part == '' } + # puts "#{val} -> [#{range_start}, #{range_end}]" + else + fail ArgumentError, "Unable to parse date value #{val}" end - fail ArgumentError, "Unable to parse date value '#{val}'" unless @year - @value = new_value + @value = val end private - def to_year(val) - return val if val.is_a?(Integer) - return val.year if val.respond_to?(:year) - matchdata = val.to_s.match(/^[0-9]+/) - matchdata[0].to_i if matchdata - end - - def to_month(val) - return val.month if val.respond_to?(:month) - matchdata = val.to_s.match(/^[0-9]+-([0-9]{2})(?![0-9])/) - matchdata[1].to_i if matchdata - end - - def to_day(val) - return val.day if val.respond_to?(:day) - matchdata = val.to_s.match(/^[0-9]+-[0-9]{2}-([0-9]{2})(?![0-9])/) - matchdata[1].to_i if matchdata - end - - def to_datetime(val) - return val if val.is_a?(DateTime) - DateTime.parse(val.to_s) - rescue ArgumentError => e - Mapping.log.debug("Can't extract DateTime from date value '#{val}': #{e}") - nil - end - - def to_date(val) - return val if val.is_a?(::Date) - return ::Date.parse(val.iso8601) if val.respond_to?(:iso8601) - ::Date.parse(val.to_s) - rescue ArgumentError => e - Mapping.log.debug("Can't extract Date from date value '#{val}': #{e}") - nil - end - # @!attribute [rw] type # @return [DateType] the type of date. Cannot be nil. typesafe_enum_node :type, '@dateType', class: DateType # @!method value # @return [String] The value as a string. May be any [W3C DateTime format](http://www.w3.org/TR/NOTE-datetime). text_node :value, 'text()' + + fallback_mapping :datacite_3, :_default end end end