如何使用RSpec在postgres中设置时间以测试时区行为?

Pet*_*xey 5 postgresql rspec ruby-on-rails

我希望能够跨不同时区测试调度程序组件的行为。但是,触发计划行为的功能在postgres中使用基于时间的查询:

例如

# find reminders which have not been sent for "today" in the local date
Schedule.where('evening_reminder_last_sent_on_local_date != 
                                     DATE( NOW() AT TIME ZONE time_zone )')
Run Code Online (Sandbox Code Playgroud)

我希望能够在RSpec中测试此行为,并确保该行为在一天中可以正确播放,并且如果我在12月25日凌晨1点(UTC)向日本用户发送提醒,然后在UTC晚上10点向他们发送“今天”的提醒,将显示为已发送(因为它是早上7点左右,第二天日本)。

但是,为了做到这一点,我需要能够在postgres中设置日期时间。这可能吗?

请注意...这不是关于浪费Rails的时间

挑战在于不要浪费时间在Rails中-我知道该怎么做。问题是如何在Postgres中设置时间。

Erw*_*ter 4

Postgres 使用底层操作系统的日期/时间设置(至少在类 UNIX 系统上)。要暂存各种时间戳,您必须使用命令设置操作系统的时间date

我当然不会建议在执行其他重要操作的系统上这样做。cronjobs 可能会导致混乱和其他令人不快的副作用。

相反,请将该函数替换now()为用户定义的服务器端函数,例如:

CREATE OR REPLACE FUNCTION now_test()
  RETURNS timestamptz AS $func$SELECT '2013-12-01 12:34'::timestamptz$func$ LANGUAGE SQL;
Run Code Online (Sandbox Code Playgroud)

(上面的转换假定会话的当前时区设置。或者,您可以使用文字提供时区或时间偏移。)
然后您可以使用以下命令测试您的代码:

Schedule.where('evening_reminder_last_sent_on_local_date != 
                             DATE(now_test() AT TIME ZONE time_zone)')
Run Code Online (Sandbox Code Playgroud)

使用各种时间戳修改上面的 SQL 函数,就可以开始了。

  • 这是非常好的、非常好的建议。然而,这给我带来了另一个问题,那就是如何在 Rails 中管理 postgres 函数。我已经将此作为一个单独的问题提出,并且很想知道您的想法 - http://stackoverflow.com/questions/20314724/how-do-you-define-postgres-functions-in-rails-and-what-is -他们的范围和寿命 (2认同)