#ruby-on-rails #postgresql #timezone
#ruby-on-rails #postgresql #Часовой пояс
Вопрос:
Я схожу с ума? time
атрибуты теряют свое значение и сбрасываются до 1 января 2000 года после сохранения активного объекта записи. База данных — Postgres. Rails 5.2 и pg gem 1.1.3
2.6.6 :019 > obj.end_time = Date.new(2019, 9,9)
=> Mon, 09 Sep 2019
2.6.6 :020 > obj.save
=> true
2.6.6 :021 > obj.end_time
=> Mon, 09 Sep 2019 00:00:00 UTC 00:00
2.6.6 :022 > obj.end_time.class
=> ActiveSupport::TimeWithZone
Но теперь, если я перезагружаюсь из базы данных, значение сбрасывается:
2.6.6 :023 > obj.reload
2.6.6 :024 > obj.end_time
=> Sat, 01 Jan 2000 00:00:00 UTC 00:00
2.6.6 :025 > obj.end_time.class
=> ActiveSupport::TimeWithZone
Тип столбца postgres отображается в psql как «время без часового пояса». Я думаю, мне просто нужно указать datetime вместо time в миграциях, если я хочу установить часть даты?
Я попытался изменить тип столбца при миграции change_column :school_courses, :start_time, :datetime
, но получил:
PG::DatatypeMismatch: ОШИБКА: столбец «start_time» не может быть автоматически преобразован в тип timestamp без часового пояса ПОДСКАЗКА: возможно, вам потребуется указать «ИСПОЛЬЗОВАНИЕ start_time::timestamp без часового пояса»
Не уверен, как это сделать
Комментарии:
1. Я не могу воспроизвести это с помощью базовой модели, вы делаете что-то в своем классе модели, что может повлиять на это?
2. Должно быть, это как-то связано с типом столбца в Postgres. У меня ничего нет в модели, и это происходит в другом месте. Попробую проверить в psql
3. Тогда вам было бы полезно опубликовать модель и определения таблиц postgres (DDL).
4. В Rails схема просто указывает «время» для столбца. Запуск d в psql в таблице дает тип столбца как «время без часового пояса», как я уже упоминал. Есть ли другая команда psql, которую вы рекомендуете, которая могла бы предоставить больше информации?
5. @rigyt можете ли вы, пожалуйста, опубликовать, как вы написали свою рабочую миграцию (решение)?
Ответ №1:
Используйте datetime
тип столбца для хранения даты и времени, используйте только time
при переносе, если вам не нужна дата (хотите сохранить только часть времени)
В любом случае это относится к postgres
Пример миграции:
create_table "school_years" do |t|
t.integer "year"
t.integer "minimum_candidates_per_exam"
t.time "am_start_time"
t.time "pm_start_time"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
Хотя я обычно просто использую datetime
и также устанавливаю часть года и избегаю использования time
Комментарии:
1. Спасибо за ответ. Вы когда-нибудь использовали подсказку, описанную «ПОДСКАЗКА: возможно, вам потребуется указать «ИСПОЛЬЗОВАНИЕ start_time::timestamp без часового пояса»» внутри самой миграции с помощью ключевого слова USING?