class Mhc::Converter::IcalendarImporter
Public Class Methods
parse_ics(ics)
click to toggle source
# File lib/mhc/converter.rb, line 182 def self.parse_ics(ics) # * 3.8.1. Descriptive Component Properties # ** CATEGORIES 3.8.1.2. Categories # ** DESCRIPTION 3.8.1.5. Description # ** LOCATION 3.8.1.7. Location # ** SUMMARY 3.8.1.12. Summary # * 3.8.2. Date and Time Component Properties # ** DTEND 3.8.2.2. Date-Time End # ** DTSTART 3.8.2.4. Date-Time Start # ** DURATION 3.8.2.5. Duration # * 3.8.4. Relationship Component Properties # ** RECURRENCE-ID 3.8.4.4. Recurrence ID # * 3.8.5. Recurrence Component Properties # ** EXDATE 3.8.5.1. Exception Date-Times # ** RDATE 3.8.5.2. Recurrence Date-Times # ** RRULE 3.8.5.3. Recurrence Rule # * 3.8.7. Change Management Component Properties # ** SEQUENCE 3.8.7.4. Sequence Number # * 3.8.8. Miscellaneous Component Properties # ** X-FIELD 3.8.8.2. Non-Standard Properties # DTSTART: # Date part => X-SC-Duration: .first # Time part => X-SC-Time: .first # DTEND # Date part => # DTEND - DTSTART = 1day # DTEND - DTSTART > 1days # Day: # RRULE: # X-SC-Cond: # UNTIL: # X-SC-Duration: .last # RDATES: # X-SC-Day: # EXDATES: # X-SC-Day: !YYYYMMDD # ical = RiCal.parse_string(ics).first return nil unless ical iev = ical.events.first allday = !iev.dtstart.respond_to?(:hour) recurring = !iev.rrule.empty? # X-SC-Day: (from DTSTART, DTEND) # for recurring event, DTSTSRT is a start part of X-SC-Duration: dates = [] unless recurring date = tz_convert(iev.dtstart).strftime("%Y%m%d") if allday && (iev.dtend - iev.dtstart).to_i > 1 date += "-" + (iev.dtend - 1).to_time.strftime("%Y%m%d") end dates << date end # X-SC-Day: (from RDATE, EXDATE) dates += iev.rdate.flatten.map{|d| d.to_time.strftime("%Y%m%d")} exdates = iev.exdate.flatten.map{|d| d.to_time.strftime("!%Y%m%d")} # X-SC-Time: unless allday time = tz_convert(iev.dtstart).strftime("%H:%M") if iev.dtend time += "-" + tz_convert(iev.dtend).strftime("%H:%M") end end ev = Mhc::Event.parse "X-SC-Subject: #{iev.summary}\n" + "X-SC-Location: #{iev.location}\n" + "X-SC-Day: #{(dates + exdates).join(' ')}\n" + "X-SC-Time: #{time}\n" + "X-SC-Category: #{iev.categories.to_a.join(' ')}\n" + "X-SC-Mission-Tag: #{iev.x_sc_mission_tag.first}\n" + "X-SC-Recurrence-Tag: #{iev.x_sc_recurrence_tag.first}\n" + "X-SC-Cond: \n" + "X-SC-Duration: \n" + "X-SC-Alarm: \n" + "X-SC-Record-Id: #{iev.uid}\n" + "X-SC-Sequence: #{iev.sequence.to_i}\n\n" + iev.description.to_s + if $MHC_DEBUG_FOR_DEVELOPER # FIXME: should introduce good logger and debug scheme ical.to_s.force_encoding("ASCII-8BIT").gsub(/\r\n/, "\n") else "" end # X-SC-Cond: ev.recurrence_condition.set_from_ics(iev.rrule.first, tz_convert(iev.dtstart)) # X-SC-Duration: is only for recurring articles if recurring duration_string = tz_convert(iev.dtstart).strftime("%Y%m%d") + "-" if iev.rrule.first.to_s.match(/until=([^;]+)/i) duration_string += parse_ical_datetime($1).strftime("%Y%m%d") end ev.duration = duration_string end return ev end
Private Class Methods
parse_ical_datetime(datetime_string, dst_tzid = nil)
click to toggle source
# File lib/mhc/converter.rb, line 309 def self.parse_ical_datetime(datetime_string, dst_tzid = nil) src_tzid = case datetime_string when /TZID=([^;]+)/ $1 when /\d{8}T\d{6}Z/ "UTC" else Mhc.default_tzid end dst_tzid ||= Mhc.default_tzid if /^(\d{4})(\d\d)(\d\d)(?:T(\d\d)(\d\d)(\d\d)Z?)?$/ =~ datetime_string time = Time.utc($1, $2, $3, $4, $5, $6) return tz_convert(time, src_tzid: src_tzid, dst_tzid: dst_tzid) else raise ArgumentError end end
tz_convert(datetime, src_tzid: nil, dst_tzid: nil)
click to toggle source
# File lib/mhc/converter.rb, line 285 def self.tz_convert(datetime, src_tzid: nil, dst_tzid: nil) return datetime unless datetime.respond_to?(:hour) dst_tzid ||= Mhc.default_tzid src_tzid ||= if datetime.respond_to?(:tzid) and datetime.tzid datetime.tzid else Mhc.default_tzid end dst_tz = TZInfo::Timezone.get(dst_tzid) src_tz = TZInfo::Timezone.get(src_tzid) utc = Time.utc(datetime.year, datetime.month, datetime.day, datetime.hour, datetime.min, datetime.sec) time1 = src_tz.local_to_utc(utc) time1.tzid = src_tzid if time1.respond_to?(:tzid) time = dst_tz.utc_to_local(time1) time.tzid = dst_tzid if time.respond_to?(:tzid) return time end