【问题标题】:Sorting array of events based on dates in PHP基于PHP中的日期对事件数组进行排序
【发布时间】:2013-04-29 16:44:50
【问题描述】:

我正在从 Google 日历导入事件并对其进行解析以在其他地方显示。我被困在跨越一系列日期的事件上。例如:

活动 1
日期:2013 年 4 月 29 日 - 2013 年 5 月 3 日

活动 2
日期:5/01/2013 - 5/03/2013

活动 3
日期:5/03/2013 - 5/06/2013

当我显示 2013 年 3 月 5 日的事件时,我需要显示事件 1、2 和 3。
到目前为止,我的计划是生成一个 DatePeriod,其中包含事件开始日期和结束日期之间的所有日期,然后遍历它,在日期键下添加事件信息。换句话说,我将有一个日期数组,每个日期都包含一个事件数组。
这就是我到目前为止所拥有的。我认为我走在正确的道路上,但任何帮助将不胜感激。谢谢。

public function groupEvents()
            {
                foreach($this->events as $event)
                {
                    // Date is in the format of "Mon Apr 29, 2013 to Wed May 1, 2013".
                    if(preg_match_all("/\w{3} \w{3} \d{0,2}. \d{4}/", $event->getDate(), $matches))
                    {
                        // If there is more than one match then the event spans multiple days.
                        if(count($matches[0] > 1))
                        {
                            // Following line grabs the first date in the format of "Apr 29 2013"
                            $bDate = substr($matches[0][0],4,6) . substr($matches[0][0],11);
                            // Following line grabs the last date in the format of "May 1,2013"
                            $eDate = substr($matches[0][1],4,6) . substr($matches[0][1],11);
                            // Create a new DateTime based on the beginning date
                            $begin = new DateTime($bDate);
                            // Create a new DateTime based on the ending date
                            $end = new DateTime($eDate);
                            // Interval of 1 day.
                            $interval = new DateInterval('P1D');
                            // Create a DatePeriod of all dates between the beginning and end dates
                            $period = new DatePeriod($begin,$interval,$end);


                            foreach($period as $d)
                            {
                                // Problems start...
                                $this->newList[$d] = array($d => $newEvent);
                            }
                        }
                    }
                }
            }

【问题讨论】:

  • 您不能使用事件列表方法的timeMaxtimeMin 参数来选择特定日期的事件吗?
  • 每个事件都应该有一个 start_date 和 end_date(可能 1 天都一样),然后用 WHERE mydate BETWEEN start_date AND end_date 进行搜索。简单的
  • 您也可以使用$twodates=explode(' to ', $date_string); 来拆分日期。然后$datestart=strtotime($twodates[0]); 创建一个date("Y-m-d", $datestart) 可以使用的时间戳。
  • 我知道开始和结束是什么。我使用它们来设置 DatePeriod。我只是无法设置基于日期的所有事件的数组。数组的第一个维度将包含天数,而第二个维度包含这些日期下的事件。

标签: php date sorting


【解决方案1】:

这将遍历事件并回显匹配事件(您需要创建数组)。

function groupEvents($mydate='2013-03-05')
{
    foreach($this->events as $event)
    {
        // Date is in the format of "Mon Apr 29, 2013 to Wed May 1, 2013".
        $event_date=$event->getDate();
        // check if TO exists in the event date
        if(stristr($event_date, ' to '))
        {
            $twodates=explode(" to ", $event_date);
            $start_date=strtotime($twodates[0]);
            $end_date=strtotime($twodates[1]);

            if( (date("Y-m-d", $start_date)<=$mydate) && ($mydate<=date("Y-m-d", $end_date)) )
            {
                // assuming $event->getName() will get the name of the event
                echo 'Event '.$event->getName().' '.date("m/d/Y", $start_date).' to '.date("m/d/Y", $start_date);
            }
        }
        else
        {
            $start_date=strtotime($event_date);

            if(date("Y-m-d", $start_date)==$mydate)
            {
                // assuming $event->getName() will get the name of the event
                echo 'Event '.$event->getName().' '.date("m/d/Y", $start_date);
            }
        }
    }
}

【讨论】:

    【解决方案2】:

    我的方法是首先将日历文本解析为一个数组。为了使事情更容易,我会声明一个Event 类来组织每个事件并存储相关信息。我会在Event 类中声明一个名为is_active 之类的方法,它将DateTime 参数作为其唯一参数并返回truefalse,具体取决于日期是否在事件的开始/结束日期。如果需要,可以很容易地将现有的所有事件数组过滤到特定日期的子集中。

    以下内容应该可以帮助您入门:

    class Event {
        // instance variables.
        private $_name;
        private $_begin;
        private $_end;
    
        // retrieve the name of the current Event instance.
        public function name() { return $this->_name; }
    
        // build a new immutable Event instance
        public function __construct($name, $begin, $end) {
            $this->_name = $name;
            $this->_begin = $begin;
            $this->_end = $end;
        }
    
        // check whether the $date argument falls between this Event's start/end dates.
        // $date is assumed to be a valid DateTime object
        public function is_active($date) {
            return $date >= $this->_begin && $date <= $this->_end;
        }
    }
    

    现在,为了继续更多OOP 的设计,我们还将创建一个类来管理一组事件,在这种情况下我将使用Calendar。我还添加了一个静态方法来解析文件中的日历。

    class Calendar {
        // Regular Expression for parsing the date range of an event. Update this if the format changes.
        // currently it assumes strings like: "Date: mm/dd/YYYY - mm/dd/YYYY"
        const PREG_DATE = '~^Date:\\s*(\\d{1,2}/\\d{1,2}/\\d{2,4})\\s*-\\s*(\\d{1,2}/\\d{1,2}/\\d{4})~i';
        // for date_create_from_format, matches the above Regular Expressions assumptions about date ordering
        const DATE_FORMAT = 'm/d/Y';
    
        // hold onto all the events
        private $_events;
    
        public function __construct($evts) {
            $this->_events = $evts;
        }
    
        // Retrieve all events active on a certain date.
        // $date is assumed to be a valid DateTime object
        public function get_events($date) {
            // If using PHP less than 5.3, you'll need to rewrite this without using closures.
            // basically just filters the array according to the results of calling "is_active" on each
            // of the event objects.
            return array_filter($this->_events, function($obj) use($date) {
                return $obj->is_active($date);
            });
        }
    
        // Very simple parsing function to read a Calendar from file
        // fairly rigid formatting expected.
        //
        // Event Name
        // Date: formatted date <-- must be on the very next line
        // <any number of blank lines can follow the above name/dates pair>
        // ...
        public static function from_file($filepath) {
            $events = null;
            $fs = fopen($filepath, 'r');
    
            if ($fs !== false) {
                $events = array();
                while (($buffer = fgets($fs)) !== false) {
                    $buffer = trim($buffer);
                    if ($buffer !== "") { // skip empty lines
                        if (($dateString = fgets($fs)) === false || preg_match(self::PREG_DATE, $dateString, $matches) !== 1) { 
                            break; // Invalid format reached (either premature EOF or unrecognized date format
                        } 
    
                        // Create a new Event object and add it to the array with the parsed values.
                        $events[] = new Event(
                            $buffer, 
                            date_create_from_format(self::DATE_FORMAT, $matches[1]),
                            date_create_from_format(self::DATE_FORMAT, $matches[2])
                        );
                    }
                }
                fclose($fs);
            }
    
            return $events !== null ? new Calendar($events) : null;
        }
    }
    

    就这么简单。日历控制一组Event 对象。通过调用get_events,您可以检索在特定日期活动的所有事件的数组。例如:

    $calendar = Calendar::from_file('foo.txt');
    var_dump($calendar->get_events(date_create_from_format('m/d/Y', '5/03/2013')));
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2013-03-17
      • 2011-02-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-03-20
      • 2010-10-10
      相关资源
      最近更新 更多