2013-12-04 3 views
2

Я не знаю, как, но моя консоль и мой сервер имеют два разных часовых пояса для DateTime.now. Если я бегу DateTime.Now в моей консоли следующее возвращается:rails - конвертировать DateTime в UTC перед сохранением на сервер

Wed, 04 Dec 2013 14:27:23 -0500 

Однако, я следующий в моей целевой модели:

def self.already_expired 
    where("time_frame < ?", DateTime.now) 
end 

Цель кода выше, чтобы выстрелить некоторые методы задачи по задачам, где «time_Frame» - прошедшая дата. Вот где я вызвать метод:

task :change_it => :environment do 
    puts "yo yo you yo you" 
    @tasks = Task.already_expired 
    @tasks.each do |task| 
     puts "Kalabar" + task.inspect + "now time is:" + DateTime.now.to_s 
    end 
end 

Логи сервера показать это:

Task Load (1.2ms) SELECT "tasks".* FROM "tasks" WHERE (time_frame < '2013-12-04 17:25:37') 
    Kalabar#<Task id: 3, title: "task 1 - past", content: "Should show this one", 
     created_at: "2013-12-04 17:05:53", updated_at: "2013-12-04 17:05:53", 
     schedule_id: 2, amount: nil, time_frame: "2013-12-02 08:15:00"> 
     now time is:2013-12-04T12:25:37-05:00 
    Kalabar#<Task id: 5, title: "another task - past", 
     content: "should show this one", created_at: "2013-12-04 17:11:23", 
     updated_at: "2013-12-04 17:11:23", schedule_id: 3, amount: nil, 
     time_frame: "2013-12-03 02:07:00">now time is:2013-12-04T12:25:37-05:00 
    Kalabar#<Task id: 6, title: "another task - future", 
     content: "should not show at first", created_at: "2013-12-04 17:11:23", 
     updated_at: "2013-12-04 17:25:09", schedule_id: 3, amount: nil, 
     time_frame: "2013-12-04 12:27:00">now time is:2013-12-04T12:25:37-05:00 

Таким образом, сравниваемые time_frame к «2013-12-04 12:25:37, который UTC. Однако, когда у меня есть печать DateTime.now.to_s, она печатает '2012-12-04 08:15:00'.

Я хочу преобразовать все в UTC, прежде чем он войдет в базу данных. Я также не понимаю, почему она имеет два разных часовых поясов для DateTime.Now Вот мои вопросы

  1. Почему существуют два разных часовых поясов для DateTime.now
  2. Как конвертировать часовых поясов в UTC, прежде чем они сохранить база данных?

UPDATE:

Я поставил следующий в моем application.rb файл:

config.time_zone = 'Eastern Time (US & Canada)' 

А теперь пользователь вводит в DateTime в восточном время, и она будет храниться как время UTC , Итак, теперь time_frame сравнивается с DateTime.now правильно. Проблема в том, что если я помещаю time_frame, он помещает его в восточное время. Я не совсем уверен, что происходит. Он хранит его в UTC, но печатает его в восточное время. Это опасно/правильно? Я добавил «ставит time_Frame» в целевой блок кода:

task :change_it => :environment do 
    @tasks = Task.already_expired 
    @tasks.each do |task| 
     puts "Kalabar" + task.inspect + "now time is:" + DateTime.now.to_s 
     puts "time_frame is:" + task.time_frame.to_s 
    end 
end 

и выводит это:

Kalabar#<Task id: 3, title: "task 1 - past", content: "Should show this one", created_at: "2013-12-04 17:05:53", updated_at: "2013-12-04 17:05:53", schedule_id: 2, amount: nil, time_frame: "2013-12-02 08:15:00">now time is:2013-12-04T15:27:22-05:00 
time_frame is:2013-12-02 03:15:00 -0500 
Kalabar#<Task id: 7, title: "Task 1 - past by days", content: "Should always show", created_at: "2013-12-04 20:20:40", updated_at: "2013-12-04 20:20:40", schedule_id: 4, amount: nil, time_frame: "2013-12-02 09:02:00">now time is:2013-12-04T15:27:22-05:00 
time_frame is:2013-12-02 04:02:00 -0500 
Kalabar#<Task id: 8, title: "Task 2 - past by minutes", content: "should always show", created_at: "2013-12-04 20:20:40", updated_at: "2013-12-04 20:20:40", schedule_id: 4, amount: nil, time_frame: "2013-12-04 20:15:00">now time is:2013-12-04T15:27:22-05:00 
time_frame is:2013-12-04 15:15:00 -0500 

Итак, как вы можете видеть, в базе данных она является UTC, но когда он говорит, что это в восточном. Почему это делается/это опасно?

ответ

0

Вы можете установить часовой пояс на заказ в config/application.rb

# Set Time.zone default to the specified zone and make Active Record auto-convert to this zone. 
# Run "rake -D time" for a list of tasks for finding time zone names. Default is UTC. 
# config.time_zone = 'Central Time (US & Canada)' 
+0

Я пробовал это. Кажется, это не работает. Что-то не так с моим кодом: Time.zone = 'UTC' – Philip7899

+0

Вам нужно установить его так: 'config.time_zone = 'Central Time (US & Canada)'', используйте 'rake time: zones: all' to см. список названий часовых поясов. – NARKOZ

+0

Спасибо, я попробовал, и это сработало (слегка/я думаю). Я обновил вопрос. – Philip7899

2

Это поведение по умолчанию ActiveRecord, что все ваше время будет получить сохранены в базе данных в формате UTC. Вам не нужно его конвертировать. Всякий раз, когда вы инициализируете текущее время, он возвращает вам объект времени, который означает независимо от часового пояса, он укажет на определенное время. Независимо от того, сколько времени вы получаете в другой часовой пояс, все указывают на то же время, если вы преобразуете его в UTC. Таким образом, я не думаю, что с поиском текущего времени не должно быть никаких проблем, потому что любое время будет храниться в соответствующее время utc.

Проблема с часовым поясом возникает, когда вы пытаетесь инициализировать объект времени с помощью строки (или передавая атрибуты DateTime).Объекты времени анализируются с использованием системного часового пояса, не используя часовой пояс, заданный в application.rb. Поэтому в этом случае лучше проанализировать время с использованием объекта часового пояса ActiveSupport.

0

1) DateTime.now возвращает DateTime obj, вы можете преобразовать его в любой часовой пояс, который вы хотите (и это все еще так), если вы попытаетесь выполнить любую операцию с ActiveRecord, ActiveRecord сначала преобразует DateTime obj по умолчанию, а затем выполните работу.

2) Прежде чем сохранять какое-либо время в базе данных, убедитесь, что это DateTime obj, если вы получаете дату и время, и вы знаете часовой пояс, вы можете использовать DateTime.parse для преобразования его в DateTime obj:

irb(main):014:0> s = "2013-12-02 09:00:00 EST" 
=> "2013-12-02 09:00:00 EST" 
irb(main):015:0> sdt = DateTime.parse(s) 
=> Mon, 02 Dec 2013 09:00:00 -0500 
0

Я не думаю, что вы смотрите на 2 часовых пояса. Часовой пояс в базе данных (показано task.inspect) - UTC. Вы правы, что при запуске DateTime.now вы получаете объект, представляющий время в вашем текущем часовом поясе. Самое интересное, что ActiveRecord достаточно умен, чтобы изменить этот объект в UTC для фактической команды sql. Попробуйте это в консоли:

Task.where("time_frame < ?", DateTime.now).to_sql 

Он должен преобразовать DateTime.now в представлении UTC, так что вы должны получить обратно результаты, которые вы ожидали. Это работает?

Смежные вопросы