查找一个人一天中的可用时间



我正在为一个事件进行资源分配。

我的一个资源的事件表如下所示:

(Int)---(nvarchar(100)---(datetime)--(datetime)
EventId --- Event ---    StartTime ---              EndTime
1    /       test    /    2013-02-20 13:00:00   /   2013-02-20 15:00:00
2    /       test2   /     2013-02-20 09:30:00  /   2013-02-20 11:00:00
3    /       test3   /     2013-02-25 11:30:00  /   2013-02-25 14:30:00

现在我想在一天内找到该资源的总可用性。

就像2013年2月20日一样,我想从这个资源中删除繁忙的时间,并只显示新活动的可用时间。

我使用的是php和sql server 2008 r2。

一天只有一张唱片,效果很好。现在我正在使用foreach循环进行计算。

我的代码是:

$id = 6;    
$cdata = $test->getResourceEvents($id);
$h = "";
$final= array();
foreach($cdata as $c)
   {
   $sh = $c['starttime']->Format('H'); // Starting hour
   $eh = $c['endtime']->Format('H'); // End hour
   $hh = $sh;
   $final = array();
   $sdate = $c['starttime']->Format('Y-m-d');
   $edate = $c['endtime']->Format('Y-m-d');
   if($edate == $sdate)
   {
   $dh = $eh-$sh; // Duration
       for($i=1;$i<=$dh;$i++)
       {
           $hh = $hh.",".($sh+$i); // Busy hours
       }    
   $busyhrs[$sdate] = explode(",",$hh);
       $final[$sdate] = $busyhrs;
   }
   else
   {
       echo "false";
   }
}
print_r($final);

我的结果是:

大堆(〔2013-02-20〕=>阵列(〔2013-02-20〕=>阵列([0]=>9[1] =>10[2] =>11))〔2013-02-26〕=>阵列(〔2013-02-26〕=>阵列([0]=>11[1] =>12[2] =>13[3] =>14)))

前两条记录的日期相同。但这只计算第二行的小时数。不计算第一行的13、14、15小时。

有人能告诉我如何匹配日期以及如何获得一次约会的总繁忙时间吗?

我认为这符合您的期望。关键行是那些涉及$all_finals和$final移动的行。我通常用python编写,不知道在php中附加到数组的最佳方式,所以我使用了这个http://php.net/manual/en/function.array-push.php

$id = 6;    
$cdata = $test->getResourceEvents($id);
$h = "";
$all_finals = array();

foreach($cdata as $c)
   {
   $final= array();
   $sh = $c['starttime']->Format('H'); // Starting hour
   $eh = $c['endtime']->Format('H'); // End hour
   $hh = $sh;
   $final = array();
   $sdate = $c['starttime']->Format('Y-m-d');
   $edate = $c['endtime']->Format('Y-m-d');
   if($edate == $sdate)
   {
   $dh = $eh-$sh; // Duration
       for($i=1;$i<=$dh;$i++)
       {
           $hh = $hh.",".($sh+$i); // Busy hours
       }    
   $busyhrs[$sdate] = explode(",",$hh);
       $final[$sdate] = $busyhrs;
   }
   else
   {
       echo "false";
   }
   array_push($all_finals, $final);
}
print_r($all_final);

我在Java中做了类似的事情。

我有一个表格,里面有日期范围,还有一个日期范围,我必须将其插入已经存在的日期范围的覆盖范围中。

我基本上取了我感兴趣的日期范围,并"减去"所有现有的日期范围。你可以在下面的代码中找到我的减法。

从DateRange_A中减去DateRange_B会导致DateRange-A被修改到位,并且如果DateRange_A被DateRange-B完全分割,则该方法返回新的DateRange。

当然,还有其他方法可以解决这个问题,比如SQL SERVER中的迭代,但我已经有了Java的想法,这个解决方案就发生了。


/*
 * Copyright (c) 2009, Ben Fortuna
 * (Modified by Alex Marunowski)
 * All rights reserved.
 * 
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 
 *  o Redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer.
 * 
 *  o Redistributions in binary form must reproduce the above copyright
 * notice, this list of conditions and the following disclaimer in the
 * documentation and/or other materials provided with the distribution.
 * 
 *  o Neither the name of Ben Fortuna nor the names of any other contributors
 * may be used to endorse or promote products derived from this software
 * without specific prior written permission.
 * 
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
import java.io.Serializable;
import java.util.Date;
/**
 * @author fortuna
 *
 */
public class DateRange implements Serializable {
    private static final long serialVersionUID = -7303846680559287286L;
    /**
     * A flag indicating whether to include the start of the period in test functions.
     */
    public static final int INCLUSIVE_START = 1;
    /**
     * A flag indicating whether to include the end of the period in test functions.
     */
    public static final int INCLUSIVE_END = 2;
    private Date rangeStart;
    private Date rangeEnd;
    /**
     * @param start the start of the range
     * @param end the end of the range
     */
    public DateRange(Date start, Date end) {
        if (start == null) {
            throw new IllegalArgumentException("Range start is null");
        }
        if (end == null) {
            throw new IllegalArgumentException("Range end is null");
        }
        if (end.before(start)) {
            throw new IllegalArgumentException("Range start must be before range end");
        }
        this.rangeStart = start;
        this.rangeEnd = end;
    }
    /**
     * @return the rangeStart
     */
    public Date getStartDate() {
        return rangeStart;
    }
    /**
     * @return the rangeEnd
     */
    public Date getEndDate() {
        return rangeEnd;
    }
    public void setRangeStart(Date rangeStart) {
        if(rangeStart.after(getEndDate()))
            throw new IllegalArgumentException("The start of a date range cannot be after its end!");
        this.rangeStart = rangeStart;
    }
    public void setRangeEnd(Date rangeEnd) {
        if(rangeStart.after(getEndDate()))
            throw new IllegalArgumentException("The end of a date range cannot be after its start!");
        this.rangeEnd = rangeEnd;
    }
    /**
     * Determines if the specified date occurs within this period (inclusive of
     * period start and end).
     * @param date a date to test for inclusion
     * @return true if the specified date occurs within the current period
     * 
     */
    public final boolean includes(final Date date) {
        return includes(date, INCLUSIVE_START | INCLUSIVE_END);
    }
    /**
     * Decides whether a date falls within this period.
     * @param date the date to be tested
     * @param inclusiveMask specifies whether period start and end are included
     * in the calculation
     * @return true if the date is in the period, false otherwise
     * @see Period#INCLUSIVE_START
     * @see Period#INCLUSIVE_END
     */
    public final boolean includes(final Date date, final int inclusiveMask) {
        boolean includes = true;
        if ((inclusiveMask & INCLUSIVE_START) > 0) {
            includes = includes && !rangeStart.after(date);
        }
        else {
            includes = includes && rangeStart.before(date);
        }
        if ((inclusiveMask & INCLUSIVE_END) > 0) {
            includes = includes && !rangeEnd.before(date);
        }
        else {
            includes = includes && rangeEnd.after(date);
        }
        return includes;
    }
    /**
     * Decides whether this period is completed before the given period starts.
     * 
     * @param range
     *            a period that may or may not start after this period ends
     * @return true if the specified period starts after this periods ends,
     *         otherwise false
     */
    public final boolean before(final DateRange range) {
        return (rangeEnd.before(range.getStartDate()));
    }
    /**
     * Decides whether this period starts after the given period ends.
     * 
     * @param range
     *            a period that may or may not end before this period starts
     * @return true if the specified period end before this periods starts,
     *         otherwise false
     */
    public final boolean after(final DateRange range) {
        return (rangeStart.after(range.getEndDate()));
    }
    /**
     * Decides whether this period intersects with another one.
     * 
     * @param range
     *            a possible intersecting period
     * @return true if the specified period intersects this one, false
     *         otherwise.
     */
    public final boolean intersects(final DateRange range) {
        boolean intersects = false;
        // Test for our start date in period
        // (Exclude if it is the end date of test range)
        if (range.includes(rangeStart) && !range.getEndDate().equals(rangeStart)) {
            intersects = true;
        }
        // Test for test range's start date in our range
        // (Exclude if it is the end date of our range)
        else if (includes(range.getStartDate())
                && !rangeEnd.equals(range.getStartDate())) {
            intersects = true;
        }
        return intersects;
    }
    /**
     * Decides whether these periods are serial without a gap.
     * @param range a period to test for adjacency
     * @return true if one period immediately follows the other, false otherwise
     */
    public final boolean adjacent(final DateRange range) {
        boolean adjacent = false;
        if (rangeStart.equals(range.getEndDate())) {
            adjacent = true;
        } else if (rangeEnd.equals(range.getStartDate())) {
            adjacent = true;
        }
        return adjacent;
    }
    /**
     * Decides whether the given period is completely contained within this one.
     * 
     * @param range
     *            the period that may be contained by this one
     * @return true if this period covers all the dates of the specified period,
     *         otherwise false
     */
    public final boolean contains(final DateRange range) {
        // Test for period's start and end dates in our range
        return (includes(range.getStartDate()) && includes(range.getEndDate()));
    }
    /**
     * Decides whether the given period is completely contained within this one, taking into consideration whether date ranges with matching start or end dates 
     * are counted as being contained
     * 
     * @param range
     *            the period that may be contained by this one
     * @param inclusiveMask
     *              if this is set to 0, the start and end dates cannot be the same date and have it be considered to be contained within this date range.
     *              this.contains(this, 1) returns true 
     *              this.contains(this, 0) returns false 
     * @return true if this period covers all the dates of the specified period,
     *         otherwise false
     */
    public final boolean contains(final DateRange range, int inclusiveMask) {
        // Test for period's start and end dates in our range
        return (includes(range.getStartDate(), inclusiveMask) && includes(range.getEndDate(), inclusiveMask));
    }

    /**
     * Exclude otherRange from the dates covered by this DateRange. Note: This will put the specified buffer around the range being subtracted from this date range. 
     * @param otherRange
     * @return an additional date range if subtracting otherRange from this DateRange results in a part of this objects DateRange being separated from the rest of the range. 
     * i.e. if this.includes(otherRange, 0), then there will be two remaining portions of this daterange.
     * If no dangling date range remains, then the method returns null.
     * @author Alex Marunowski. 2012.10.31
     */
    public DateRange subtract(DateRange otherRange, long buffer) throws DateRangeObliteratedException{
        Date bufferedStart = new Date(otherRange.getStartDate().getTime()-buffer);
        Date bufferedEnd= new Date(otherRange.getEndDate().getTime()+buffer);
        otherRange = new DateRange(bufferedStart, bufferedEnd);
        // If the other range is entirely after this range, nothing happens
        if(getEndDate().before(otherRange.getStartDate()))
            return null;
        // If the other range is entirely before this range, nothing happens
        if(getStartDate().after(otherRange.getEndDate()))
            return null;
        if(otherRange.contains(this))
            throw new DateRangeObliteratedException();
        DateRange separatedTimeInterval = null;
        if(this.contains(otherRange, 0)){
            // The trailing daterange is the time between the end date of the inner daterange, and the end date of the outer date range
            separatedTimeInterval = new DateRange(otherRange.getEndDate(), getEndDate());
            // This date range now ends at the start time of the inner date range
            this.setRangeEnd(otherRange.getStartDate());
            return separatedTimeInterval;
        }


        if(otherRange.getEndDate().before(getEndDate())){
            // This date range is now the time between the end of the otherRange plus the buffer time, and the end of this date range
            long newRangeStart = otherRange.getEndDate().getTime();
            this.setRangeStart(new Date(newRangeStart));
            return null;
        }
        if(otherRange.getStartDate().after(getStartDate())){
            // This date range is now the time between this date range's start, and the other date ranges start minus the buffer time
            long newRangeEnd = otherRange.getStartDate().getTime();
            this.setRangeEnd(new Date(newRangeEnd));
            return null;
        }
        // This will never happen, but the compiler doesn't know that
        System.out.println("This should never have happened. No comparisons between the date ranges was discovered");
        return null;

    }
    public static class DateRangeObliteratedException extends Exception {
        /**
         * 
         */
        private static final long serialVersionUID = -5642891561498447972L;
        public DateRangeObliteratedException() {
            super("This date range no longer exists. It was entirely contained within the range you subtracted from it.");
        }
    }
}

                        for(int rangeIndex = 0; rangeIndex less than rangesBusy.size(); rangeIndex++) {
                            DateRange busyRange = rangesBusy.get(rangeIndex);
                            try {
                                DateRange trailingRange =  freeTimeBlock.subtract(busyRange, 0);
                                if(trailingRange != null) {
                                    freeTimeRanges.add(trailingRange);
                                }
                            } catch (DateRangeObliteratedException e) {
                                freeTimeRanges.remove(rangeIndex);
                                rangeIndex--;
                            }
                        }

我找到了解决方案。我改变了制作最终阵列的过程。非常感谢所有帮助我的人。我认为这很简单。这是我的密码。

也许它会对某人有所帮助。

        $id = 6;    
        $cdata = $test->getResourceEvents($id);
        $h = "";
        $final= array();
        foreach($cdata as $c)
        {
            $sh = $c['starttime']->Format('H'); // Starting hour
            $eh = $c['endtime']->Format('H'); // End hour

            $hh = $sh;
            $busyhrs = array();
            $sdate = $c['starttime']->Format('Y-m-d');
            $edate = $c['endtime']->Format('Y-m-d');
            if($edate == $sdate)
            {
                $dh = $eh-$sh; // Duration
                for($i=1;$i<=$dh;$i++)
                {
                    $hh = $hh.",".($sh+$i); // Busy hours
                }   
                if($final != array() || $final != NULL)
                {
                    foreach($final as $key=>$val)
                    {
                        if($key==$sdate)
                        {
                            $final[$key] = $val.",".$hh;
                        }
                        else
                        {
                            $final[$sdate] = $hh;
                        }
                    }
                }
                else
                {
                    $final[$sdate] = $hh;
                }                           
            }
            else
            {
                echo "false";
            }
        }
        echo "<pre>";
        print_r($final);

相关内容

  • 没有找到相关文章

最新更新