2011-05-27 58 views

回答

4
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寶石。
  • 如果你做了很多這些(就像你在解析日誌文件時經常做的那樣),不要考慮使用正則表達式。使用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) 

它需要的事實,所有領域都有固定寬度的優勢(至少我認爲他們這樣做)。所以你需要做的就是提取子字符串。它還將時區偏移量計算爲數字而不是字符串。