I'm doing it wrong somehow. I'm getting tripped up on timezones with Fullcalendar. I've tried setting ignoreTimezone to true and false, but it doesn't seem to matter. It's in the code below in two places because I wasn't sure from the doc where it goes.
My data source is a hidden form field. Data that goes out of FullCalendar is adjusted by adding 5 hours (CDT). Data that goes in to FullCalendar isn't adjusted by removing 5 hours.
On the back-end, I'm just saving and returning the JSON string without processing it (or even decoding it)
Page Load:
Data In: Empty, no data
Data Edit: drag from noon to 2pm (CDT), then submit form
Data Out: Use clientEvent to get data, and JSON.stringify to put into form field.
[{"id":6844,"title":"Open","start":"2011-04-19T17:00:00.000Z","end":"2011-04-19T19:00:00.000Z","allDay":false}]
Page Load (after submitting form):
Data In: Use JSON.parse to load data from hidden form field. This is the incoming data, but the event is shifted to 5pm (CDT) in the control.
[{"id":6844,"title":"Open","start":"2011-04-19T17:00:00.000Z","end":"2011-04-19T19:00:00.000Z","allDay":false}]
Data Out: Without changing the control, it's now:
[{"id":6844,"title":"Open","start":"2011-04-19T22:00:00.000Z","end":"2011-04-20T00:00:00.000Z","allDay":false}]
I setup the Fullcalendar like this:
// Fullcalendar for business hours page
jQuery(document).ready(function() {
jQuery('#edit-submit').bind("click", business_hours_set);
jQuery('#edit-preview').bind("click", business_hours_set);
jQuery('#calendar').fullCalendar({
// configure display
header: {
left: '',
center: '',
right: ''
},
ignoreTimezone: false,
defaultView: 'agendaWeek',
allDaySlot: false,
firstHour: 8,
// configure selection for event creation
selectable: true,
selectHelper: true,
select: business_hours_add,
// configure data source
editable: true,
eventSources: [
{
events: jQuery.parseJSON(jQuery('#fullcalendar_data').val()),
color: '#992B0A',
textColor: 'white',
ignoreTimezone: false
}
],
// configure editing
eventClick: function(calEvent) {
business_hours_delete(calEvent.id);
}
});
alert(jQuery('#fullcalendar_data').val());
});
function business_hours_add(startDate, endDate) {
var calendar = jQuery('#calendar');
var newid = Math.ceil(Math.random()*64000);
calendar.fullCalendar('renderEvent',
{
id: newid,
title: "Open",
start: startDate,
end: endDate,
allDay: false
},
true // make the event "stick"
);
calendar.fullCalendar('unselect');
}
var business_hours_selectedId = -1;
function business_hours_delete(id) {
business_hours_selectedId = id;
jQuery( "#dialog-confirm" ).dialog({
resizable: false,
height:160,
modal: true,
buttons: {
"Yes, delete!": function() {
calendar = jQuery('#calendar');
calendar.fullCalendar( 'removeEvents', business_hours_selectedId);
jQuery( this ).dialog( "close" );
},
Cancel: function() {
jQuery( this ).dialog( "close" );
}
}
}, id);
}
function business_hours_set() {
var data = jQuery('#calendar').fullCalendar( 'clientEvents' );
// data is cyclical. Create a new data structure to stringify.
var ret = [];
for(var i=0; i<data.length; i++) {
var datum = {
id: data[i].id,
title: data[i].title,
start: data[i].start,
end: data[i].end,
allDay: data[i].allDay
}
ret[i] = datum;
}
// stringify and return
jQuery('#fullcalendar_data').val(JSON.stringify(ret));
alert(JSON.stringify(ret));
}
What am I doing wrong?
Thanks in advance, Mike
You are serializing CDT-adjusted dates as UTC dates (thus getting a 5 hour shift) so when they are read back in they get re-adjusted to CDT, and so on..
Because there isn't a way to set a timezone on JS date objects, Fullcalendar represents them internally as UTC dates, but adjusts for timezone offset on input time.
$.fullCalendar.parseISO8601('2011-04-19T17:00:00.000-05:00');
// Tue Apr 19 2011 22:00:00 GMT+0000 (GMT) <-- note time shift
This is why, when you serialize to JSON, you get a string with the "Zulu" (UTC) timezone:
var dt = $.fullCalendar.parseISO8601('2011-04-19T17:00:00.000-05:00');
JSON.stringify( dt ); // "2011-04-19T22:00:00.000Z"
You need the date back to your timezone. It doesn't look like Fullcalendar has this so you'll need to to the work:
// detect local timezone offset
var localoffset = (new Date()).getTimezoneOffset();
// "unadjust" date
ret = new Date( ret.valueOf() + (localoffset * 60 * 1000) );
// serialize
function pad (n) { return String(n).replace(/^(-?)(\d)$/,'$10$2'); }
JSON.stringify( ret )
// replace Z timezone with current
.replace('Z', pad(Math.floor(localoffset / 60))+':'+ pad(localoffset % 60));
// should result in something like: "2011-04-21T19:00:00.000-05:00"
There may be a better way of solving this using Fullcalendar but I am not familiar with it.
Code is untested: I live in GMT with no-DST and don't really want to mess with my system just to see it work (YMMW). :-)
I had the same timeshift in FullCalendar. Check out your timezone on server, when I changed it to my own it help me. You may try to do it in few ways:
On serer:
[root@mx ~]# mv /etc/localtime /etc/localtime.old
[root@mx ~]# ln -s /usr/share/zoneinfo/Europe/Moscow /etc/localtime
Or in PHP script (which returns JSON string):
date_default_timezone_set('Europe/Moscow');
P.S. Don't forget to change "Europe/Moscow" to your values :-)
Then you have to set your valid time in new time zone ("date" command);
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With