Полный календарь и часовые пояса. Помогите, я делаю это неправильно

#javascript #jquery #timezone #fullcalendar

#javascript #jquery #Часовой пояс #полный календарь

Вопрос:

Я как-то неправильно это делаю. Я запутался в часовых поясах с 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));
}
  

Что я делаю не так?

Заранее спасибо, Майк

Комментарии:

1. майк, у тебя есть решение для этого, я тоже сталкиваюсь с той же проблемой

Ответ №1:

Вы сериализуете даты с поправкой на CDT как даты UTC (таким образом, получая 5-часовой сдвиг), поэтому, когда они считываются обратно, они перенастраиваются на 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, но я с ним не знаком.

Код непроверен: я живу по Гринвичу без перехода на летнее время и на самом деле не хочу возиться со своей системой только для того, чтобы посмотреть, как она работает (YMMW). 🙂

Комментарии:

1. Привет, спасибо за ответ. Я понимаю (немного) проблему с часовым поясом, но не поведение FullCalendar. Данные, которые я помещаю в полный календарь, — это время Зулу: например [{«id»:6844,»title»:»Open»,»start»:»2011-04-19T17:00:00.000Z»,»end»:»2011-04-19T19:00:00.000Z»,»allDay»:false}] Но, похоже, это также настраивает это на 5 часов! Переносим его на начало в 22:00. По сути, я беру данные, которые получаю из полного календаря, и загружаю их обратно, в результате чего происходит этот 5-часовой сдвиг.

Ответ №2:

У меня был такой же сдвиг во времени в 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 (‘Европа / Москва’);

P.S. Не забудьте изменить «Европа / Москва» на ваши значения 🙂

Затем вы должны установить свое действительное время в новом часовом поясе (команда «дата»);