2016年5月17日火曜日

FuelPHP 1.7 月の検証でドハマリ valid_dateのバグ

今回は、検証後の日付の値がひと月戻る現象についてお伝えしようと思います。

まず、フォームはこんな感じ。月を選択するセレクトボックスです。


    <select name="month">
        <option value="2016-05">2016年 5月</option>
        <option value="2016-06">2016年 6月</option>
        <option value="2016-07">2016年 7月</option>
    </select>

いたって普通ですね。

Validationルールはこんな感じ


    $val = Validation::forge();

    $val->add('month', '月')
        ->add_rule('required')
        ->add_rule('valid_date', 'Y-m');

ここまでは特に問題ないと思います。

monthの値は'2016-05'を送信し、これを実行してみます。


    $result = $val->run();        //これは当然true
    $data = $val->validated();    //何が入るでしょう????

なんとびっくりなのですが、$data['month']の値は'2016-04'になります。

一か月戻っちゃってるよ!!!

coreのほうのコードをのぞいてみると元凶を見つけました。


    //中略
    $parsed = date_parse_from_format($format, $val);  //$valは'2016-05', $formatは'Y-m'
    //中略
    return date($format, mktime($parsed['hour'], $parsed['minute'], $parsed['second'], $parsed['month'], $parsed['day'], $parsed['year']));
    //↑お前が元凶だ!!

まず、$parsedの中身を見てみましょう


array(12) {
  ["year"]=>
  int(2016)
  ["month"]=>
  int(5)
  ["day"]=>
  bool(false)
  ["hour"]=>
  bool(false)
  ["minute"]=>
  bool(false)
  ["second"]=>
  bool(false)
  ["fraction"]=>
  bool(false)
  ["warning_count"]=>
  int(0)
  ["warnings"]=>
  array(0) {
  }
  ["error_count"]=>
  int(0)
  ["errors"]=>
  array(0) {
  }
  ["is_localtime"]=>
  bool(false)
}

$parsedのyear, monthはそれぞれ 2016, 5 なんですが、dayがbooleanのfalseです。
'2016-05'を送信したので年と月以外の値がfalseになっています。
falseは0と扱われますので、dayは0と同等です。
day(と時刻関連)が0なのにmktimeに代入してしまっているのが問題。
mktimeは2016年5月0日を、2016年5月1日の前日である2016年4月30日であると解釈しますので、これを'Y-m'でフォーマットすると2016-04になるんですねー

Y-mのフォーマットはあまり使われることはないと思いますが、使われる際はvalid_dateをオーバーライドするか独自ルールを作っての検証が必要です。
(FuelPHP 1.7でのお話なので、それ以降は治っていると思いたい)

2015年2月3日火曜日

Surface Pro 3 ネットワークアダプタでエラーコード10エラー

一昨日我が家に Surface Pro 3 がやってきました
キーボードもあるし、マウスもつけたらノートPCと使い勝手は変わらない感じです。
開発にも使えます。どうしても視線が低くなってしまうので肩こりはひどくなりそうですが。

さて、ちょっと放置してから作業を再開すると、なぜかWifiが繋がらない。
もともと我が家のwifiの調子が悪く繋がったり繋がらなかったりなのでまたそれかぁと思っていたのですが、何気なくデバイスマネージャを見てみたところネットワークアダプタに!マークがついてるじゃないですか…。エラーコード10ですかそうですか。

どうも復帰後はネットワークアダプタがうまく動かないみたいです。
他にも同様の問題が起きている人がいるらしく、カカクコムの口コミにも記載がありました。

『復帰後にWifiが使用出来なくなる?』のクチコミ掲示板

単純に再起動すれば治るので安心ですが、修正こないかなぁと期待しています。

2015年1月27日火曜日

Excel を SQL 文で集計する

エクセル関数だととても複雑になってしまう処理をSQLで代替できれば可読性良くあっさりと書けそうね、ということでやり方を調べてみた。

まずは接続するところから。 参照設定でADOが使えるようにしておくこと。 DBは作業しているブックとなる。


    Dim conn As ADODB.connection
    Set conn = New ADODB.connection
    With conn
        .Provider = "Microsoft.ACE.OLEDB.12.0"
        .Properties("Extended Properties") = "Excel 12.0"
        .Open ThisWorkbook.FullName
    End With

次は SELECT 文を実行してみる。Sheet1のテーブルを全部読み込む。


    Dim rs As ADODB.Recordset
    Dim sql As String

    'SQLを作成
    sql = "SELECT * FROM [Sheet1$];" 

    'データを取得
    Set rs = New ADODB.Recordset
    rs.Open sql, conn, adOpenKeyset, adLockReadOnly

    '取得データをSheet2に展開
    '指定したセルを起点にまるっと貼り付ける
    Worksheets("Sheet2").Cells(1, 1).CopyFromRecordset rs

    '閉じるのを忘れずに
    rs.Close
    Set rs = Nothing

    conn.Close
    Set conn = Nothing
 

SQLは普通にJOINとかGROUP BYとかおなじみな感じで安心。 ただテーブル名やフィールド名の指定がエクセル独自な感じなのかなー。 この辺の書き方は要調査ですね。

ADODB.commandオブジェクトも使用可能みたいなので、パラメータも使えそう。 (今日はまだ試せてない。) 接続から切断までクラスモジュールにしておけばめんどくさくなくてよさげ。