我有以下代码段:
class Foo
include DataMapper::Resource
property :id, Serial
property :timestamp, DateTime
end
我只想将当前时间转换为ms:
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
有什么想法吗?
答案 0 :(得分: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
请参阅“保存失败时引发异常”一章
顺便说一句,要在保存项目之前查看项目有什么问题,请使用item.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"]}
答案 1 :(得分:2)
PostgreSQL数据类型为timestamp
or timestamp with time zone
。但这与你正在做的事情相矛盾。您获取纪元值并乘以1000.您必须将其保存为integer
或某些numeric type。
More about the handling of timestamps in Postgres in this related answer.
我会将值保存为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
。
如果您想要timestamp
而不是timestamptz
,您仍然可以使用now()
,根据服务器时区设置将其转换为“本地”时间。或者,为了获得给定时区的时间:
now() AT ZIME ZONE 'Europe/Vienna' -- your time zone here
或者,在您的特定情况下,因为您似乎只需要三个小数位: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
,请添加TRIGGER,如下所示:
触发功能:
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's answer似乎很好地涵盖了Ruby方面。
答案 2 :(得分:0)
我不熟悉PostgreSQL,但为什么要将Fixnum(time
)分配给timestamp
(这是一个DateTime)?在生成SQL之前,您的模型必须无法将time
转换为正确的DateTime值。
试试foo.save!
。我很确定你会看到一个错误,或者从PostgreSQL报告,说1352633569151
不是表列的有效值,或者你的模型会说它无法将1352633569151
解析为有效的DateTime。
foo.timestamp = Time.now
或foo.timestamp = '2012-11-11 00:00:00'
是可行的。