Как вы храните строку в MongoDB как тип Date, используя Ruby? - PullRequest
1 голос
/ 27 мая 2011

У меня есть строка, которую я анализирую из файлов журнала, которая выглядит следующим образом:

"[22 / May / 2011: 23: 02: 21 +0000]"

Каков наилучший способ (примеры в Ruby были бы наиболее полезны, так как я использую драйвер Mongo Ruby), чтобы хранить его в MongoDB как собственный тип Date?

1 Ответ

4 голосов
/ 27 мая 2011
require 'date' # this is just to get the ABBR_MONTHNAMES list

input = "[22/May/2011:23:02:21 +0000]"
# this regex captures the numbers and month name
pattern = %r{^\[(\d{2})/(\w+)/(\d{4}):(\d{2}):(\d{2}):(\d{2}) ([+-]\d{4})\]$}
match = input.match(pattern)
# MatchData can be splatted, which is very convenient
_, date, month_name, year, hour, minute, second, tz_offset = *match
# ABBR_MONTHNAMES contains "Jan", "Feb", etc.
month = Date::ABBR_MONTHNAMES.index(month_name)
# we need to insert a colon in the tz offset, because Time.new expects it
tz = tz_offset[0,3] + ':' + tz_offset[3,5]
# this is your time object, put it into Mongo and it will be saved as a Date
Time.new(year.to_i, month, date.to_i, hour.to_i, minute.to_i, second.to_i, tz)

Несколько замечаний:

  • Я предположил, что названия месяцев такие же, как в списке ABBR_MONTHNAMES, в противном случае просто создайте свой собственный список.
  • Никогда не используйте Date.parse для анализа дат, это невероятно медленно, то же самое относится к DateTime.parse, Time.parse, которые используют ту же реализацию.
  • Если вы анализируете много разных форматов дат, посмотрите home_run gem.
  • Если вы делаете многие из них (как вы часто делаете при разборе файлов журналов), не используйте регулярное выражение. Используйте String#index, #[] и #split для извлечения необходимых деталей.

Если вы хотите сделать это как можно быстрее, возможно, вам подойдет что-то вроде следующего. Он не использует регулярные выражения (которые полезны, но не быстро):

date = input[1, 2].to_i
month_name = input[4, 3]
month = Date::ABBR_MONTHNAMES.index(month_name)
year = input[8, 4].to_i
hour = input[13, 2].to_i
minute = input[16, 2].to_i
second = input[19, 2].to_i
tz_offset = input[22, 3].to_i * 60 * 60 + input[25, 2].to_i * 60
Time.new(year, month, date, hour, minute, second, tz_offset)

Используется тот факт, что все поля имеют фиксированную ширину (по крайней мере, я предполагаю, что они имеют). Так что все, что вам нужно сделать, это извлечь подстроки. Он также вычисляет смещение часового пояса в виде числа вместо строки.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...