class Tilia::VObject::Property::VCard::DateAndOrTime
DateAndOrTime
property.
This object encodes DATE-AND-OR-TIME values.
Attributes
Field separator.
@return [null|string]
Public Class Methods
Tilia::VObject::Property::new
# File lib/tilia/v_object/property/v_card/date_and_or_time.rb, line 323 def initialize(*args) super(*args) @delimiter = nil end
Public Instance Methods
Returns a date-time value.
Note that if this property contained more than 1 date-time, only the first will be returned. To get an array with multiple values, call getDateTimes.
If no time was specified, we will always use midnight (in the default timezone) as the time.
If parts of the date were omitted, such as the year, we will grab the current values for those. So at the time of writing, if the year was omitted, we would have filled in 2014.
@return [Time]
# File lib/tilia/v_object/property/v_card/date_and_or_time.rb, line 91 def date_time now = ::Time.zone.now tz_format = now.utc_offset == 0 ? 'Z' : '%z' now_parts = DateTimeParser.parse_v_card_date_time(now.strftime('%Y%m%dT%H%M%S' + tz_format)) date_parts = DateTimeParser.parse_v_card_date_time(value) # This sets all the missing parts to the current date/time. # So if the year was missing for a birthday, we're making it 'this # year'. date_parts.each do |k, v| date_parts[k] = now_parts[k] unless v end # Now follows a ruby Hack date_parts['timezone'] = '+0000' if date_parts['timezone'] == 'Z' done = false datetime = nil ActiveSupport::TimeZone.all.each do |tz| datetime = tz.parse("#{date_parts['year']}-#{date_parts['month']}-#{date_parts['date']} #{date_parts['hour']}:#{date_parts['minute']}:#{date_parts['second']}") next unless datetime.strftime('%z') == date_parts['timezone'] done = true break end fail 'could not load correct time zone' unless done # End ruby hack datetime.freeze datetime end
Sets the property as a DateTime
object.
@param [Time] dt
@return [void]
# File lib/tilia/v_object/property/v_card/date_and_or_time.rb, line 63 def date_time=(dt) tz = dt.time_zone is_utc = ['UTC', 'GMT', 'Z'].include?(tz.name) if is_utc value = dt.strftime('%Y%m%dT%H%M%SZ') else # Calculating the offset. value = dt.strftime('%Y%m%dT%H%M%S%z') end @value = value end
Returns the value, in the format it should be encoded for json.
This method must always return an array.
@return [array]
# File lib/tilia/v_object/property/v_card/date_and_or_time.rb, line 131 def json_value parts = DateTimeParser.parse_v_card_date_time(value) date_str = '' # Year if !parts['year'].nil? date_str += format('%02i', parts['year']) unless parts['month'].nil? # If a year and a month is set, we need to insert a separator # dash. date_str += '-' end else if !parts['month'].nil? || !parts['date'].nil? # Inserting two dashes date_str += '--' end end # Month if !parts['month'].nil? date_str += format('%02i', parts['month']) if parts['date'] # If month and date are set, we need the separator dash. date_str += '-' end elsif parts['date'] # If the month is empty, and a date is set, we need a 'empty # dash' date_str += '-' end # Date date_str += format('%02i', parts['date']) unless parts['date'].nil? # Early exit if we don't have a time string. if parts['hour'].nil? && parts['minute'].nil? && parts['second'].nil? return [date_str] end date_str += 'T' # Hour if !parts['hour'].nil? date_str += format('%02i', parts['hour']) date_str += ':' unless parts['minute'].nil? else # We know either minute or second _must_ be set, so we insert a # dash for an empty value. date_str += '-' end # Minute if !parts['minute'].nil? date_str += format('%02i', parts['minute']) date_str += ':' unless parts['second'].nil? elsif parts['second'] # Dash for empty minute date_str += '-' end # Second date_str += format('%02i', parts['second']) unless parts['second'].nil? # Timezone date_str += parts['timezone'] unless parts['timezone'].nil? [date_str] end
Sets a multi-valued property.
You may also specify DateTime
objects here.
@param [array] parts
@return [void]
Tilia::VObject::Property#parts=
# File lib/tilia/v_object/property/v_card/date_and_or_time.rb, line 31 def parts=(parts) fail ArgumentError, 'Only one value allowed' if parts.size > 1 if parts[0].is_a?(::Time) self.date_time = parts[0] else super(parts) end end
Returns a raw mime-dir representation of the value.
@return [String]
# File lib/tilia/v_object/property/v_card/date_and_or_time.rb, line 301 def raw_mime_dir_value parts.join(@delimiter) end
Sets a raw value coming from a mimedir (iCalendar/vCard) file.
This has been 'unfolded', so only 1 line will be passed. Unescaping is not yet done, but parameters are not included.
@param [String] val
@return [void]
# File lib/tilia/v_object/property/v_card/date_and_or_time.rb, line 294 def raw_mime_dir_value=(val) self.value = val end
(see Component#validate
)
Tilia::VObject::Property#validate
# File lib/tilia/v_object/property/v_card/date_and_or_time.rb, line 306 def validate(options = 0) messages = super(options) value = self.value begin DateTimeParser.parse_v_card_date_time(value) rescue InvalidDataException messages << { 'level' => 3, 'message' => "The supplied value (#{value}) is not a correct DATE-AND-OR-TIME property", 'node' => self } end messages end
Updates the current value.
This may be either a single, or multiple strings in an array.
Instead of strings, you may also use DateTime
here.
@param [String|array|DateTime] value
@return [void]
# File lib/tilia/v_object/property/v_card/date_and_or_time.rb, line 50 def value=(value) if value.is_a?(::Time) self.date_time = value else super end end
Returns the type of value.
This corresponds to the VALUE= parameter. Every property also has a 'default' valueType.
@return [String]
# File lib/tilia/v_object/property/v_card/date_and_or_time.rb, line 20 def value_type 'DATE-AND-OR-TIME' end
Protected Instance Methods
This method serializes only the value of a property. This is used to create xCard or xCal documents.
@param [XmlWriter] writer XML writer.
@return [void]
# File lib/tilia/v_object/property/v_card/date_and_or_time.rb, line 214 def xml_serialize_value(writer) value_type = self.value_type.downcase parts = DateTimeParser.parse_v_card_date_and_or_time(value) value = '' # d = defined d = lambda do |part| !parts[part].nil? end # r = read r = lambda do |part| parts[part] || '' end # From the Relax NG Schema. # # # 4.3.1 # value-date = element date { # xsd:string { pattern = "\d{8}|\d{4}-\d\d|--\d\d(\d\d)?|---\d\d" } # } if (d.call('year') || d.call('month') || d.call('date')) && (!d.call('hour') && !d.call('minute') && !d.call('second') && !d.call('timezone')) if d.call('year') && d.call('month') && d.call('date') value += r.call('year') + r.call('month') + r.call('date') elsif d.call('year') && d.call('month') && !d.call('date') value += r.call('year') + '-' + r.call('month') elsif !d.call('year') && d.call('month') value += '--' + r.call('month') + r.call('date') elsif !d.call('year') && !d.call('month') && d.call('date') value += '---' + r.call('date') end # # 4.3.2 # value-time = element time { # xsd:string { pattern = "(\d\d.call(\d\d.call(\d\d)?)?|-\d\d.call(\d\d?)|--\d\d)" # ~ "(Z|[+\-]\d\d.call(\d\d)?)?" } # } elsif (!d.call('year') && !d.call('month') && !d.call('date')) && (d.call('hour') || d.call('minute') || d.call('second')) if d.call('hour') value += r.call('hour') + r.call('minute') + r.call('second') elsif d.call('minute') value += '-' + r.call('minute') + r.call('second') elsif d.call('second') value += '--' + r.call('second') end value += r.call('timezone') # # 4.3.3 # value-date-time = element date-time { # xsd:string { pattern = "(\d{8}|--\d{4}|---\d\d)T\d\d.call(\d\d.call(\d\d)?)?" # ~ "(Z|[+\-]\d\d.call(\d\d)?)?" } # } elsif d.call('date') && d.call('hour') if d.call('year') && d.call('month') && d.call('date') value += r.call('year') + r.call('month') + r.call('date') elsif !d.call('year') && d.call('month') && d.call('date') value += '--' + r.call('month') + r.call('date') elsif !d.call('year') && !d.call('month') && d.call('date') value += '---' + r.call('date') end value += 'T' + r.call('hour') + r.call('minute') + r.call('second') + r.call('timezone') end writer.write_element(value_type, value) end