Fullcalendar和时区。 救命,我做错了

我不知何故做错了。 我正在使用Fullcalendar绊倒时区。 我已经尝试将ignoreTimezone设置为true和false,但似乎并不重要。 它在下面的代码中有两个地方,因为我不确定它来自哪个文档。

我的数据源是隐藏的表单字段。 超出 FullCalendar数据通过添加5小时(CDT)进行调整。 进入FullCalendar数据不会通过删除5小时来调整。

在后端,我只是保存并返回JSON字符串而不处理它(甚至解码它)

 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}] 

我像这样设置Fullcalendar

 // 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)); } 

我究竟做错了什么?

先谢谢你,迈克

您正在将CDT调整的日期序列化为UTC日期(因此获得5小时的class次),因此当他们被回读时,他们会重新调整为CDT,依此类推。

因为没有办法在JS日期对象上设置时区,所以Fullcalendar在内部将它们表示为UTC日期,但在输入时间调整时区偏移量。

 $.fullCalendar.parseISO8601('2011-04-19T17:00:00.000-05:00'); // Tue Apr 19 2011 22:00:00 GMT+0000 (GMT) <-- note time shift 

这就是为什么当你序列化为JSON时,你得到一个带有“Zulu”(UTC)时区的字符串:

 var dt = $.fullCalendar.parseISO8601('2011-04-19T17:00:00.000-05:00'); JSON.stringify( dt ); // "2011-04-19T22:00:00.000Z" 

您需要将日期返回到您的时区。 它看起来不像Fullcalendar,所以你需要做的工作:

 // 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" 

使用Fullcalendar可能有更好的解决方法,但我不熟悉它。

代码是未经测试的:我生活在没有DST的GMT中,并且真的不想弄乱我的系统只是为了看它工作(YMMW)。 🙂

我在FullCalendar中有相同的时间转换。 在服务器上查看你的时区,当我把它更改为我自己的时候它帮助我。 您可以尝试以几种方式执行此操作:

在serer上:

[root @mx~] #mv / etc / localtime /etc/localtime.old

[root @mx~] #ln -s / usr / share / zoneinfo / Europe / Moscow / etc / localtime

或者在PHP脚本中(返回JSON字符串):

date_default_timezone_set( ‘欧洲/莫斯科’);

PS别忘了将“欧洲/莫斯科”改为你的价值观:-)

然后你必须在新的时区设置你的有效时间(“日期”命令);