# Работа с датой и временем

## Работа с датой и временем

В этом курсе вы узнаете, как использовать класс Time, чтобы представлять время, дату и продолжительность временных интервалов.

### Создание временой метки

Для начала давайте посмотрим как получить объект Time содержащий информацию о текущем либо произвольном времени:

```ruby
# Получение информации о текущей дате и времени
now = Time.now # = 2023-03- 15:43:20 +0200
# Альернативный споосб получения текущего даты и времени
now = Time.new # = 2018-10-19 15:43:20 +0200
# Получение объекта с информацией о времени за конкретный день
# формат Time.new(год, месяц, день)
custom = Time.new(2018, 1, 1) # = 2018-01-01 00:00:00 +0100
# формат Time.new(год, месяц, день, час, минута, секунда, отступ часового пояса по UTC)
custom = Time.new(2002, 10, 31, 2, 2, 2, "+02:00") # = 2002-10-31 02:02:02 +0200
zone = timezone("Europe/Moscow") # Московский часовой пояс, UTC+3
# формат Time.new(год, месяц, день, час, минута, секунда, часовой пояс по UTC)
custom = Time.new(2002, 10, 31, 2, 2, 2, zone)  # = 2002-10-31 02:02:02 +0300
# Поучение объекта Time прозводный от Timestamp (POSIX-время, количество секунд прошедшее с 00:00:00 UTC 1 января, 1970 года)
custom = Time.at(15000000000) # = 2017-07-14 04:40:00 +0200
```

### Форматирование времени

За частую, во время работы со временем нам нужно превращать его в строку, либо наборот, превращать строку в метку времени.

Для того, чтобы перевести Time в строковое представление используется метод `.strftime(format)` в который передается формат записи времени. Так как форматов записи может быть огромное множество, то был создан способ описания формата времени:

* %Y - год в формате с 4-мя цифрами (например, 2022)
* %m - номер месяца с предваряющим нулем (например, 01 для января)
* %d - день месяца с предваряющим нулем (например, 01)
* %H - часы в 24-часовом формате с предваряющим нулем (например, 02 для 2 часов утра или 2 часов дня)
* %M - минуты с предваряющим нулем
* %S - секунды с предваряющим нулем
* %z - Часов

Это лишь список наиболее часто используемых форматов, более подробное описание форматов можете поискать сами по необходимости.

Кроме того, эти форматы мы можем комбинировать между собой как это показано в примере ниже:

```ruby
time = Time.new(2022, 1, 1, 11, 20, 35)
puts time.strftime("%d/%m/%Y - %H:%M") # = 01/01/2022 - 11:20
puts time.strftime("%m.%y %H:%M:S") # = 01.2022 11:20:35
```

Для того, чтобы нам теперь перевести строку в метку времени нам необходимо расширить возможности класса `Time` с помощью добавления `require 'time'` в самом начале нашего `.rb` файла, после чего мы сможем воспользоваться конструкцией `Time.strptime(str, format)`. В качестве первого аргумента мы передаем строкове представление метки времени (например `"01/01/2022 - 11:20"`), а в качестве формата мы передаем формат записи (например `%d/%m/%Y - %H:%M`).

```ruby
require 'time'

time = Time.new(2022, 1, 1, 11, 20, 35)
date_format = "%d/%m/%Y - %H:%M"
str_time = time.strftime(date_format) # метод возвращает строковое представление 
puts str_time # = "01/01/2022 - 11:20"
decoded_dtime = Time.strptime(str_time, date_format) # метод возвращает метку времени 
p decoded_dtime # = Time ( 2022-01-01 11:20:00 +0300 )
```

Помимо прочего существует конструкция `Time.parse(str)`, которая автоматически подбирает формат из предстановленных спецификаций RFC, но во первых, далеко не любой формат так можно распарсить, а во вторых, этот метод парсит строку с помощью перебоора формата: попробовал распарсить - не получилось - пробует еще раз с другим форматом и так до тех пора, пока не получится. Указывая формат напрямую мы избавляемся от лишних действий6 которые за нас сделает сам язык.

### Арифметические операции со временем

Хорошо, мы научились создавать метку времени, научились превращать ее в строку, теперь стоит изучить способы манипуляции со временем.

У метки времени есть возможность прибавлять и убавлять время с помощью привычных для нас операторов `-` и `+`. Обратите внимание, прибавляются **секунды**.

```ruby
time = Time.new(2022, 1, 1, 11, 20, 35)
puts time.strftime("%%d/m/%y %H:%M:S") # = "01/01/2022 - 11:20:35"
# альтернатвная запись выражения time = time + 5
time += 5
puts time.strftime("%%d/m/%y %H:%M:S") # = "01/01/2022 - 11:20:40"
# альтернатвная запись выражения time = time - 2
time -= 2
puts time.strftime("%%d/m/%y %H:%M:S") # = "01/01/2022 - 11:20:38"
```

### Вычисление разницы между двумя временами

Также мы можем вычитать метки времени между собой для нахождения разницы между ними в **секундах**

```ruby
start = Time.new(2022, 1, 1, 11, 20, 35)
finish = Time.new(2022, 1, 1, 11, 20, 40)

puts finish - start # 5
```

Вычитание одной метки времени и другой - это излюбленный способ для замера продолжительности выполнения время выполнения кода

```ruby
start = Time.now
sleep(5) # заставляем программу 'засыпать' на 5 секунд
finish = Time.now
puts finish - start # = 5.0... секунд
```

## Задание birthdays

Реализуйте метод `collect_birthdays(year, month, day)`, который будет печатать в консоль ваш возраст, дата дня рождения и день недели вашего дня рождения

Как это должно выглядеть:

```ruby
  collect_birthdays(1997, 12, 1)

  # 0 - 01.12.1997 - Monday
  # 1 - 01.12.1998 - Tuesday
  # 2 - 01.12.1999 - Wednesday
  # ...
  # 25 - 01.12.2022 - Thursday
```

### Дополнительный материал

* [Работа со временем и датой](https://www.rubyguides.com/2015/12/ruby-time/)
* [официальная документация по Time](https://ruby-doc.org/3.2.1/Time.html)
* [Еще одна документация по Time из stdlib](https://ruby-doc.org/3.2.1/stdlibs/time/Time.html)
* [Официальная документация по форматированию](https://ruby-doc.org/3.2.1/strftime_formatting_rdoc.html)


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://evgenii-afanasev.gitbook.io/ruby-course/2_basics/6_datetime.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
