Rails3/jQuery UI Datepicker - месяц и день отменены при сохранении
(Моя проблема почти такая же, как описанная в этом вопросе, только этот ответ не работает в моем случае.)
Я использую jQuery UI Datepicker в приложении Rails с db Postgres. Реализация по умолчанию использует формат даты мм/дд/гг, чтобы отобразить выбранную дату, и именно этого я хочу. Однако, после сохранения записи в базе данных, месяц и день меняются на противоположные - тогда она отображается как yy-dd-mm. Таким образом, выбор 3/11/2012 пытается сэкономить 3 ноября вместо 11 марта, а дата типа 3/31/2012 вообще не сохраняется, потому что ее не существует.
Я пропустил еще 3 различных способа, чтобы исправить это:
1) Первая попытка состояла в том, чтобы переформатировать текстовое поле, чтобы дисплей выглядел так, как я хотел:
<%= f.text_field :foo, :value => (@model.foo.blank? ? '' : @model.foo.strftime('%m/%d/%Y')), class: "datepicker" %>
Это отобразилось 03/31/2012 правильно, но при сохранении было отменено.
2) Итак, в следующий раз я попытался изменить способ по умолчанию, в котором хранятся даты, и подумал, что проблема будет решена. Как описано в ответе на этот вопрос, я добавил следующее в config/locales/en.yml:
# config/locales/en.yml
en:
date:
formats:
default: "%m/%d/%Y"
Это не имело никакого значения. Затем я нашел этот вопрос и попытался создать config/initializers/date_formats.rb следующие строки:
Date::DATE_FORMATS[:default]="%m/%d/%Y"
Time::DATE_FORMATS[:default]="%m/%d/%Y %H:%M"
То же, что и выше, без разницы.
3) После игры с множеством комбинаций одна вещь, которую я обнаружил, что работа DID указывала формат yyyy-mm-dd в моем обращении к плагину datepicker - это противоположность того, что я хотел, но, по крайней мере, даты могут быть успешно сохранены. Поэтому вызов datepicker выглядит следующим образом:
$( ".datepicker" ).datepicker({ dateFormat: 'yy-mm-dd' });
Выбор 31 марта из календаря заполняет поле 2012-03-31 и по-прежнему отображается как 2012-03-31 после сохранения.
Но как я могу заставить datepicker работать с форматом mm/dd/yy? Я не могу себе представить, что это сложно сделать, но чего я не хватает? Должен ли я что-то делать с тем, как даты хранятся в Postgres? (Они указаны как дата, а не дата и время.)
Ответы
Ответ 1
Хорошо, это зависит от того, как вы храните данные в своей базе данных.
Если вы используете SQL-запросы RAW, вы можете использовать to_date('31 Mar 2012', 'DD Mon YYYY')
в своем запросе на вставку.
Postgres 'to_date
ссылка
Теперь, на вашей стороне клиента, в jquery date picker вы можете использовать
$.datepicker.formatDate('dd-M-yy', Yourdate);
Я использовал DD Mon YYYY, потому что это кажется яснее. Вы можете использовать формат mm/dd/yy
или другие форматы, основанные на потребностях. В таких случаях используйте формат в функции postgre to_date
Просьба отметить, что я не тестировал выше код. Оставьте комментарии, если есть какие-либо проблемы или вы столкнулись с какими-либо проблемами.
Edit:
Вы можете использовать Date.parse('2011-06-18')
в вашем представлении рельсов, прежде чем вставлять данные в базу данных и установить formatDate
в 'yy-mm-dd'
в datepicker.
Ответ 2
Если вы хотите изменить формат даты по умолчанию для своего кластера баз данных, вы также можете установить DateStyle GUC в postgresql.conf
и перезагрузить:
datestyle = 'iso, mdy'
(что должно быть по умолчанию в любом случае.)
Обратите внимание, что это не влияет на то, как даты отображаются в вашем приложении. Как PostgreSQL интерпретирует неоднозначный ввод и некоторые параметры вывода Postgres.
Если вы установите параметр datestyle
в psql в (очевидно) другом соединении, это ничего не доказывает. Приложение может устанавливать другой datestyle
в связи с локальными настройками. Вам нужно будет проверить настройку внутри вашего фактического соединения (не из psql).
Если ваша настройка datestyle 'iso, mdy'
, тогда она должна работать так, как вы хотите: словарные литеры интерпретируются месяцем раньше. Рассмотрим эту демонстрацию (используя PostgreSQL 9.1):
db=# set datestyle = 'ISO, MDY';
SET
db=# select '1.12.2012'::date;
date
------------
2012-01-12
(1 row)
db=# set datestyle = 'ISO, DMY';
SET
db=# select '1.12.2012'::date;
date
------------
2012-12-01
(1 row)
Акцент на мой.
Чтобы узнать, какие параметры действительно установлены вашим приложением, вы можете установить
log_statement = all
в postgresql.conf
и перезагрузите. Затем запустите приложение и сохраните дату. Каждая команда будет регистрироваться. Не забудьте reset и перезагрузите его (или ваши файлы журналов могут увеличиться):
log_statement = none
Затем проверьте свои файлы журналов db, что ваше приложение действительно отправлено в базу данных.
Вы также можете быть заинтересованы в команде to_date()
, которая позволяет вводить литералы даты в любом формате, который вам нравится. Но вам это не нужно.
Ответ 3
Я столкнулся с теми же проблемами, что и исходный плакат. Поскольку мне приходится сравнивать даты/время друг с другом, я не хотел менять поля БД на строки, потому что это потребует дополнительного кода и конверсий позже.
В моей модели я использовал before_save и attr_accessor следующим образом:
before_save :format_date
attr_accessor :unformatted_date
def format_date
self.inquiry_date = Date.strptime(self.unformatted_date, "%m/%d/%Y").to_time(:utc)
end
Строка в моем представлении выглядит следующим образом:
f.text_field :unformatted_date, :value => (@foo.inquiry_date.blank? ? '' : @foo.inquiry_date.strftime('%m/%d/%Y)), :id => 'datepicker'