.ics export from Google calendar has wrong time - php

Using PHP,mysql, i am trying to export/import calendar data from/to Google calendar.
The importing (to Google) works fine. I can export data from my mysql table and create an ics file then import it into Google Calendar, using a specific timezone.
The problem is when i am exporting the data... Google changes the timezone for every event. I'll give an example.
When i am importing the data to Google Calender, a typical event looks like this:
BEGIN:VEVENT
UID:20
DTSTAMP:20160328T222128
DTSTART:20160328T033000
DTEND:20160328T043000
LOCATION:
DESCRIPTION:My description here
SUMMARY:Event number 3
END:VEVENT
The StartTime is 033000 and EndTime is 043000. Everything is fine, i see an event starting at 3:30am and ending at 4:30am.
When i am exporting my calendar from Google this event looks like this:
BEGIN:VEVENT
DTSTART:20160328T003000Z
DTEND:20160328T013000Z
DTSTAMP:20160328T194501Z
UID:20
CREATED:20160328T224357Z
DESCRIPTION:My description here
LAST-MODIFIED:20160328T194410Z
LOCATION:
SEQUENCE:0
STATUS:CONFIRMED
SUMMARY:Event number 3
TRANSP:OPAQUE
END:VEVENT
StartTime 003000 EndTime 013000
Both .ics files have X-WR-TIMEZONE:Europe/Athens
Why on earth is Google sending me back Zulu time, instead of what i am seeing in the calendar ?
I dont want to handle timezones. This means if a person from the Usa uploads an .ics file to the custom calendar i am making, it will insert wrong times in the database. Is it possible, Google Calendar to export exactly the hours a person sees in his calendar?
If i cant avoid this, what is the easiest way to convert this Z time into the proper time ? (the time that person sees in Google Calendar)
Thanks!

I assume that, since you are able to insert the date/times into a database, you are able to parse the format of DTSTART. If not, I recommend taking a look at sabre/vobject for a full-on iCalendar parser.
So after parsing DTSTART, make sure you parse this into a php DateTime object. This object makes it really easy to convert to different timezones:
$dt = new \DateTime($input);
$dt->setTimeZone(new DateTimeZone('Europe/Athens'));
After that, your $dt contains your start time, converted to your timezone.
Here's an example with vobject:
$cal = Sabre\VObject\Reader::read($iCalendarData);
// DTSTART property
$dtstart = $cal->VEVENT->DTSTART;
// Turn into DateTime object
$dateTime = $dtstart->getDateTime();
// Convert to your timezone
$newDateTime = $dateTime->setTimeZone('Europe/Athens');
Disclaimer: I'm the main author for vobject.

Related

iCalendar exclude date range

I am working on school timetables system and currently developing a PHP script that would allow exporting the data in iCalendar (.ics) format. The target use-case of exporting the data would be importing it into Google Calendar.
Since there are holidays inbetween the semesters in our school (specified by start and end date), what would be the best way to exclude the holidays from the iCalendar recurrence rule (RRULE)?. Keep in mind that there can be many different schedules in one export.
I did try using EXDATE;VALUE=DATE:YYYYMMDD,YYYYMMDD,YYYYMMDD... with all holiday days, but Google Calendar didn't exclude the dates, probably because schedules also have time attached and therefore they don't match.
I'll also provide the data in iCalendar format with one of the events, with holiday days excluded one by one (the one that didn't work)
BEGIN:VCALENDAR
PRODID:-//Gregor Eesmaa/NONSGML Poska timetables//ET
VERSION:2.0
METHOD:PUBLISH
BEGIN:VEVENT
UID:schedule-1442#jpg.tartu.ee
SUMMARY:French
DESCRIPTION:
LOCATION:Room 210
DTSTART:20151215T123000Z
DTEND:20151215T134500Z
RRULE:FREQ=WEEKLY;UNTIL=20160211;INTERVAL=1;BYDAY=TU
EXDATE;VALUE=DATE:20151223,20151224,20151225,20151226,20151227,20151228,20151229,20151230,20151231,20160101,20160102,20160103,20160104,20160105,20160106,20160107,20160108,20160109,20160110,20160319,20160320,20160321,20160322,20160323,20160324,20160325,20160326,20160327,20160415,20160416,20160417,20160418,20160607,20160608,20160609,20160610,20160611,20160612,20160613,20160614,20160615,20160616,20160617,20160618,20160619,20160620,20160621,20160622,20160623,20160624,20160625,20160626,20160627,20160628,20160629,20160630,20160701,20160702,20160703,20160704,20160705,20160706,20160707,20160708,20160709,20160710,20160711,20160712,20160713,20160714,20160715,20160716,20160717,20160718,20160719,20160720,20160721,20160722,20160723,20160724,20160725,20160726,20160727,20160728,20160729,20160730,20160731,20160801,20160802,20160803,20160804,20160805,20160806,20160807,20160808,20160809,20160810,20160811,20160812,20160813,20160814,20160815,20160816,20160817,20160818,20160819,20160820,20160821,20160822,20160823,20160824,20160825,20160826,20160827,20160828,20160829,20160830,20160831
LAST-MODIFIED:20160102T123758Z
DTSTAMP:20160107T232137Z
END:VEVENT
END:VCALENDAR
If DTSTART is a date-time value then EXDATEs must also be date-times. I propose you append T123000Z to each of your EXDATEs to make them actually point to valid instance starts. They will then get correctly excluded.
Based on this other SO issue, it seems you're not setting any excluded date in EXDATE. EXDATE can be set to DATE, based on the RFC 5545 specificaiton.
Based on the answer on the other issue, your EXDATE should have been
EXDATE:20151223,20151224,20151225,20151226,20151227,20151228,20151229,20151230,20151231,20160101,20160102,20160103,20160104,20160105,20160106,20160107,20160108,20160109,20160110,20160319,20160320,20160321,20160322,20160323,20160324,20160325,20160326,20160327,20160415,20160416,20160417,20160418,20160607,20160608,20160609,20160610,20160611,20160612,20160613,20160614,20160615,20160616,20160617,20160618,20160619,20160620,20160621,20160622,20160623,20160624,20160625,20160626,20160627,20160628,20160629,20160630,20160701,20160702,20160703,20160704,20160705,20160706,20160707,20160708,20160709,20160710,20160711,20160712,20160713,20160714,20160715,20160716,20160717,20160718,20160719,20160720,20160721,20160722,20160723,20160724,20160725,20160726,20160727,20160728,20160729,20160730,20160731,20160801,20160802,20160803,20160804,20160805,20160806,20160807,20160808,20160809,20160810,20160811,20160812,20160813,20160814,20160815,20160816,20160817,20160818,20160819,20160820,20160821,20160822,20160823,20160824,20160825,20160826,20160827,20160828,20160829,20160830,20160831
Hope this helps!
I posted this question looking for a solution that would exclude whole ranges. After careful consideration, I decided to do this properly, by excluding only the date-times where the event would actually take place. This decreased the file size of the export three fold.
I also added timezone information as recommended for using RRULE. Now the French lesson event would look like this:
BEGIN:VEVENT
UID:schedule-1442#jpg.tartu.ee
SUMMARY:French
DESCRIPTION:
LOCATION:Room 210
DTSTART;TZID=Europe/Tallinn:20151215T143000
DTEND;TZID=Europe/Tallinn:20151215T154500
RRULE:FREQ=WEEKLY;UNTIL=20160211;INTERVAL=1;BYDAY=TU
EXDATE;TZID=Europe/Tallinn:20151229T143000,20160105T143000
CREATED:20160102T123758Z
LAST-MODIFIED:20160102T123758Z
DTSTAMP:20160108T115122Z
END:VEVENT

Google Calendar Feed

I am trying to add a Google calendar to a website I'm making that the client will be able to update themselves. I found this: http://mikeclaffey.com/google-calendar-into-html/ which has been quite helpful, but I am a bit stuck.
The website I am building is using PHP template and the page contents is contained within the $content variable. Here is the link I'm working on: http://victoriasawyer.com/AmosTheTransparent.
The calendar feed is the top one of the two lists of Tour Dates. I would like the top one to look similar to the bottom one. The same would be ideal but not necessary.
The biggest issue I'm having is with the start date and time. In the title of the event I would like just the date to show (preferably like 10/03/14) not the time. I have figured out how to display just the time separately without issue. Is there some way to change the date format?
The other issue I'm having is the order that the events are appearing. I would like the events to show with the soonest one first in the list and the furthest one last in the list. I added the additional parameters as instructed in the tutorial (orderby=starttime and sortorder=ascending) but they do not display correctly.
The url I am using is: https://www.google.com/calendar/feeds/qmfadhgtq2kmabsi3dlb456v98%40group.calendar.google.com/public/full?orderby=starttime&sortorder=ascending&futureevents=true&alt=json. Is there something I can adjust or add to fix the order?
Any help will be much appreciated (even if you can recommend an alternative. It just needs to be customizable, and so far this seems to be the best option I have found).
You can use PHP's DateTime class like this:
$date = new DateTime('Sun Nov 16 2014 00:30:00 GMT+0000');
echo $date->format('Y-m-d');
You can then use the predefined formats in PHP which are listed here to format it into whatever style you like.
echo $date->format('d/m');
echo $date->format('d/m/Y');

Working with unix timestamps and timezones

Timezones and timestamps confuses me so I'm hoping someone can answer my questions :)
Lets say I have a Python script that parses an RSS feed, converts the date value into a timestamp using the following code and stores it in a database:
article_date = parse(article.published).strftime('%s') if hasattr(article, 'published') else round(time.time())
Now when I retrieve that record from the db in PHP, and I run the following code, does PHP assume the timestamp was UTC-0 and automatically offsets the timezone to Eastern time?
date_default_timezone_set('America/New_York');
echo date('Y-m-d H:i:s',$timestamp);
I'm seeing weird issues with my dates, so I'm wondering if someone can help me out with advice on how to properly convert and store rss feed timestamps. I can across this line of code somewhere so should I put this at the top of my script?
os.environ['TZ'] = 'Europe/London'
If you want to set your timezones and keep them aligned in PHP and in Python, then your PHP code is completely correct and for python you need to apply the following:
os.environ['TZ'] = 'America/New_York'
time.tzset()
before you call strftime()
That should make sure you store the time in the same zone you're trying to retrieve it.
Note: tzset() is a Unix-only function.

Importing iCal calendar into MySQL database

I've searched through a lot of sites, but all of them do in reverse already what I've achieved , but not what I need.
I need a way to import data FROM ICAL into a MySQL database, actually just one table and a few columns in a WordPress database. But I'm ignoring WordPress (as it messed up my export) and using direct database connection.
Can any of you help me achieve this? Is importing ICAL so obviously simple that I'm thinking way too difficult?
My ICAL docs setup:
BEGIN:VCALENDAR
VERSION:2.0C
ALSCALE:GREGORIAN
METHOD:PUBLISH
X-WR-TIMEZONE:Europe/Amsterdam
BEGIN:VEVENT
DTSTART:20120113T133300
DTEND:20120223T165900
DTSTAMP:20120118T093232
SEQUENCE:0
STATUS:CONFIRMED
SUMMARY:29007/on/on
TRANSP:OPAQUE
END:VEVENT
END:VCALENDAR
From "BEGIN:" to "END:" also gets repeated when a user exports multiple events. In status I've currently (will change to something else) a post ID, whether or not the event is "on"(true) meaning to be displayed (in order to preserve data of past events), and the 2nd "on" tells the front end whether an event is an all-day event (from 00:00 until 23:59).
So again the question, how could I import this, using just a few lines of code, not a plugin or some other external code, into my table in a WP database?
Thanks in advance!
P.s. -> I just made this profile, not here to leech knowledge, before I created the profile just now I've also answered questions anonymously and corrected some answers in which I spotted mistakes.
The next is not a universal tool, but may suit your needs
iCal Export/Import Tool for dhtmlxScheduler

How to create a Calendar in Php?

How can I create a calendar in PHP?
Today should be in bold. How could it be coded?
You can try dhtml Calendar, or maybe Yahoo UI's Calendar.
PHP: date should give you everything you need.
Then, format everything in a table.
Firstly, start by capturing your requirements (should it handle month browsing, should it show a week at a time, etc.) - this should let you derive a functional spec of sorts, which should guide you when actually writing the component/page/application
If you mean: "how to show a date picker on your web page from PHP", the answer is to use some default JavaScript library for it. E.g. Dojo or jQuery.

Categories