База данных Rails Seed из CSV — проблема с форматом даты

(Вот моя необходимая строка о том, что я новичок в ruby/rails и программировании в целом, а также первый вопрос SO)

У меня есть задача rake, чтобы заполнить мою БД MySQL из CSV-файла.

...
    CSV.read(uri).each do |row|
      Incident.create(
        :building_address => row[9],
        :agency => row[3],
        :complaint_type => row[6],
        :descriptor => row[5],
        :created => row[1],
        :closed => row[2],
        )
end

:created и :closed определяются как поля даты (и также отделены от/не связаны с полями rails created_at и updated_at), но я предполагаю, что файлы CSV распознают только строки.

Когда я запускаю эту задачу, день и месяц меняются местами. Таким образом, 1/12/2010 12:00:00 AM в CSV (что для CSV и меня в США означает 12 января) в конечном итоге анализируется как 2010-12-1, и любой день после 12 возвращает нуль, поэтому 1/20/2010 12:00:00 AM приводит к нулевой записи в моей БД.

я добавил

date:
    formats:
        default: "%m/%d/%Y"

в мой en.yml, но это, похоже, влияет только на отображение даты и не влияет на создание объектов с помощью моей задачи rake. После поиска вокруг SO и других ресурсов я попробовал

:created => row[1].strftime,

и

:created => row[1].strptime,

но получил undefined method strptime/strftime for "Created Date":String (Дата создания - это имя столбца в CSV).

Так я тоже пробовал

:created => row[1].to_date

изменить (предположительно) строку «дата» в CSV на дату, но получить ошибку undefined method '<' for nil:NilClass

Изменение поля даты в CSV кажется невозможным, поскольку существует более 1 миллиона записей.

Как я могу отредактировать эту задачу rake, чтобы правильно заполнить мою базу данных из этого CSV? Или я должен изменить :created с даты на строку и манипулировать ею в логике приложения?


person sbauch    schedule 18.11.2011    source источник


Ответы (1)


Вы можете попробовать использовать DateTime.strptime для преобразования ваших строк в экземпляры DateTime:

:created => DateTime.strptime(row[1], '%m/%d/%Y %H:%M:%S %p'),
:closed  => DateTime.strptime(row[2], '%m/%d/%Y %H:%M:%S %p')

Метод класса strptime позволит вам точно указать формат, который вы используете, чтобы ни одному из программ не пришлось его угадывать. Я бы порекомендовал вам придерживаться форматов даты и времени ISO 8601 для внутреннего использования в будущем, оставьте двусмысленные форматы для человеческого потребления.

person mu is too short    schedule 18.11.2011
comment
Прошлой ночью пробовал это и несколько вариантов, но продолжает получать ошибку invalid date. Я подумал, может быть, потому что :created и :closed были классом Date вместо DateTime, но изменение не помогло. Я продолжу попытки сегодня вечером, а также прочитаю больше о рубиновых документах, на которые вы ссылались. - person sbauch; 19.11.2011
comment
@sbauch: какого типа столбцы :created и :closed? Это date, datetime или timestamp? Если это даты, попробуйте Date.strptime(row[1], '%m/%d/%Y') и Date.strptime(row[2], '%m/%d/%Y') игнорировать часть времени суток. - person mu is too short; 19.11.2011
comment
Я пробовал с обоими. Прямо сейчас у меня есть оба столбца как date, и я могу использовать Date.strptime('12/15/2010 12:00 AM', '%m/%d/%Y') (скопировав эту дату непосредственно из моего csv) в моей консоли. Но все еще получаю ошибку invalid date в задаче rake. - person sbauch; 19.11.2011
comment
@sbauch: Кто жалуется на неверную дату, Date или Incident? - person mu is too short; 19.11.2011
comment
Похоже, мой заголовок CSV искажал это. Спасибо за помощь! edit- Хотя я думаю, что понял это, как бы это сказать? Я получал invalid date /Users/Sam/.rvm/rubies/ruby-1.9.2-p290/lib/ruby/1.9.1/date.rb:1022:in new_by_frags' - person sbauch; 19.11.2011
comment
@sbauch: Круто. Вы Date.strptime вызываете исключение ArgumentError, когда не можете проанализировать строку; так что вы можете добавить rescue ArgumentError => e и отметить, что находится в e. - person mu is too short; 19.11.2011