Книга: Программирование на языке Ruby

3.14.5 Сопоставление с датой и временем

3.14.5 Сопоставление с датой и временем

Пусть надо выделить дату и время, записанные в формате mm/dd/yy hh:mm:ss. Вот первая попытка: datetime = /(dd)/(dd)/(dd) (dd): (dd): (dd)/.

Но такой образец распознает некоторые некорректные даты и отвергает правильные. Следующий вариант более избирателен. Обратите внимание, как мы строим его путем интерполяции мелких регулярных выражений в более крупное:

mo = /(0?[1-9]|1[0-2])/         # От 01 до 09 или от 1 до 9 или 10-12.
dd = /([0-2]?[1-9]| [1-3][01])/ # 1-9 или 01-09 или 11-19 и т.д.
yy = /(dd)/ # 00-99
hh = /([01]?[1-9]|[12][0-4])/   # 1-9 или 00-09 или...
mi = /([0-5]d)/                # 00-59, обе цифры должны присутствовать.
ss = /([0-6]d)?/               # разрешены еще и доли секунды ;-)
date = /(#{mo}/#{dd}/#{yy})/
time = /{#{hh}:#{mi}:#{ss})/
datetime = /(#{date} #{time})/

Вот как можно вызвать это регулярное выражение из метода String#scan, чтобы получить массив соответствий:

str="Recorded on 11/18/07 20:31:00"
str.scan(datetime)
# [["11/18/07 20:31:00", "11/18/07", "11", "18", "00",
# "20:31:00", "20", "31", ":00"]]

Разумеется, все это можно было сделать с помощью одного большого регулярного выражения:

datetime = %r{(
 (0?[1-9]|1[0-2])/        # mo: от 01 до 09 или от 1 до 9 или 10-12.
 ([0-2]?[1-9]|[1-3][01])/ # dd: 1-9 или 01-09 или 11-19 и т. д.
 (dd) [ ]               # yy: 00-99
 ([01]?[1-9]|[12][0-4]):  # hh: 1-9 или 00-09 или...
 ([0-5]d):               # mm: 00-59, обе цифры должны присутствовать.
 (([0-6]d))?             # ss: разрешены еще и доли секунды ;-)
)}x

Обратите внимание на конструкцию %r{}, позволяющую не экранировать символы обратной косой черты.

Оглавление книги


Генерация: 1.164. Запросов К БД/Cache: 3 / 0
поделиться
Вверх Вниз