15

MySQL テーブルがあり、このテーブルには というDATETIME名前の列がありますdatetime_utc。ご想像のとおり、UTC の日付と時刻です。私の Bookshelf モデルでは、Moment.js を使用してこれを ISO 8601 文字列形式に変換する仮想ゲッターを定義しました。私のモデルは次のようになります。

bookshelf.plugin('virtuals');

exports.MyModel = bookshelf.Model.extend({
    tableName : 'my_table',
    idAttribute : 'id',
    virtuals : {
        datetime_iso : {
            get : function () {
                return moment.utc(this.get('datetime_utc')).format();
            }
        }
    }
});

問題は、Bookshelf (またはそれを駆動する基礎となる Knex) がDATETIME列を見ると、値をnew Date(...)コードに渡す前に a でラップすることです。日付の値は UTC ですが、Date コンストラクターは値がサーバーのローカルの非 UTC タイムゾーンにあると想定しているため、正しい日付が間違ったタイムゾーンにある Date オブジェクトになってしまいます。Moment がこの Date で作業を開始すると、すべての値が一定時間ずれます。

Date オブジェクトを探し、日付コンポーネントを Moment コンストラクターに直接分解することで、この問題を回避しました。しかし、それはひどく感じます:

get : function () {
    var dt = this.get('datetime_utc');

    if (dt instanceof Date) {
        dt = [
            dt.getFullYear(), dt.getMonth(), dt.getDate(),
            dt.getHours(), dt.getMinutes(), dt.getSeconds()
        ];
    }

    return moment.utc(dt).format();
}

Bookshelf からラップされていないYYYY-MM-DD HH:MM:SS文字列値を取得する、またはタイムゾーンを無視/UTC に変更して Date から新しい Moment オブジェクトを作成する簡単な方法はありますか?

4

1 に答える 1

25

これは Knex や Bookshelf が原因ではなく、基盤となる node-mysql ライブラリが原因であることが判明しました。Date オブジェクトに解析される前に、 、 、 、および各値に追加されるtimezoneと呼ばれる接続プロパティがあります。DATETIMEDATETIMESTAMPNEWDATE

Knex は、初期化中にこのプロパティを node-mysql に渡します。

require('knex')({
    "client": "mysql",
    "connection": {
        "host": "...",
        "user": "...",
        "password": "...",
        "database": "...",
        "timezone": "UTC"    <-- This is the culprit
    }
});
于 2014-09-08T16:54:56.037 に答える