jQuery FullCalendar 中的重复事件

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/15161654/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-26 14:31:05  来源:igfitidea点击:

Recurring Events in FullCalendar

javascriptjquerycalendarfullcalendarfullcalendar-3

提问by Junnel Gallemaso

I am using jQuery FullCalendar as my calendar used in my website for availability agenda.

我正在使用 jQuery FullCalendar 作为我的网站中用于可用性议程的日历。

Is there any functions/methods/options in fullcalendar that handles my recurring events by Days? For example, Monday only to time 7:00AM to 9:00 AM, tuesdays - 4:00PM to 9:00PM, something like that?

fullcalendar 中是否有任何功能/方法/选项可以按天处理我的重复事件?例如,星期一只到时间 7:00AM 到 9:00AM,星期二 - 4:00PM 到 9:00PM,诸如此类?

回答by DanielST

Simple Repeating Events

简单的重复事件

To add a simple alternative to those listed here, Fullcalendar now (somewhat) supports weekly recurring events. So if you only need something like: [Every Monday and Thursday from 10:00am to 02:00pm], you can use the following:

为了给此处列出的事件添加一个简单的替代方案,Fullcalendar 现在(在某种程度上)支持每周重复事件。因此,如果您只需要类似的东西:[Every Monday and Thursday from 10:00am to 02:00pm],您可以使用以下内容:

events: [{
    title:"My repeating event",
    start: '10:00', // a start time (10am in this example)
    end: '14:00', // an end time (2pm in this example)
    dow: [ 1, 4 ] // Repeat monday and thursday
}],

JSFiddle

JSFiddle

This is documented in Background eventsbut it works for regular events as well.

这在后台事件中有记录,但它也适用于常规事件。

Saving this to a database wouldn't be hard.

将其保存到数据库并不难。

Add some restrictions

添加一些限制

If you don't want them to repeat infinitely, you would need to add some start and end dates.

如果您不希望它们无限重复,则需要添加一些开始和结束日期。

So, in the DB:

所以,在数据库中:

  • Let the event shown above represent the parent record
  • Have another table with start/end dates.
  • Joined table example:
  • 让上面显示的事件代表父记录
  • 有另一个带有开始/结束日期的表格。
  • 连接表示例:

eventId  timeStart  timeEnd   dow    dateStart      dateEnd
     1      10:00    12:00  [1,4]  2015/03/01   2015/04/01  // Month of March
     1      10:00    12:00  [1,4]  2015/05/01   2015/06/01  // Month of May
     1      10:00    12:00  [1,4]  2016/01/01   2017/01/01  // Year of 2017

Pass this to the client as JSON:

将此作为 JSON 传递给客户端:

{ id:1, start:"10:00", end:"12:00", dow:[1,4],
  ranges[{start:"2015/03/01", end:"2015/04/01"},
         {start:"2015/05/01", end:"2015/06/01"},
         {start:"2016/01/01", end:"2017/01/01"},]
}

And client side, use fullcalendar's eventRenderto only render events when there are within one of the time ranges. Something like this should work:

在客户端,使用 fullcalendar 的eventRender仅在时间范围之一内呈现事件。这样的事情应该工作:

eventRender: function(event){
    return (event.ranges.filter(function(range){ // test event against all the ranges

        return (event.start.isBefore(range.end) &&
                event.end.isAfter(range.start));

    }).length)>0; //if it isn't in one of the ranges, don't render it (by returning false)
},

That's assuming your events are structured as:

假设您的事件结构如下:

var repeatingEvents = [{
    title:"My repeating event",
    id: 1,
    start: '10:00', 
    end: '14:00', 
    dow: [ 1, 4 ], 
    ranges: [{ //repeating events are only displayed if they are within at least one of the following ranges.
        start: moment().startOf('week'), //next two weeks
        end: moment().endOf('week').add(7,'d'),
    },{
        start: moment('2015-02-01','YYYY-MM-DD'), //all of february
        end: moment('2015-02-01','YYYY-MM-DD').endOf('month'),
    },/*...other ranges*/],
},/*...other repeating events*/];

JSFiddle

JSFiddle



Overnight

过夜

In case you want overnight repeating events (like here), just go over 24:00for the end time. For instance:

如果您想要一夜之间重复的事件(如这里),只需转到24:00结束时间即可。例如:

{
  start: '10:00', //starts at 10 on monday
  end:   '27:00', //24+3 is handled correctly.
  dow: [1]
}

JSFiddle

JSFiddle

回答by Juan Gonzales

Take a look at this site... http://fajitanachos.com/Fullcalendar-and-recurring-events/

看看这个网站... http://fajitanachos.com/Fullcalendar-and-recurring-events/

It offers alot of good insite on recurring events. FullCalendar does support recurring events in respect to the id. You can handle the events either server side or client side, but the preference would be server side. I will give you some ideas, but its not all inclusive. As I have learned recurring events are a pain to maintain.

它提供了很多关于经常性事件的良好现场。FullCalendar 确实支持与 id 相关的重复事件。您可以处理服务器端或客户端的事件,但首选是服务器端。我会给你一些想法,但它不是全部。据我所知,重复发生的事件很难维持。

If you wanted to handle them client side, you would have to loop through the frequency of the repeating event and the logic of which days. You would probably need to use the eventRender callback, then render each looped event using the options callback. The problem with this will be that you still have to save the recurring frequency and a logical operator for your frequency option in your database...

如果您想在客户端处理它们,则必须遍历重复事件的频率和哪几天的逻辑。您可能需要使用 eventRender 回调,然后使用选项回调渲染每个循环事件。这样做的问题是您仍然必须在数据库中为您的频率选项保存重复频率和逻辑运算符...

(column1:frequency=(int)8, column2:type=enum(a'b'c), a=daily, b=weekly, c=monthly etc).

(column1:frequency=(int)8, column2:type=enum(a'b'c), a=daily, b=weekly, c=monthly 等)。

...and then anytime you edited that event it would edit all of the events. If you needed delete just one event you would run into a series of issues within your logic and it could easily become a GIANT mess.

...然后无论何时您编辑该事件,它都会编辑所有事件。如果您只需要删除一个事件,您将在逻辑中遇到一系列问题,并且很容易变成一团糟。

The second option was to do all this server side. Creating two tables, one with the parent event, and the second with all its recurrences. In the parent table you would store the general information, such as a unique id, color, background color, title, allDay, isRecurring, frequency, type etc. In the child table, you would use the unique id from the parent table to associate each recurrence (keep in mind if you want to delete/edit individual events the child table rows need to have their own unique id as well and a column that labels which table it is located). When you add a recurring event, you need to add a enum field that labels whether or not it is a recurring event or not AKA...

第二种选择是在服务器端完成所有这些工作。创建两个表,一个包含父事件,第二个包含所有重复事件。在父表中,您将存储一般信息,例如唯一 id、颜色、背景颜色、标题、allDay、isRecurring、频率、类型等。在子表中,您将使用父表中的唯一 id 来关联每次重复(请记住,如果您想删除/编辑单个事件,子表行也需要有自己的唯一 ID 以及标记它所在表的列)。添加重复性事件时,您需要添加一个枚举字段,用于标记它是否是重复性事件,AKA...

column:recurring=enum('0','1')---true/false

列:recurring=enum('0','1')---真/假

... and then you need to add each recurrence, into the child table with its specific information like start and end etc. When you query the event you could either query from the parent and then if the event is recurring get those events associated in a second query, or you could use an INNER JOIN on table1.id=table2.parentID in one single query.

...然后您需要将每个重复添加到子表中,并带有其特定信息,例如开始和结束等。当您查询事件时,您可以从父表中查询,然后如果事件重复发生,则将这些事件关联到第二个查询,或者您可以在一个查询中对 table1.id=table2.parentID 使用 INNER JOIN。

As you can see, recurring event can get very detailed very fast, find out what logic you need and I hope this helps you or someone at least get started. Cheers.

如您所见,重复事件可以非常快速地变得非常详细,找出您需要的逻辑,我希望这可以帮助您或至少有人开始。干杯。

回答by Akshay Jindal

No need to make parent and child relationship here is the code that provide simple solution for recurring events in jquery Full calender use these below functions in your php file that you use further to call all your events.

无需在此处建立父子关系是为 jquery 中的重复事件提供简单解决方案的代码完整日历在您的 php 文件中使用以下函数,您将进一步使用这些函数来调用所有事件。

function render_fccalendar_events() {
        $_POST['start'] = strtotime('2013-05-01');
        $_POST['end'] = strtotime('2013-05-31');
        $start = date('Y-m-d',$_POST['start']);
        $end = date('Y-m-d', $_POST['end']);
        $readonly = (isset($_POST['readonly'])) ? true : false;    
        $events = fcdb_query_events($start, $end);       
        render_json(process_events($events, $start, $end, $readonly));
}

function process_events($events, $start, $end, $readonly) {
    if ($events) {
        $output = array();
        foreach ($events as $event) {
            $event->view_start = $start;
            $event->view_end = $end;
            $event = process_event($event, $readonly, true);
            if (is_array($event)) {
                foreach ($event as $repeat) {
                    array_push($output, $repeat);
                }
            } else {
                array_push($output, $event);
            }
        }
        return $output;
    }
}

function process_event($input, $readonly = false, $queue = false) {
    $output = array();
    if ($repeats = generate_repeating_event($input)) {
        foreach ($repeats as $repeat) {
            array_push($output, generate_event($repeat));
        }
    } else {
        array_push($output, generate_event($input));
    }

    if ($queue) {
        return $output;
    }
    render_json($output);
}


function generate_event($input) {
    $output = array(
        'id' => $input->id,
        'title' => $input->name,
        'start' => $input->start_date,
        'end' => $input->end_date,
        'allDay' => ($input->allDay) ? true : false,
        //'className' => "cat{$repeats}",
        'editable' => true,
        'repeat_i' => $input->repeat_int,
        'repeat_f' => $input->repeat_freq,
        'repeat_e' => $input->repeat_end
    );
    return $output;
}



function generate_repeating_event($event) {

    $repeat_desk = json_decode($event->repeat_desk);
    if ($event->repeat == "daily") {
        $event->repeat_int =0;
        $event->repeat_freq = $repeat_desk->every_day;
    }
    if ($event->repeat == "monthly") {
        $event->repeat_int =2;        
        $event->repeat_freq = $repeat_desk->every_month;
    }
    if ($event->repeat == "weekly") {
        $event->repeat_int =1;                
       $event->repeat_freq = $repeat_desk->every_weak;
    }
    if ($event->repeat == "year") {
        $event->repeat_int =3;                        
        $event->repeat_freq = $repeat_desk->every_year;
    }

    if ($event->occurrence == "after-no-of-occurrences") {
        if($event->repeat_int == 0){
            $ext = "days";
        }
        if($event->repeat_int == 1){
            $ext = "weeks";
        }
        if($event->repeat_int == 2){
            $ext = "months";
        }
        if($event->repeat_int == 3){
            $ext = "years";
        }
       $event->repeat_end =  date('Y-m-d',strtotime("+" . $event->repeat_int . " ".$ext));
    } else if ($event->occurrence == "no-end-date") {
        $event->repeat_end = "2023-04-13";
    } else if ($event->occurrence == "end-by-end-date") {
        $event->repeat_end = $event->end_date;
    }



    if ($event->repeat_freq) {

        $event_start = strtotime($event->start_date);
        $event_end = strtotime($event->end_date);
        $repeat_end = strtotime($event->repeat_end) + 86400;
        $view_start = strtotime($event->view_start);
        $view_end = strtotime($event->view_end);
        $repeats = array();

        while ($event_start < $repeat_end) {
            if ($event_start >= $view_start && $event_start <= $view_end) {
                $event = clone $event; // clone event details and override dates
                $event->start_date = date(AEC_DB_DATETIME_FORMAT, $event_start);
                $event->end_date = date(AEC_DB_DATETIME_FORMAT, $event_end);
                array_push($repeats, $event);
            }
            $event_start = get_next_date($event_start, $event->repeat_freq, $event->repeat_int);
            $event_end = get_next_date($event_end, $event->repeat_freq, $event->repeat_int);
        }
        return $repeats;
    }
    return false;
 }

function get_next_date($date, $freq, $int) {
    if ($int == 0)
        return strtotime("+" . $freq . " days", $date);
    if ($int == 1)
        return strtotime("+" . $freq . " weeks", $date);
    if ($int == 2)
        return get_next_month($date, $freq);
    if ($int == 3)
        return get_next_year($date, $freq);
}

function get_next_month($date, $n = 1) {
    $newDate = strtotime("+{$n} months", $date);
    // adjustment for events that repeat on the 29th, 30th and 31st of a month
    if (date('j', $date) !== (date('j', $newDate))) {
        $newDate = strtotime("+" . $n + 1 . " months", $date);
    }
    return $newDate;
}

function get_next_year($date, $n = 1) {
    $newDate = strtotime("+{$n} years", $date);
    // adjustment for events that repeat on february 29th
    if (date('j', $date) !== (date('j', $newDate))) {
        $newDate = strtotime("+" . $n + 3 . " years", $date);
    }
    return $newDate;
}

function render_json($output) {
    header("Content-Type: application/json");
    echo json_encode(cleanse_output($output));
    exit;
}


function cleanse_output($output) {
    if (is_array($output)) {
        array_walk_recursive($output, create_function('&$val', '$val = trim(stripslashes($val));'));
    } else {
        $output = stripslashes($output);
    }
    return $output;
}

function fcdb_query_events($start, $end) {
    global $wpdb;
    $limit = ($limit) ? " LIMIT {$limit}" : "";
    $result = $wpdb->get_results("SELECT id, name,start_date,end_date,repeat_desk,`repeat`,occurrence,occurrence_desk

                                        FROM " . 

$wpdb->prefix . "lgc_events
                                        WHERE (
                                        (start_date >= '{$start}' AND start_date < '{$end}')
                                        OR (end_date >= '{$start}' AND end_date < '{$end}')
                                        OR (start_date <= '{$start}' AND end_date >= '{$end}')
                                        OR (start_date < '{$end}' AND (`repeat`!= ''))


                            )
                                        ORDER BY start_date{$limit};");

    return return_result($result);
}


function return_result($result) {
    if ($result === false) {
        global $wpdb;
        $this->log($wpdb->print_error());
        return false;
    }
    return $result;
}

in the above code i used repeat_desk in which i store json code for repeat frequencyenter image description here

在上面的代码中,我使用了repeat_desk,其中我存储了重复频率的json代码在此处输入图片说明

and jquery to call your file

和 jquery 调用你的文件

 events:  {
                url: '<?php echo $lgc_plugindir; ?>includes/imagerotator.php',
                data: {
                    action: 'get_events'
                },
                type: 'POST'
            }

i used this for wordpress you can use this code as per your requirement

我将此用于 wordpress,您可以根据您的要求使用此代码

回答by Sergey Kharchishin

At the moment I'm doing project where I have FullCalendar and I have to do Recurring events. So this is my why how it's can be done. Hope this code help someone:)

目前我正在做项目,我有 FullCalendar 并且我必须做重复事件。所以这就是我为什么可以做到这一点。希望此代码可以帮助某人:)

I have next table in database:

我在数据库中有下一个表:

CREATE TABLE IF NOT EXISTS `app_ext_calendar_events` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `users_id` int(11) NOT NULL,
  `name` varchar(255) NOT NULL,
  `description` text,
  `start_date` int(11) NOT NULL,
  `end_date` int(11) NOT NULL,
  `event_type` varchar(16) NOT NULL,
  `is_public` tinyint(1) DEFAULT NULL,
  `bg_color` varchar(16) DEFAULT NULL,
  `repeat_type` varchar(16) DEFAULT NULL,
  `repeat_interval` int(11) DEFAULT NULL,
  `repeat_days` varchar(16) DEFAULT NULL,
  `repeat_end` int(11) DEFAULT NULL,
  `repeat_limit` int(11) DEFAULT NULL,
  PRIMARY KEY (`id`),
  KEY `idx_users_id` (`users_id`)
) ENGINE=MyISAM  DEFAULT CHARSET=utf8 AUTO_INCREMENT=18 ;

and I developed next php class to get events with repeat events:

我开发了下一个 php 类来获取具有重复事件的事件:

<?php

class calendar
{
  static public function get_events($date_from, $date_to,$calendar_type)
  {
    global $app_user;

    $list = array();

    $events_query = db_query("select * from app_ext_calendar_events where FROM_UNIXTIME(start_date,'%Y-%m-%d')>='" . $date_from . "' and  FROM_UNIXTIME(end_date,'%Y-%m-%d')<='" . $date_to . "' and event_type='" . $calendar_type . "' and users_id='" . db_input($app_user['id']) . "'");
    while($events = db_fetch_array($events_query))
    {
      $list[] = $events; 
    }

    if(count($repeat_events_list = calendar::get_repeat_events($date_to,$calendar_type)))
    {
      $list = array_merge($list,$repeat_events_list);
    }

    return $list;
  }

  public static function weeks_dif($start, $end)
  {
    $year_start = date('Y',$start);
    $year_end = date('Y',$end);

    $week_start = date('W',$start); 
    $week_end = date('W',$end);

    $dif_years = $year_end - $year_start;
    $dif_weeks = $week_end - $week_start;

    if($dif_years==0 and $dif_weeks==0)
    {
      return 0;
    }
    elseif($dif_years==0 and $dif_weeks>0)
    {
      return $dif_weeks;
    }
    elseif($dif_years==1)
    {
      return (42-$week_start)+$week_end;
    }
    elseif($dif_years>1)
    {
      return (42-$week_start)+$week_end+(($dif_years-2)*42);
    }


  }

  public static function months_dif($start, $end)
  {
    // Assume YYYY-mm-dd - as is common MYSQL format
    $splitStart = explode('-', date('Y-n',$start));
    $splitEnd = explode('-', date('Y-n',$end));

    if (is_array($splitStart) && is_array($splitEnd)) 
    {
        $startYear = $splitStart[0];
        $startMonth = $splitStart[1];
        $endYear = $splitEnd[0];
        $endMonth = $splitEnd[1];

        $difYears = $endYear - $startYear;
        $difMonth = $endMonth - $startMonth;

        if (0 == $difYears && 0 == $difMonth) 
        { // month and year are same
            return 0;
        }
        else if (0 == $difYears && $difMonth > 0) 
        { // same year, dif months
            return $difMonth;
        }
        else if (1 == $difYears) 
        {
            $startToEnd = 13 - $startMonth; // months remaining in start year(13 to include final month
            return ($startToEnd + $endMonth); // above + end month date
        }
        else if ($difYears > 1) 
        {
            $startToEnd = 13 - $startMonth; // months remaining in start year 
            $yearsRemaing = $difYears - 2;  // minus the years of the start and the end year
            $remainingMonths = 12 * $yearsRemaing; // tally up remaining months
            $totalMonths = $startToEnd + $remainingMonths + $endMonth; // Monthsleft + full years in between + months of last year
            return $totalMonths;
        }
    }
    else 
    {
      return false;
    }
  }

  public static function get_repeat_events($date_to,$calendar_type)
  {
    global $app_user;

    //convert date to timestamp
    $date_to_timestamp = get_date_timestamp($date_to);

    $list = array();

    //get all events that already started (start_date<=date_to)      
    $events_query = db_query("select * from app_ext_calendar_events where length(repeat_type)>0 and FROM_UNIXTIME(start_date,'%Y-%m-%d')<='" . $date_to . "' and  event_type='" . $calendar_type . "' and users_id='" . db_input($app_user['id']) . "'");
    while($events = db_fetch_array($events_query))
    {
      $start_date = $events['start_date'];

      //set repeat end      
      $repeat_end = false;
      if($events['repeat_end']>0)
      {
        $repeat_end = $events['repeat_end'];
      } 

      //get repeat events by type                       
      switch($events['repeat_type'])
      {
        case 'daily': 
            //check repeat events day bay day       
            for($date = $start_date; $date<=$date_to_timestamp; $date+=86400)            
            {
              if($date>$start_date)
              {
                $dif = round(abs($date-$start_date)/86400);

                if($dif>0)
                {  
                  $event_obj = $events;                                                
                  $event_obj['start_date'] = strtotime('+' . $dif . ' day',$event_obj['start_date']);                                                          
                  $event_obj['end_date'] = strtotime('+' . $dif . ' day',$event_obj['end_date']);

                  if(calendar::check_repeat_event_dif($dif,$event_obj,$repeat_end))
                  {                
                    $list[] = $event_obj;                
                  }
                }
              }
            }                                                          
          break;
        case 'weekly':  
            //check repeat events day bay day    
            for($date = $start_date; $date<=$date_to_timestamp; $date+=86400)            
            {
              if($date>$start_date)
              {
                //find days dif
                $dif = round(abs($date-$start_date)/86400);
                //find week dif
                $week_dif = calendar::weeks_dif($start_date, $date);

                if($dif>0 and (in_array(date('N',$date),explode(',',$events['repeat_days']))))
                {  
                  $event_obj = $events;                                                
                  $event_obj['start_date'] = strtotime('+' . $dif . ' day',$event_obj['start_date']);                                                          
                  $event_obj['end_date'] = strtotime('+' . $dif . ' day',$event_obj['end_date']);

                  if(calendar::check_repeat_event_dif($week_dif,$event_obj,$repeat_end))
                  {                
                    $list[] = $event_obj;                
                  }
                }
              }
            }                       

          break;            
        case 'monthly':                        
            /**
             *in calendar we display 3 month in one view
             *so we have to check difference for each month
             */

             //check 1                                      
            $date_to_timestamp2 = strtotime('-2 month',$date_to_timestamp);

            $dif =  calendar::months_dif($start_date, $date_to_timestamp2);

            if($dif>0)
            {  
              $event_obj = $events;                                                
              $event_obj['start_date'] = strtotime('+' . $dif . ' month',$event_obj['start_date']);                                                          
              $event_obj['end_date'] = strtotime('+' . $dif . ' month',$event_obj['end_date']);

              if(calendar::check_repeat_event_dif($dif,$event_obj,$repeat_end))
              {                
                $list[] = $event_obj;                
              }
            }

            //check 2
            $date_to_timestamp1 = strtotime('-1 month',$date_to_timestamp);

            $dif =  calendar::months_dif($start_date, $date_to_timestamp1);

            if($dif>0)
            {  
              $event_obj = $events;                                                
              $event_obj['start_date'] = strtotime('+' . $dif . ' month',$event_obj['start_date']);                                                          
              $event_obj['end_date'] = strtotime('+' . $dif . ' month',$event_obj['end_date']);

              if(calendar::check_repeat_event_dif($dif,$event_obj,$repeat_end))
              {                
                $list[] = $event_obj;                
              }
            }

            //check 3
            $dif =  calendar::months_dif($start_date, $date_to_timestamp);

            if($dif>0)
            {     
              $event_obj = $events;                                             
              $event_obj['start_date'] = strtotime('+' . $dif . ' month',$event_obj['start_date']);                                                          
              $event_obj['end_date'] = strtotime('+' . $dif . ' month',$event_obj['end_date']);

              if(calendar::check_repeat_event_dif($dif,$event_obj,$repeat_end))
              {                                
                $list[] = $event_obj;
              }
            }

          break;
        case 'yearly':                        
            $dif =  date('Y',$date_to_timestamp)-date('Y',$start_date);

            if($dif>0)
            {             
              $events['start_date'] = strtotime('+' . $dif . ' year',$events['start_date']);                                                          
              $events['end_date'] = strtotime('+' . $dif . ' year',$events['end_date']);

              if(calendar::check_repeat_event_dif($dif,$events,$repeat_end))
              {
                $list[] = $events;
              }
            }                                                                                               
          break;
      }            

    }

    return $list;

  }

  static public function check_repeat_event_dif($dif,$events,$repeat_end)
  {
    $check = true;

    if($dif>0)
    {
      //check interval
      if($dif/$events['repeat_interval']!=floor($dif/$events['repeat_interval'])) $check=false;            

      //check repeat limit
      if($events['repeat_limit']>0)            
      if(floor($dif/$events['repeat_interval'])>$events['repeat_limit']) $check=false;
    }
    else
    {
      $check=false; 
    } 

    //check repeat end date            
    if($repeat_end>0)
    {
      if($repeat_end<$events['start_date'])
      {
         $check=false;
      }
    }

    return $check;
  }  

}

function get_events get all events + recurring events in my way there are 4 type of recurring events: daily, weekly, monthly,yearly + there is repeat interval, repeat date end and repeat limit.

函数 get_events 以我的方式获取所有事件 + 重复事件有 4 种类型的重复事件:每天、每周、每月、每年 + 有重复间隔、重复日期结束和重复限制。

function get_repeat_events calculate difference for each type of event and include repeat event if exist.

函数 get_repeat_events 计算每种类型事件的差异,如果存在,则包括重复事件。

note: function db_query() can be replace to myslq_query or something else

注意:函数 db_​​query() 可以替换为 myslq_query 或其他东西

to prepare events to FullCalendar I'm using next code

准备事件到 FullCalendar 我正在使用下一个代码

$list = array();        

  foreach(calendar::get_events($_GET['start'],$_GET['end'],'personal') as $events)
  {
    $start = date('Y-m-d H:i',$events['start_date']);
    $end = date('Y-m-d H:i',$events['end_date']);


    $list[] = array('id' => $events['id'],
                  'title' => addslashes($events['name']),
                  'description' => str_replace(array("\n\r","\n","\r"),'<br>',$events['description']),
                  'start' => str_replace(' 00:00','',$start),
                  'end' => str_replace(' 00:00','',$end),
                  'color'=> $events['bg_color'],                      
                  'allDay'=>(strstr($start,'00:00') and strstr($end,'00:00')),
                  'url' => url_for('ext/calendar/personal_form','id=' . $events['id'])                      
                  );      
  }

  echo json_encode($list);

回答by tohood87

This seemed to work quite nicely within the eventRender: function(event, element){}

这似乎在 eventRender 中工作得很好:function(event, element){}

            EXAMPLE JSON:
            var json = [{title: "All Day Event",
              start: "2015-12-22T00:00",
              end: "2015-12-22T23:55",
              dow: [2,4],
              recurstart: moment("2015-12-22").startOf("week"),
              recurend: moment("2015-12-22").endOf("week").add(1,'w')},{
              title: "Long Event",
              start: "2015-12-21T00:00",
              end: "2015-12-24T23:55",
              recurstart: moment("2015-12-21").startOf("month"),
              recurend: moment("2015-12-24").endOf("month"),
            }];

            eventRender: function(event, element){
            var theDate = moment(event.start).format("YYYY-MM-DD");
            var startDate = event.recurstart;
            var endDate = event.recurend;

            if (startDate < theDate && theDate < endDate) {
                console.log(theDate);
                }
            else {
                return event.length>0;
            }
            }, /* End eventRender */

1) Set a Start/End date & time in the JSON.

1) 在 JSON 中设置开始/结束日期和时间。

2) Create two custom recur Start and recur Ends in the JSON.

2)在JSON中创建两个自定义recur Start和recur Ends。

3) Use moment.js to create the recur durations: http://momentjs.com/docs/#/durations/.

3) 使用 moment.js 创建重复持续时间:http://momentjs.com/docs/#/durations/ 。

4) Recur Start uses the (start:) date to pinpoint the start of the week.

4) Recur Start 使用 (start:) 日期来确定一周的开始。

5) Recur End uses (end:) date to pinpoint the end of the week + adding 1 week.

5) Recur End 使用 (end:) 日期来确定一周的结束时间 + 增加 1 周。

6) Adding 1, 2, 3 weeks can create the recur limit.

6) 添加 1、2、3 周可以创建重复限制。

7) Adding another part of the JSON called (recurlimit:"") could manage the recur limit.

7) 添加名为 (recurlimit:"") 的 JSON 的另一部分可以管理重复限制。

8) Using variables within the eventRender - set the date my example uses (theDate) which is moment(event.start). It's important to format this correctly so that the start/ end/ recurstart etc all match formats i.e (YYYY-MM-DD) http://momentjs.com/docs/#/displaying/format/.

8) 在 eventRender 中使用变量 - 设置我的示例使用的日期 (theDate),即 moment(event.start)。正确格式化很重要,以便开始/结束/ recurstart 等所有格式都匹配,即 (YYYY-MM-DD) http://momentjs.com/docs/#/displaying/format/

9) Variable for the custom recurstart

9) 自定义 recurstart 的变量

10) Variable for the custom recurend

10) 自定义递归的变量

11) Use an IF statement to see weather the (theDate) falls between (recurstart) & (recurend) - log result

11) 使用 IF 语句查看 (theDate) 介于 (recurstart) 和 (recurend) 之间的天气 - 日志结果

12) Use ELSE statement to return the length>0 to hide other events that don't fall within that parameter.

12) 使用 ELSE 语句返回 length>0 以隐藏不属于该参数的其他事件。

13) Non recurring events must have moment("match start date").startOf("month") & moment("match start date").endOf("month") otherwise they won't be visible.

13) 非重复事件必须有 moment("match start date").startOf("month") & moment("match start date").endOf("month") 否则它们将不可见。

回答by John

For people who have more complex recurring events than what FullCalendar can handle builtin (see slicedtoad's answer), you can use rSchedule.

对于拥有比 FullCalendar 可以处理的内置事件更复杂的重复事件的人(请参阅 slicedtoad 的答案),您可以使用rSchedule

For example, Monday only to time 7:00AM to 9:00 AM, tuesdays - 4:00PM to 9:00PM

例如,仅周一至上午 7:00 至上午 9:00,周二至下午 4:00 至晚上 9:00

import { Schedule } from '@rschedule/rschedule';
import { StandardDateAdapter } from '@rschedule/standard-date-adapter';

const mondayDate = new Date(2019, 6, 15);
const tuesdayDate = new Date(2019, 6, 16);

const schedule = new Schedule({
  // add specific dates
  dates: [
    new StandardDateAdapter(mondayDate, {duration: 1000 * 60 * 60 * 2})
  ],
  // add recurrence rules
  rrules: [{
    start: tuesdayDate,
    duration: 1000 * 60 * 60 * 5, // duration is expressed in milliseconds
    frequency: 'WEEKLY'
  }],
});

const firstFiveEvents = schedule
  .occurrences({ take: 5 })
  .toArray()
  .map(adapter => 
    ({title: 'My event title', start: adapter.date, end: adapter.end})
  );

// You can then pass `firstFiveEvents` to fullcalendar for rendering

rSchedule also supports moment/ luxon, as well as timezones. For more information, you can check out the rSchedule docs.

rSchedule 还支持moment/luxon以及时区。有关更多信息,您可以查看rSchedule 文档

回答by leela

To handle complex recurring rules, we should use iCal's rrule implementation libraries. We have JS library (rrule). FullCalendar now also supports rrule plugin.

为了处理复杂的重复规则,我们应该使用 iCal 的 rrule 实现库。我们有JS 库 (rrule)。FullCalendar 现在还支持rrule 插件

回答by user3401445

There is now a plugin that will do what you want: http://momentjs.com/docs/#/plugins/recur/

现在有一个插件可以做你想做的事:http: //momentjs.com/docs/#/plugins/recur/