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>
    
    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥50 buildozer打包kivy app失败
  • ¥30 在vs2022里运行python代码
  • ¥15 不同尺寸货物如何寻找合适的包装箱型谱
  • ¥15 求解 yolo算法问题
  • ¥15 虚拟机打包apk出现错误
  • ¥15 用visual studi code完成html页面
  • ¥15 聚类分析或者python进行数据分析
  • ¥15 三菱伺服电机按启动按钮有使能但不动作
  • ¥15 js,页面2返回页面1时定位进入的设备
  • ¥50 导入文件到网吧的电脑并且在重启之后不会被恢复