Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 23 additions & 1 deletion src/IcalParser.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,9 @@ class IcalParser {
/** @var \DateTimeZone */
public $timezone;

/** @var string */
public $title;

/** @var array */
public $data;

Expand Down Expand Up @@ -382,7 +385,26 @@ private function parseRow($row) {
// if this is an invalid timezone, then fallback to GMT. This logic may not be right!
$this->timezone = new \DateTimeZone("GMT");
}
}
} else if ($key === "TZOFFSETTO" &&
(!isset($this->timezone) ||
$this->timezone->getName() === "GMT") &&
preg_match("/[-+]?(?<hours>[\d]{2})(?<minutes>[\d]{2})/", $value, $matches)
) {
// if timezone is invalid and TZOFFSETTO is provided, use that to build a timezone
$seconds = intval($matches["hours"]) * 60 * 60 + intval($matches["minutes"]) * 60;

if ($value[0] === "-") {
$seconds *= -1;
}

// TZOFFSETTO provides local time offset when DST is not in operation, so I think this is right
$timezoneName = timezone_name_from_abbr("", $seconds, false);
$this->timezone = new \DateTimezone($timezoneName);
}

if ($key === "X-WR-CALNAME") {
$this->title = $value;
}

// have some middle part ?
if ($middle && preg_match_all('#(?<key>[^=;]+)=(?<value>[^;]+)#', $middle, $matches, PREG_SET_ORDER)) {
Expand Down
63 changes: 63 additions & 0 deletions tests/cal/calendar_title.ics
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
BEGIN:VCALENDAR
PRODID:-//Google Inc//Google Calendar 70.9054//EN
VERSION:2.0
CALSCALE:GREGORIAN
METHOD:PUBLISH
X-WR-CALNAME:School Board
X-WR-TIMEZONE:America/Chicago
X-WR-CALDESC:
BEGIN:VTIMEZONE
TZID:America/Chicago
X-LIC-LOCATION:America/Chicago
BEGIN:DAYLIGHT
TZOFFSETFROM:-0600
TZOFFSETTO:-0500
TZNAME:CDT
DTSTART:19700308T020000
RRULE:FREQ=YEARLY;BYMONTH=3;BYDAY=2SU
END:DAYLIGHT
BEGIN:STANDARD
TZOFFSETFROM:-0500
TZOFFSETTO:-0600
TZNAME:CST
DTSTART:19701101T020000
RRULE:FREQ=YEARLY;BYMONTH=11;BYDAY=1SU
END:STANDARD
END:VTIMEZONE
BEGIN:VEVENT
DTSTART;TZID=America/Chicago:20160808T180000
DTEND;TZID=America/Chicago:20160808T203000
DTSTAMP:20160718T160226Z
UID:kpgr4590djmi89l3sv51gmalrc@google.com
ATTENDEE;CUTYPE=INDIVIDUAL;ROLE=REQ-PARTICIPANT;PARTSTAT=ACCEPTED;CN=School
Board;X-NUM-GUESTS=0:mailto:aliceisd.net_7hatmpq9uek3a1h6if0r0sn5bc@group.
calendar.google.com
RECURRENCE-ID;TZID=America/Chicago:20160808T183000
CREATED:20150715T183809Z
DESCRIPTION:
LAST-MODIFIED:20160718T155538Z
LOCATION:
SEQUENCE:1
STATUS:CONFIRMED
SUMMARY:Regular Board Meeting Modified
TRANSP:OPAQUE
END:VEVENT
BEGIN:VEVENT
DTSTART;TZID=America/Chicago:20150810T183000
DTEND;TZID=America/Chicago:20150810T210000
RRULE:FREQ=MONTHLY;UNTIL=20180709T233000Z;BYDAY=2MO
DTSTAMP:20160718T160226Z
UID:kpgr4590djmi89l3sv51gmalrc@google.com
ATTENDEE;CUTYPE=INDIVIDUAL;ROLE=REQ-PARTICIPANT;PARTSTAT=ACCEPTED;CN=School
Board;X-NUM-GUESTS=0:mailto:aliceisd.net_7hatmpq9uek3a1h6if0r0sn5bc@group.
calendar.google.com
CREATED:20150715T183809Z
DESCRIPTION:
LAST-MODIFIED:20160718T155538Z
LOCATION:
SEQUENCE:0
STATUS:CONFIRMED
SUMMARY:Regular Board Meeting
TRANSP:OPAQUE
END:VEVENT
END:VCALENDAR
58 changes: 58 additions & 0 deletions tests/cal/no_tzid.ics
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
BEGIN:VCALENDAR
PRODID:-//Google Inc//Google Calendar 70.9054//EN
VERSION:2.0
CALSCALE:GREGORIAN
METHOD:PUBLISH
X-WR-CALNAME:School Board
X-WR-CALDESC:
BEGIN:VTIMEZONE
BEGIN:DAYLIGHT
TZOFFSETFROM:-0600
TZOFFSETTO:-0500
DTSTART:19700308T020000
RRULE:FREQ=YEARLY;BYMONTH=3;BYDAY=2SU
END:DAYLIGHT
BEGIN:STANDARD
TZOFFSETFROM:-0500
TZOFFSETTO:-0600
DTSTART:19701101T020000
RRULE:FREQ=YEARLY;BYMONTH=11;BYDAY=1SU
END:STANDARD
END:VTIMEZONE
BEGIN:VEVENT
DTSTART;TZID=America/Chicago:20160808T180000
DTEND;TZID=America/Chicago:20160808T203000
DTSTAMP:20160718T160226Z
UID:kpgr4590djmi89l3sv51gmalrc@google.com
ATTENDEE;CUTYPE=INDIVIDUAL;ROLE=REQ-PARTICIPANT;PARTSTAT=ACCEPTED;CN=School
Board;X-NUM-GUESTS=0:mailto:aliceisd.net_7hatmpq9uek3a1h6if0r0sn5bc@group.
calendar.google.com
RECURRENCE-ID;TZID=America/Chicago:20160808T183000
CREATED:20150715T183809Z
DESCRIPTION:
LAST-MODIFIED:20160718T155538Z
LOCATION:
SEQUENCE:1
STATUS:CONFIRMED
SUMMARY:Regular Board Meeting Modified
TRANSP:OPAQUE
END:VEVENT
BEGIN:VEVENT
DTSTART;TZID=America/Chicago:20150810T183000
DTEND;TZID=America/Chicago:20150810T210000
RRULE:FREQ=MONTHLY;UNTIL=20180709T233000Z;BYDAY=2MO
DTSTAMP:20160718T160226Z
UID:kpgr4590djmi89l3sv51gmalrc@google.com
ATTENDEE;CUTYPE=INDIVIDUAL;ROLE=REQ-PARTICIPANT;PARTSTAT=ACCEPTED;CN=School
Board;X-NUM-GUESTS=0:mailto:aliceisd.net_7hatmpq9uek3a1h6if0r0sn5bc@group.
calendar.google.com
CREATED:20150715T183809Z
DESCRIPTION:
LAST-MODIFIED:20160718T155538Z
LOCATION:
SEQUENCE:0
STATUS:CONFIRMED
SUMMARY:Regular Board Meeting
TRANSP:OPAQUE
END:VEVENT
END:VCALENDAR
12 changes: 12 additions & 0 deletions tests/calendar_title.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
<?php
/**
* @author Roman Ozana <ozana@omdesign.cz>
*/
use Tester\Assert;

require_once __DIR__ . '/../vendor/autoload.php';
\Tester\Environment::setup();

$cal = new \om\IcalParser();
$results = $cal->parseFile(__DIR__ . '/cal/calendar_title.ics');
Assert::same('School Board', $cal->title);
13 changes: 13 additions & 0 deletions tests/no_tzid_value.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<?php
/**
* @author Marc Vachette <marc.vachette@gmail.com>
*/
use Tester\Assert;

require_once __DIR__ . '/../vendor/autoload.php';
\Tester\Environment::setup();

//some clean timezone
$cal = new \om\IcalParser();
$results = $cal->parseFile(__DIR__ . '/cal/no_tzid.ics');
Assert::same('America/New_York', $cal->timezone->getName());