Open yinshiyi opened 1 year ago
Not sure the cause. Can you share a minimal reproducible example and a sample of the .ics file that causes the error?
Hi, I am getting the same error:
Error in if (!is.na(x) & !x == "NA" & !grepl("^\\d{8}T\\d{6}Z?$", x)) { :
the condition has length > 1
When I try to parse the following ics file with calendar::ic_read()
:
BEGIN:VCALENDAR
VERSION:2.0
PRODID:healthroster
X-WR-CALNAME:R
BEGIN:VEVENT
UID:45768392
DTSTAMP:20230405T230000Z
DTSTART:20230406T110000Z
DTEND:20230406T190000Z
LOCATION:Admitting
DESCRIPTION:Rest Time : 00:00\n
SUMMARY:Late shift
END:VEVENT
BEGIN:VEVENT
UID:46794060
DTSTAMP:20230410T230000Z
DTSTART:20230411T070000Z
DTEND:20230411T110000Z
LOCATION:Admitting
DESCRIPTION:Rest Time : 00:00\n
SUMMARY:Early shift
END:VEVENT
END:VCALENDAR
Wasn't sure if it was the format of the ics file, which is being produced by roster software at work, or a bug.
So I have passed this through the debugger tracing the failure sequentially: ic_read()
>> ical()
>> ic_dateframe()
>> ic_datetime()
.
If you shorten the above ics file to just one event it works ok, although does not correctly identify that the times are offset by 1 hour as they are actually BST but stored at GMT:
BEGIN:VCALENDAR
VERSION:2.0
PRODID:healthroster
X-WR-CALNAME:R
BEGIN:VEVENT
UID:45768392
DTSTAMP:20230405T230000Z
DTSTART:20230406T110000Z
DTEND:20230406T190000Z
LOCATION:Admitting
DESCRIPTION:Rest Time : 00:00\n
SUMMARY:Late shift
END:VEVENT
END:VCALENDAR
Interestingly if I import an ics created with MacOS calendar with multiple events, it completes parsing it but it fails to convert the date columns to datetime class:
BEGIN:VCALENDAR
CALSCALE:GREGORIAN
PRODID:-//Apple Inc.//macOS 13.4.1//EN
VERSION:2.0
X-WR-CALNAME:Acute Med
BEGIN:VTIMEZONE
TZID:Europe/London
BEGIN:DAYLIGHT
DTSTART:19810329T010000
RRULE:FREQ=YEARLY;BYMONTH=3;BYDAY=-1SU
TZNAME:BST
TZOFFSETFROM:+0000
TZOFFSETTO:+0100
END:DAYLIGHT
BEGIN:STANDARD
DTSTART:19961027T020000
RRULE:FREQ=YEARLY;BYMONTH=10;BYDAY=-1SU
TZNAME:GMT
TZOFFSETFROM:+0100
TZOFFSETTO:+0000
END:STANDARD
END:VTIMEZONE
BEGIN:VEVENT
CREATED:20230320T213321Z
DESCRIPTION:Rest Time : 00:00\n
DTEND;TZID=Europe/London:20230630T160000
DTSTAMP:20230709T221931Z
DTSTART;TZID=Europe/London:20230630T120000
LAST-MODIFIED:20230320T213321Z
LOCATION:ED
SEQUENCE:0
SUMMARY:ED PM - PM - Medics - AMU Medical Staff
TRANSP:OPAQUE
UID:5C15BDCE-C77A-4A67-BBD3-8D5AD233A034
END:VEVENT
BEGIN:VEVENT
CREATED:20230320T213321Z
DESCRIPTION:Rest Time : 00:00\n
DTEND;TZID=Europe/London:20230630T120000
DTSTAMP:20230709T221931Z
DTSTART;TZID=Europe/London:20230630T080000
LAST-MODIFIED:20230320T213321Z
LOCATION:Admitting
SEQUENCE:0
SUMMARY:Take AM - Day - Medics - AMU Medical Staff
TRANSP:OPAQUE
UID:E8451B5F-FCD7-4FE8-BF8E-52B76AAAFEA1
END:VEVENT
END:VCALENDAR
At present my work around is to use the ical package which does seem to parse all the above correctly and also even corrects the times which are stored offset to GMT by the roster software but it doesn't have such comprehensive tools as your package.
Unfortunately I am not good enough at coding to get my head round what the problems are.
Thanks @silverfoxdoc for the updated info. We have limited capacity to work on this at the moment so anything to help, including a fully reproducible example, could really help.
library(ical)
library(calendar)
# 1) example using a calendar initially produced by work health roster software
# import calendar text to object then write out to ics file in preparation for import
# calendar packages
# the double escape at line 20 included to produce a single \ which
# appears in the original file
health_roster_calendar_file_one_item <- "BEGIN:VCALENDAR
VERSION:2.0
PRODID:healthroster
X-WR-CALNAME:R
BEGIN:VEVENT
UID:45768392
DTSTAMP:20230405T230000Z
DTSTART:20230406T110000Z
DTEND:20230406T190000Z
LOCATION:Admitting
DESCRIPTION:Rest Time : 00:00\\n
SUMMARY:Late shift
END:VEVENT
END:VCALENDAR"
writeLines(health_roster_calendar_file_one_item, "health_roster_one_item.ics")
# ical package produces the correct times; the times are stored as zulu time and
# it automatically offsets this to be correct to the local time zone on my computer which
# Europe/London and at time of writing is BST (British Summer Time)
ical::ical_parse_df("health_roster_one_item.ics")
#> uid summary start end
#> 1 45768392 Late shift 2023-04-06 12:00:00 2023-04-06 20:00:00
#> description last.modified status
#> 1 Rest Time : 00:00\n 1970-01-01 01:00:00 NA
# calendar parses and correctly produces columns with class dttm but it does not correctly
# offset the time like ical does
calendar::ic_read("health_roster_one_item.ics")
#> # A tibble: 1 × 7
#> UID DTSTAMP DTSTART DTEND LOCATION DESCRIPTION
#> <chr> <chr> <dttm> <dttm> <chr> <chr>
#> 1 45768392 2023040… 2023-04-06 11:00:00 2023-04-06 19:00:00 Admitti… "Rest Time…
#> # ℹ 1 more variable: SUMMARY <chr>
# 2) example using an ics file with two events produced by health roster software
# import same process as above
health_roster_calendar_file_two_items <- "BEGIN:VCALENDAR
VERSION:2.0
PRODID:healthroster
X-WR-CALNAME:R
BEGIN:VEVENT
UID:45768392
DTSTAMP:20230405T230000Z
DTSTART:20230406T110000Z
DTEND:20230406T190000Z
LOCATION:Admitting
DESCRIPTION:Rest Time : 00:00\\n
SUMMARY:Late shift
END:VEVENT
BEGIN:VEVENT
UID:46794060
DTSTAMP:20230410T230000Z
DTSTART:20230411T070000Z
DTEND:20230411T110000Z
LOCATION:Admitting
DESCRIPTION:Rest Time : 00:00\\n
SUMMARY:Early shift
END:VEVENT
END:VCALENDAR"
writeLines(health_roster_calendar_file_two_items, "health_roster_two_items.ics")
# ical package again parses corectly
ical::ical_parse_df("health_roster_two_items.ics")
#> uid summary start end
#> 1 45768392 Late shift 2023-04-06 12:00:00 2023-04-06 20:00:00
#> 2 46794060 Early shift 2023-04-11 08:00:00 2023-04-11 12:00:00
#> description last.modified status
#> 1 Rest Time : 00:00\n 1970-01-01 01:00:00 NA
#> 2 Rest Time : 00:00\n 1970-01-01 01:00:00 NA
# calendar fails to parse at all
calendar::ic_read("health_roster_two_items.ics")
#> Error in if (!is.na(x) & !x == "NA" & !grepl("^\\d{8}T\\d{6}Z?$", x)) {: the condition has length > 1
# 3) example using calendar originally exported using MacOS calendar
# import same process as above
mac_os_calendar <- "BEGIN:VCALENDAR
CALSCALE:GREGORIAN
PRODID:-//Apple Inc.//macOS 13.4.1//EN
VERSION:2.0
X-WR-CALNAME:Acute Med
BEGIN:VTIMEZONE
TZID:Europe/London
BEGIN:DAYLIGHT
DTSTART:19810329T010000
RRULE:FREQ=YEARLY;BYMONTH=3;BYDAY=-1SU
TZNAME:BST
TZOFFSETFROM:+0000
TZOFFSETTO:+0100
END:DAYLIGHT
BEGIN:STANDARD
DTSTART:19961027T020000
RRULE:FREQ=YEARLY;BYMONTH=10;BYDAY=-1SU
TZNAME:GMT
TZOFFSETFROM:+0100
TZOFFSETTO:+0000
END:STANDARD
END:VTIMEZONE
BEGIN:VEVENT
CREATED:20230320T213321Z
DESCRIPTION:Rest Time : 00:00\\n
DTEND;TZID=Europe/London:20230630T160000
DTSTAMP:20230709T221931Z
DTSTART;TZID=Europe/London:20230630T120000
LAST-MODIFIED:20230320T213321Z
LOCATION:ED
SEQUENCE:0
SUMMARY:ED PM - PM - Medics - AMU Medical Staff
TRANSP:OPAQUE
UID:5C15BDCE-C77A-4A67-BBD3-8D5AD233A034
END:VEVENT
BEGIN:VEVENT
CREATED:20230320T213321Z
DESCRIPTION:Rest Time : 00:00\\n
DTEND;TZID=Europe/London:20230630T120000
DTSTAMP:20230709T221931Z
DTSTART;TZID=Europe/London:20230630T080000
LAST-MODIFIED:20230320T213321Z
LOCATION:Admitting
SEQUENCE:0
SUMMARY:Take AM - Day - Medics - AMU Medical Staff
TRANSP:OPAQUE
UID:E8451B5F-FCD7-4FE8-BF8E-52B76AAAFEA1
END:VEVENT
END:VCALENDAR"
writeLines(mac_os_calendar, "mac_os_calendar.ics")
# ical package parses correctly
ical::ical_parse_df("mac_os_calendar.ics")
#> uid
#> 1 <NA>
#> 2 5C15BDCE-C77A-4A67-BBD3-8D5AD233A034
#> 3 E8451B5F-FCD7-4FE8-BF8E-52B76AAAFEA1
#> summary start
#> 1 <NA> 1970-01-01 01:00:00
#> 2 ED PM - PM - Medics - AMU Medical Staff 2023-06-30 12:00:00
#> 3 Take AM - Day - Medics - AMU Medical Staff 2023-06-30 08:00:00
#> end description last.modified status
#> 1 1970-01-01 01:00:00 <NA> 1970-01-01 01:00:00 NA
#> 2 2023-06-30 16:00:00 Rest Time : 00:00\n 2023-03-20 21:33:21 NA
#> 3 2023-06-30 12:00:00 Rest Time : 00:00\n 2023-03-20 21:33:21 NA
# calendar parses but does not correctly allocate the datetime columns as dttm class
calendar::ic_read("mac_os_calendar.ics")
#> # A tibble: 2 × 11
#> CREATED DESCRIPTION DTEND;TZID=Europe/Lo…¹ DTSTAMP DTSTART;TZID=Europe/…²
#> <chr> <chr> <chr> <chr> <chr>
#> 1 20230320T21… "Rest Time… 20230630T160000 202307… 20230630T120000
#> 2 20230320T21… "Rest Time… 20230630T120000 202307… 20230630T080000
#> # ℹ abbreviated names: ¹`DTEND;TZID=Europe/London`,
#> # ²`DTSTART;TZID=Europe/London`
#> # ℹ 6 more variables: `LAST-MODIFIED` <chr>, LOCATION <chr>, SEQUENCE <chr>,
#> # SUMMARY <chr>, TRANSP <chr>, UID <chr>
Created on 2023-07-16 with reprex v2.0.2
put together a reprex as best I can to try to highlight the three issues I have come across
Many thanks @silverfoxdoc . I will try to look at this but have limited time at the moment I'm afraid.
thanks for adding to the, no doubt, huge do list @Robinlovelace
Hi
I have just send a pull request to fix this
The error occurred because the warning from function ic_datetime
is not vectorized
Replacing the !is.na(x) & !x == "NA" & !grepl("^\d{8}T\d{6}Z?$", x)
with any(!is.na(x) & !(x == "NA") & !grepl("^\\d{8}T\\d{6}Z?$", x))
in the If
will fix the issue
Thanks and regards
Amazing. Will check the PR now :pray:
just sent a pull request to fix the zulu time zone assignment problem I was experiencing above; see what you think and if it should be included
Thank you, will check now!
Error in if (!is.na(x) & !x == "NA" & !grepl("^\d{8}T\d{6}Z?$", x)) { : the condition has length > 1
Anyone know the possible bugs?