7.20. Извлечение даты и времени из строки
7.20. Извлечение даты и времени из строки
Дата и время могут быть представлены в виде строки самыми разными способами: в полной или сокращенной форме, с разной пунктуацией, различным порядком компонентов и т.д. Из-за такого разнообразия очень сложно написать код, интерпретирующий символьную строку как дату. Рассмотрим несколько примеров:
s1 = "9/13/98 2:15am"
s2 = "1961-05-31"
s3 = "11 July 1924"
s4 = "April 17, 1929"
s5 = "20 July 1969 16:17 EDT"
s6 = "Mon Nov 13 2000"
s7 = "August 24, 79" # День разрушения Помпеи.
s8 = "8/24/79"
К счастью, большую часть работы за нас уже проделали. В модуле ParseDate есть единственный класс с таким же именем, а в нем — единственный метод parsedate. Он возвращает массив компонентов даты в следующем порядке: год, месяц, день, час, минута, секунда, часовой пояс, день недели. Вместо полей, которые не удалось распознать, возвращается nil.
require "parsedate.rb"
include ParseDate
p parsedate(s1) # [98, 9, 13, 2, 15, nil, nil, nil]
p parsedate(s2) # [1961, 5, 31, nil, nil, nil, nil, nil]
p parsedate(s3) # [1924, 7, 11, nil, nil, nil, nil, nil]
p parsedate(s4) # [1929, 4, 17, nil, nil, nil, nil, nil]
p parsedate(s5) # [1969, 7, 20, 16, 17, nil, "EDT", nil]
p parsedate(s6) # [2000, 11, 13, nil, nil, nil, nil, 1]
p parsedate(s7) # [79, 8, 24, nil, nil, nil, nil, nil]
p parsedate(s8,true) # [1979, 8, 24, nil, nil, nil, nil, nil]
Последние две строки иллюстрируют назначение второго параметра parsedate, который называется guess_year. Из-за привычки записывать год двумя цифрами может возникнуть неоднозначность. Последние две строки интерпретируются по-разному; при разборе s8 мы установили значение guess_year равным true, вследствие чего программа сочла, что имеется в виду четырехзначный год. С другой стороны, s7 — это дата извержения Везувия в 79 году, так что двузначный год был употреблен сознательно.
Правило применения параметра guess_year таково: если год меньше 100 и guess_year равно true, преобразовать в четырехзначный год. Преобразование выполняется так: если год больше либо равен 70, прибавить к нему 1900, в противном случае прибавить 2000. Таким образом, 75 преобразуется в 1975, а 65 — в 2065. Такое правило применяется программистами повсеместно.
А что сказать о строке s1, в которой, вероятно, имелся в виду 1998 год? Не все потеряно, если полученное число передается другому фрагменту программы, который интерпретирует его как 1998.
Учтите, что parsedate практически не контролирует ошибки. Например, если подать ему на вход дату, в которой день недели установлен некорректно, то он несоответствия не обнаружит. Это всего лишь анализатор — со своей работой он справляется неплохо, а требовать от него большего было бы неправильно.
Следует особо отметить склонность этого кода к «американизмам». Когда американец пишет 3/4/2001, он обычно имеет в виду 4 марта 2001 года. В Европе и большинстве других мест это означает 3 апреля. Но если при записи всех дат применяется одно и то же соглашение, ничего страшного не произойдет. Ведь возвращается просто массив, и ничто не мешает вам мысленно переставить первый и второй элементы. Кстати, имейте в виду, что вышеописанным образом интерпретируется даже такая дата, как 15/3/2000, хотя нам совершенно очевидно, что 15 — это день, а не месяц. Метод же parsedate «на голубом глазу» сообщит, что 15 — номер месяца!..
Данный текст является ознакомительным фрагментом.