0

以下のコード スニペットがあります。

class Foo    
  include DataMapper::Resource
  property :id, Serial
  property :timestamp, DateTime
 end

現在の時刻をミリ秒に変換したいだけです:

 class Time
   def to_ms
     (self.to_f * 1000.0).to_i
   end
 end

 def current_time
   time = Time.now
   return time.to_ms
  end

  time = current_time # => 1352633569151

しかし、上記のタイムスタンプで Foo を保存しようとすると、データベースに保存できず、エラー メッセージが表示されません。

foo = Foo.new
foo.timestamp = time
foo.save

何か案が?

4

3 に答える 3

3

プロパティに正しいフォーマットを使用しています:datetimeか?

次のようにする必要があります。

DateTime.now.to_s
=> "2012-11-11T14:04:02+02:00"

または変換なしの「ネイティブ」DateTime オブジェクト。

DataMapper は、使用されているアダプターに基づいて、値を適切な値に変換します。

また、アイテムを保存するときに例外を発生させるには:

DataMapper::Model.raise_on_save_failure = true 

これはグローバル設定です。つまり、すべてのモデルで例外が発生します。

一部のモデルのみを次のように動作させるには:

YourModel.raise_on_save_failure = true

http://datamapper.org/docs/create_and_destroy.html

「保存が失敗したときに例外を発生させる」の章を参照してください

ところで、アイテムを保存する前に何が問題なのかを確認するには、 anditem.valid?item.errors

foo = Foo.new
foo.timestamp = time
if foo.valid?
  foo.save
else
  p foo.errors
end

コードを複製したところ、次のエラーが発生しました。

@errors={:timestamp=>["Timestamp must be of type DateTime"]}

ライブデモはこちら

于 2012-11-11T12:01:38.603 に答える
2

PostgreSQLのデータ型はtimestampまたtimestamp with time zoneはです。しかし、それはあなたがしていることと矛盾します。エポック値を取得し、1000を掛けます。それをintegerまたは数値タイプとして保存する必要があります。

この関連する回答で、Postgresでのタイムスタンプの処理について詳しく説明します。

値をそのまま保存しますtimestamp with time zone(乗算なし)。必要に応じて、いつでもmsを抽出できます。

Unixエポック値をタイムスタンプに戻す必要がある場合は、次を使用します。

SELECT to_timestamp(1352633569.151);
--> timestamptz 2012-11-11 12:32:49.151+01

「今」を保存するだけ

実際に「今」、つまり現在の時点を保存したい場合は、Postgresに任せてください。データベースサーバーに信頼できる現地時間が存在することを確認してください-ntpをインストールします。これは一般的に、より信頼性が高く、正確で、単純です。

DEFAULTタイムスタンプ列のをnow()またはに設定しCURRENT_TIMESTAMPます。代わりに必要な
場合は、サーバーのタイムゾーン設定に従って「ローカル」時間に変換されるを使用できます。または、特定のタイムゾーンの時間を取得するには:timestamptimestamptznow()

now() AT ZIME ZONE 'Europe/Vienna'  -- your time zone here

または、特定のケースでは、3桁の小数桁のみが必要なように見えるため、now()::timestamp(3)またはCURRENT_TIMESTAMP(3)またはCURRENT_TIMESTAMP(3) AT ZIME ZONE 'Europe/Vienna'
または、列のタイプをとして定義するとtimestamp(3)、すべてのタイムスタンプ値がタイプに強制変換され、小数点以下3桁に自動的に丸められます。

したがって、必要なのはこれだけです。

CREATE TABLE tbl (
   -- other columns
  ,ts_column timestamp(3) DEFAULT now()
);

値は自動的にオンINSERTに設定されます。列について言及する必要はありません。
更新する場合は、次のようなトリガーON UPDATEを追加します。

トリガー機能:

CREATE OR REPLACE FUNCTION trg_up_ts()
  RETURNS trigger AS
$BODY$
BEGIN
   NEW.ts_column := now();
   RETURN NEW;
END
$BODY$ LANGUAGE plpgsql VOLATILE

引き金:

CREATE TRIGGER log_up_ts
BEFORE UPDATE ON tbl
FOR EACH ROW EXECUTE PROCEDURE trg_up_ts();

これで、すべてが自動的に機能します。
それがあなたが求めているものではない場合、@slivuの答えはRubyの側面をうまくカバーしているようです。

于 2012-11-11T12:08:09.463 に答える
0

私は PostgreSQL に詳しくありませんが、なぜ Fixnum ( time) をtimestamp(DateTime である) に割り当てているのですか? SQL を生成する前に、モデルがtime適切な DateTime 値への変換に失敗している必要があります。

試してみてくださいfoo.save!1352633569151PostgreSQL から報告されたテーブル列の有効な値ではないというエラーが表示されるか、モデルが1352633569151有効な DateTime に解析できないというエラーが表示されると確信しています。

foo.timestamp = Time.nowまたはfoo.timestamp = '2012-11-11 00:00:00'うまくいくものです。

于 2012-11-11T15:12:04.353 に答える