duanjiao5082 2018-01-28 16:31
浏览 74
已采纳

Bootstrap年历yii2扩展 - 月解析问题

I have integrated bootstrap year calendar yii2 into my website. I'm using active data provider to load the calendar items. I have encountered one issue so far. The month of each calendar item is not correct. One month is added to each calendar item. Eg item from 19th of May is shown as 19th of June etc. Has anyone faced a similar issue in the past?

print screen

echo ActiveCalendar::widget([
'language' => 'es',

'dataProvider' => new ActiveDataProvider([
    'query' => Event::find()->andWhere(['calendar_id' => $calendar->id])
]),
'options' => [
    // HTML attributes for the container.
    // the `tag` option is specially handled as the HTML tag name
],
'clientOptions' => [
    'enableContextMenu' => true,
    'enableRangeSelection' => true,
    'displayWeekNumber' => false,
    'alwaysHalfDay' =>true,
    'disabledDays'=> [],
    'startYear'=> '2018',
    'minDate'=> new JsExpression('new Date("2018-01-01")'),
    'maxDate'=> new JsExpression('new Date("2018-12-31")'),

    // JS Options to be passed to the `calendar()` plugin.
    // see http://bootstrap-year-calendar.com/#Documentation/Options
    // The `dataSource` property will be overwritten by the dataProvider.
],
'clientEvents' => [
    'mouseOnDay' => '',
    // JS Events for the `calendar()` plugin.
    // see http://bootstrap-year-calendar.com/#Documentation/Events
]
]);

$i = 1;
foreach($calendar->events as $event) {
echo 'Event ' . $i . ' start date: ' . $event->startDate . '- ';
echo 'end date: ' . $event->startDate . '<br/>';
$i++;
}

Edit: model as in the plugin documentation

class Event extends \yii\db\ActiveRecord implements DataItem
{

public function getName()
{
    return $this->event_title;
}

public function getStartDate()
{
    return JsExpressionHelper::parse($this->event_date);
}

public function getEndDate()
{
    return JsExpressionHelper::parse($this->event_date_end);
}

http://bootstrap-year-calendar.com/

  • 写回答

1条回答 默认 最新

  • donglinyi4313 2018-01-28 19:35
    关注

    There looks to be a logical fault in the Helper JsExpressionHelper and that needs a fix in the method parsePhpDate.

    What's The problem

    What it is doing is that when you call the method

    return JsExpressionHelper::parse($this->event_date);

    in your model passing it the date string or object it returns back the Javascript expression new Date(2018, 05, 19) now look closely there is a difference when you call the Date function of javascript by passing the date as Date(string) and date as Date(year,month,date).

    As in javascript Date() function starting month January is 0 rather than 1.

    See example

    console.log("new Date(2015,10,10) outputs : ", new Date(2015, 10, 10));
    console.log("new Date('2015-10-10') outputs : ", new Date('2015-10-10'));

    So in this case the helper is passing the month date and year by using php date function like JsExpression('new Date(' . $date->format('Y, m, d') . ')'); and that too without decrementing by one, means it is using php date function and it has month representation starting from 1-12 or 01-12. So the datepicker is loading the May date into June which is technically correct at its end.

    What to do

    You need to change the javascript expression returned by the function either return the expression with string or provide all the parameters manually.

    But since the helper has all static functions and you cant extend them i would suggest

    1.Copy that helper to the common/components folder and rename it as ExperssionHelper.

    2.In your model change the calls to JsExpressionHelper to ExpressionHelper.

    3.Then change the code to the following you can have 2 approaches to it first try this one by using string format if it works

     /**
         * Parses a DateTime object to a `JsExpression` containing a javascript date
         * object.
         *
         * @param DateTime $date
         * @return JsExpression
         */
        public static function parsePhpDate(DateTime $date)
        {
            return new JsExpression('new Date("' . $date->format('Y-m-d') . '")');
        }
    

    If for some reason the calendar does not work with that format change it to the following and it will work

    /**
     * Parses a DateTime object to a `JsExpression` containing a javascript date
     * object.
     *
     * @param DateTime $date
     * @return JsExpression
     */
    public static function parsePhpDate(DateTime $date)
    {
        $month=$date->format('m')-1;
        $day=$date->format('d');
        $year=$date->format('Y');
    
        return new JsExpression('new Date('.$year.','.$month.','.$day.')');
    
    }
    

    You can copy the following to your folder common/components

    <?php 
    namespace common\components;
    
    use DateTime;
    use yii\base\InvalidParamException;
    use yii\web\JsExpression;
    
    /**
     * Helper to parse data into
     * [JsExpression](http://www.yiiframework.com/doc-2.0/yii-web-jsexpression.html) * which is what the widgets expect when dealing with dates for the JS plugin.
     *
     * Its main usage is in classes implementing the [[DataItem]] interface
     *
     * ```php
     * public function getStartDate()
     * {
     *     return JsExpressionHelper::parse($this->start_date);
     * }
     * ```
     *
     * @author Angel (Faryshta) Guevara <angeldelcaos@gmail.com>
     */
    class ExpressionHelper
    {
        /**
         * Parses a date to a `JsExpression` containing a javascript date object.
         *
         * @param DateTime|string|integer $date
         * @param string $format only used when the ``$date` param is an string
         * @return JsExpression
         */
        public static function parse($date, $format = 'Y-m-d')
        {
            if (is_string($date)) {
                echo "string<br />";
                return self::parseString($date, $format);
            }
            if (is_integer($date)) {
                return self::parseTimestamp($date);
            }
            if (is_object($date) && $date instanceof DateTime) {
                return self::parsePhpDate($date);
            }
    
            throw new InvalidParamException('The parameter `$date` must be a '
                . 'formatted string, a timestamp or a `DateTime` object'
            );
        }
    
        /**
         * Parses a DateTime object to a `JsExpression` containing a javascript date
         * object.
         *
         * @param DateTime $date
         * @return JsExpression
         */
        public static function parsePhpDate(DateTime $date)
        {
            $month=$date->format('m')-1;
            $day=$date->format('d');
            $year=$date->format('Y');
    
            return new JsExpression('new Date('.$year.','.$month.','.$day.')');
        }
    
        /**
         * Parses an string to a `JsExpression` containing a javascript date object.
         *
         * @param string $date
         * @param string $format used to create a temporal `DateTime` object
         * @return JsExpression
         * @see http://php.net/manual/es/datetime.format.php
         */
        public static function parseString($date, $format = 'Y-m-d')
        {
            return self::parsePhpDate(DateTime::createFromFormat(
                $format,
                $date
            ));
        }
    
        /**
         * Parses a timestamp integer to a `JsExpression` containing a javascript
         * date object.
         *
         * @param integer $date
         * @return JsExpression
         * @see http://php.net/manual/es/datetime.settimestamp.php
         */
        public static function parseTimestamp($date)
        {
            $PhpDate = new DateTime();
            $PhpDate->setTimestamp($date);
            return self::parsePhpDate($PhpDate);
        }
    }
    

    Your Event Model should look like

    use common\components\ExpressionHelper;
    class Event extends \yii\db\ActiveRecord implements DataItem
    {
    
    public function getName()
    {
        return $this->event_title;
    }
    
    public function getStartDate()
    {
        return ExpressionHelper::parse($this->event_date);
    }
    
    public function getEndDate()
    {
        return ExpressionHelper::parse($this->event_date_end);
    }
    
    </div>
    
    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥100 set_link_state
  • ¥15 虚幻5 UE美术毛发渲染
  • ¥15 CVRP 图论 物流运输优化
  • ¥15 Tableau online 嵌入ppt失败
  • ¥100 支付宝网页转账系统不识别账号
  • ¥15 基于单片机的靶位控制系统
  • ¥15 真我手机蓝牙传输进度消息被关闭了,怎么打开?(关键词-消息通知)
  • ¥15 装 pytorch 的时候出了好多问题,遇到这种情况怎么处理?
  • ¥20 IOS游览器某宝手机网页版自动立即购买JavaScript脚本
  • ¥15 手机接入宽带网线,如何释放宽带全部速度