#ruby #string
#ruby #строка
Вопрос:
Я пытаюсь использовать case
инструкцию:
week # => "03 – 09 MAR 2019"
first_day = week.slice(0..2) # => 03
last_day = week.slice(5..7) # => 09
month = week.slice(8..11) # => MAR
year = week.slice(12..17) # => 2019
puts month # >> MAR
case month
when 'JAN' then month_num = '01'
when 'FEB' then month_num = '02'
when 'MAR' then month_num = '03'
when 'APR' then month_num = '04'
when 'MAY' then month_num = '05'
when 'JUN' then month_num = '06'
when 'JUL' then month_num = '07'
when 'AGO' then month_num = '08'
when 'SEP' then month_num = '09'
when 'OCT' then month_num = '10'
when 'NOV' then month_num = '11'
when 'DEC' then month_num = '12'
else month_num = 'ERROR'
end
puts month_num # >> ERROR
Однако case
оператор всегда отправляется в else
ветку.
Почему var month_num
равен строке "ERROR"
вместо "03"
?
Ответ №1:
Вы используете puts
для проверки того, что у вас есть, и поэтому вам не хватает пробелов в ваших результатах. На самом деле у вас есть:
week.slice(0..2) # => "03 "
week.slice(5..7) # => "09 "
week.slice(8..11) # => "MAR "
week.slice(12..17) # => "2019"
Чтобы увидеть, что у вас есть, лучше использовать p
, а не puts
.
У вас неверный диапазон. На самом деле, здесь нет причин использовать диапазоны. Гораздо проще использовать второй аргумент для указания длины:
week.slice(0, 2) # => "03"
week.slice(5, 2) # => "09"
week.slice(8, 3) # => "MAR"
week.slice(12, 4) # => "2019"
Ответ №2:
Ваш month
является "MAR "
Попробуйте
month = week.slice(8..10)
И это имеет смысл, от 8 до 10 включительно — это три символа. То же самое для других частей.
Ответ №3:
Похоже, вы хотите проанализировать строку, содержащую данные в определенном формате. Вместо того чтобы полагаться на абсолютные индексы, вы могли бы использовать регулярное выражение для соответствия формату даты, например:
PATTERN = /
(?<first_day>d{2}) # 2-digit first day
s* # optional whitespace
[–-] # delimiter(s)
s*
(?<last_day>d{2}) # 2-digit last day
s*
(?<month>w{3}) # 3-letter month name
s*
(?<year>d{4}) # 4-digit year
/ix
Для извлечения данных:
str = '03 – 09 MAR 2019'
m = str.match(PATTERN)
#=> #<MatchData "03 – 09 MAR 2019" first_day:"03" last_day:"09" month:"MAR" year:"2019">
m[:first_day] #=> "03"
m[:last_day] #=> "09"
m[:month] #=> "MAR"
m[:year] #=> "2019"
Полученные результаты в дальнейшем можно было бы использовать в Date.strptime
:
require 'date'
from = m.values_at(:first_day, :month, :year).join(' ') #=> "03 MAR 2019"
to = m.values_at(:first_day, :month, :year).join(' ') #=> "09 MAR 2019"
Date.strptime(from, '%d %b %Y') #=> #<Date: 2019-03-03 ...>
Date.strptime(to, '%d %b %Y') #=> #<Date: 2019-03-09 ...>
Или _strptime
если вас интересуют только исходные значения:
Date._strptime(from, '%d %b %Y')
#=> {:mday=>3, :mon=>3, :year=>2019}