Главная Обратная связь

Дисциплины:






Листинг 7.1. Вычисление n-ого дня недели в месяце



def nth_wday(n, wday, month, year)

if (!n.between? 1,5) or

(!wday.between? 0,6) or

(!month.between? 1,12) raise ArgumentError

end

t = Time.local year, month, 1

first = t.wday

if first == wday

fwd = 1

elsif first < wday

fwd = wday - first + 1

elsif first > wday

fwd = (wday+7) - first + 1

end

target = fwd + (n-1)*7

begin

t2 = Time.local year, month, target

rescue ArgumentError

return nil

end

if t2.mday == target

t2

else

nil

end

end

Странный код в конце текста метода призван скорректировать давнюю традицию, принятую в функциях работы с датами. Если вы думаете, что попытка создать объект для представления 31 ноября приведет к ошибке, то разочарую вас. Почти все системы молчаливо преобразуют эту дату в 1 декабря. Если вы давным-давно программируете в UNIX, то, наверное, полагаете, что так и должно быть. Другие сочтут это ошибкой.

Не станем спорить о том, что должна делать системная библиотека и должен ли Ruby изменить это поведение. Но мы не хотим, чтобы наша процедура продолжала эту традицию. Если вы ищете, к примеру, пятую пятницу в ноябре 2000 года, то она вернет nil (а не 1 декабря 2000 года).

Преобразование из секунд в более крупные единицы

Иногда нужно преобразовать заданное число секунд в дни, часы, минуты и секунды. Это можно сделать следующим образом:

def sec2dhms(seсs)

time = seсs.round # Отбрасываем микросекунды.

sec = time % 60 # Извлекаем секунды.

time /= 60 # Отбрасываем секунды.

mins = time % 60 # Извлекаем минуты.

time /= 60 # Отбрасываем минуты.

hrs = time % 24 # Извлекаем часы.

time /= 24 # Отбрасываем часы.

days = time # Дни (последний остаток).

[days, hrs, mins, sec] # Возвращаем массив [d,h,m,s].

end

 

t = sec2dhms(1000000) # Миллион секунд равно...

 

puts "#{t[0]} days," # 11 дней,

puts "#{t[1]} hours," # 13 часов,

puts "#{t[2]} minutes," # 46 минут

puts " and #{t[3]} seconds." # и 40 секунд.

Можно было пойти и дальше. Но неделю вряд ли назовешь полезной единицей, месяц не слишком точно определен, а год не всегда содержит одно и то же число дней.

Ниже приведена также обратная функция:

def dhms2sec(days,hrs=0,min=0,sec=0)

days*86400 + hrs*3600 + min*60 + sec

end

Вычисление промежутка времени, прошедшего от точки отсчета

По разным причинам может понадобиться перейти от внутреннего (традиционного) представления времени к стандартному. В системе время хранится как число секунд, прошедших с точки отсчета.

Метод класса Time.at создает новый объект Time, зная, сколько секунд прошло с точки отсчета:



epoch = Time.at(0) # Найти точку отсчета (1 января 1970 GMT)

newmil = Time.at(978307200) # Счастливого миллениума! (1 января 2001)

Обратная функция — это метод экземпляра to_i, который преобразует дату в целое число.

now = Time.now # 16 Nov 2000 17:24:28

sec = now.to_i # 974424268

Если нужны микросекунды, и система поддерживает такую точность, то можно воспользоваться методом to_f для преобразования в число с плавающей точкой.

Високосные секунды

Вот снова день исчез, как ветра легкий стон,

Из нашей жизни, друг, навеки выпал он.

Но я, покуда жив, тревожиться не стану

О дне, что отошел, и дне, что не рожден.[10]

Омар Хайям, «Рубаи»

Хотите иметь дело с «високосными» секундами? Мой совет: не делайте этого.

Високосные секунды — это не миф. Одна была добавлена в 2005 году; его последняя минута состояла из 61 секунды, а не из 60. Библиотечные функции уже много лет учитывают возможность появления минут, состоящих из 61 секунды. Но наш опыт показывает, что большинство операционных систем високосные секунды игнорирует. Говоря «большинство», мы имеем в виду все, с которыми когда-либо сталкивались.

Известно, например, что високосная секунда была добавлена в конец последнего дня 1998 года. Вслед за моментом 23:59:59 наступил редкий момент 23:59:60. Но стандартная библиотека языка С, которой пользуется Ruby, этого в расчет не принимает.

t0 = Time.gm(1998, 12, 31, 23, 59, 59)

t1 = t0 + 1

puts t1 # Fri Jan 01 00:00:00 GMT 1999

Быть может (хотя и маловероятно), Ruby скорректирует эту ситуацию. Но во время работы над данной книгой таких планов не было.





sdamzavas.net - 2019 год. Все права принадлежат их авторам! В случае нарушение авторского права, обращайтесь по форме обратной связи...