-
Notifications
You must be signed in to change notification settings - Fork 362
Better preserve timezones in ical #569
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change | ||||||||
---|---|---|---|---|---|---|---|---|---|---|
|
@@ -35,10 +35,22 @@ def self.ical_utc_format(time) | |||||||||
|
||||||||||
def self.ical_format(time, force_utc) | ||||||||||
time = time.dup.utc if force_utc | ||||||||||
|
||||||||||
# Keep timezone. strftime will serializer short versions of time zone (eg. EEST), | ||||||||||
# which are not reversivible, as there are many repeated abbreviated zones. This will result in | ||||||||||
# issues in parsing | ||||||||||
if time.respond_to?(:time_zone) | ||||||||||
tz_id = time.time_zone.name | ||||||||||
return ";TZID=#{tz_id}:#{IceCube::I18n.l(time, format: "%Y%m%dT%H%M%S")}" # local time specified" | ||||||||||
end | ||||||||||
|
||||||||||
if time.utc? | ||||||||||
":#{IceCube::I18n.l(time, format: "%Y%m%dT%H%M%SZ")}" # utc time | ||||||||||
else | ||||||||||
";TZID=#{IceCube::I18n.l(time, format: "%Z:%Y%m%dT%H%M%S")}" # local time specified | ||||||||||
# Convert to UTC as TZID=+xxxx format is not recognized by JS libraries | ||||||||||
warn "IceCube: Time object does not have timezone info. Assuming UTC: #{caller(1..1).first}" | ||||||||||
Comment on lines
+50
to
+51
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||||||
utc_time = time.dup.utc | ||||||||||
":#{IceCube::I18n.l(utc_time, format: "%Y%m%dT%H%M%SZ")}" # converted to utc time | ||||||||||
end | ||||||||||
end | ||||||||||
|
||||||||||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -4,18 +4,25 @@ def self.schedule_from_ical(ical_string, options = {}) | |
data = {} | ||
ical_string.each_line do |line| | ||
(property, value) = line.split(":") | ||
(property, _tzid) = property.split(";") | ||
(property, tzid_param) = property.split(";") | ||
|
||
# Extract TZID if present | ||
tzid = nil | ||
if tzid_param && tzid_param.start_with?("TZID=") | ||
tzid = tzid_param[5..-1] # Remove "TZID=" prefix | ||
end | ||
|
||
case property | ||
when "DTSTART" | ||
data[:start_time] = TimeUtil.deserialize_time(value) | ||
data[:start_time] = deserialize_time_with_tzid(value, tzid) | ||
when "DTEND" | ||
data[:end_time] = TimeUtil.deserialize_time(value) | ||
data[:end_time] = deserialize_time_with_tzid(value, tzid) | ||
when "RDATE" | ||
data[:rtimes] ||= [] | ||
data[:rtimes] += value.split(",").map { |v| TimeUtil.deserialize_time(v) } | ||
data[:rtimes] += value.split(",").map { |v| deserialize_time_with_tzid(v, tzid) } | ||
when "EXDATE" | ||
data[:extimes] ||= [] | ||
data[:extimes] += value.split(",").map { |v| TimeUtil.deserialize_time(v) } | ||
data[:extimes] += value.split(",").map { |v| deserialize_time_with_tzid(v, tzid) } | ||
when "DURATION" | ||
data[:duration] # FIXME | ||
when "RRULE" | ||
|
@@ -26,6 +33,22 @@ def self.schedule_from_ical(ical_string, options = {}) | |
Schedule.from_hash data | ||
end | ||
|
||
def self.deserialize_time_with_tzid(time_value, tzid) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This should maybe be moved into the TimeUtil class since it's a wrapper for the |
||
if tzid.nil? || tzid.empty? | ||
# No TZID, use standard deserialization | ||
TimeUtil.deserialize_time(time_value) | ||
else | ||
# TZID is a timezone name - Assume it's a valid timezone in a try-catch block | ||
begin | ||
TimeUtil.deserialize_time({time: time_value, zone: tzid}) | ||
rescue ArgumentError | ||
# If the timezone is invalid, fall back to standard deserialization | ||
# Perhaps we want to log this? | ||
TimeUtil.deserialize_time(time_value) | ||
Comment on lines
+44
to
+47
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Should we issue a warning here as well? |
||
end | ||
end | ||
end | ||
|
||
def self.rule_from_ical(ical) | ||
raise ArgumentError, "empty ical rule" if ical.nil? | ||
|
||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.