Когда в PostgreSQL вычитаете одну дату из другой или складываете интервалы, результат не всегда выглядит так, как ожидает человек.
База данных может честно вернуть:
36 hours;
90 days;
800 minutes;
52:30:00.
Для компьютера всё нормально: длительность посчитана правильно. Но человеку в отчёте удобнее увидеть не «52 часа», а «2 дня и 4 часа». Вот здесь и пригодится семейство функций JUSTIFY_*.
Эти функции приводят интервал к более аккуратному виду: лишние часы переносят в дни, а лишние дни — в месяцы.
Но сразу важная мысль: JUSTIFY_* не пересчитывает время по настоящему календарю. Это не волшебная функция для точного возраста, стажа или срока договора. Это скорее «косметическая уборка» интервала, чтобы он выглядел понятнее.
Например, JUSTIFY_HOURS считает просто:
24 часа = 1 день
И всё. Она не знает, был ли в этот день переход на летнее время, короткий февраль или длинный июль. Она работает с интервалом как с длительностью, а не как с реальным календарным периодом.
Что делает семейство JUSTIFY_*
В PostgreSQL есть три основные функции:
JUSTIFY_HOURS(interval) — переводит каждые 24 часа в 1 день.
JUSTIFY_DAYS(interval) — переводит каждые 30 дней в 1 месяц.
JUSTIFY_INTERVAL(interval) — делает оба переноса сразу: часы в дни, дни в месяцы, а ещё приводит знаки к более согласованному виду.
Посмотрим на простом примере:
SELECT
JUSTIFY_HOURS(INTERVAL '36 hours') AS hours_result,
JUSTIFY_DAYS(INTERVAL '90 days') AS days_result,
JUSTIFY_INTERVAL(INTERVAL '1 mon 33 days 27 hours') AS full_result;
Результат будет примерно таким:
hours_result -> 1 day 12:00:00
days_result -> 3 mons
full_result -> 2 mons 4 days 03:00:00
Разберём последний пример.
Было:
1 mon 33 days 27 hours
JUSTIFY_INTERVAL делает два шага:
27 hours превращает в 1 day 03:00:00.
33 days + 1 day превращает в 34 days.
- Из
34 days забирает 30 days и превращает их в 1 mon.
Получается:
2 mons 4 days 03:00:00
Выглядит аккуратнее и читается легче.
Важная деталь: interval — это не просто секунды
У новичков часто возникает ощущение, что интервал — это просто количество секунд, а PostgreSQL потом красиво его показывает. Но в PostgreSQL всё интереснее.
Интервал внутри хранится не одним числом, а несколькими частями:
- месяцы;
- дни;
- время, вплоть до микросекунд.
Именно поэтому 1 mon и 30 days — не совсем одно и то же. В одних ситуациях они могут выглядеть близко, но при прибавлении к реальной дате дадут разный результат.
Например, месяц от 1 февраля и месяц от 1 июля — это разные по длине периоды в днях. А 30 days — это всегда просто 30 дней.
Функции JUSTIFY_* не превращают интервал в абсолютное количество секунд. Они лишь перекладывают значения между частями интервала по простым правилам.
Пример: сколько заказ находится в обработке
Представим таблицу заказов:
SELECT
id,
created_at,
NOW() - created_at AS raw_age
FROM orders
WHERE status = 'processing';
Такой запрос показывает, сколько времени прошло с момента создания заказа.
Результат может выглядеть так:
raw_age -> 52:30:00
Технически всё правильно: заказ обрабатывается 52 часа 30 минут. Но менеджеру, который смотрит отчёт, это читать неудобно. Ему проще увидеть:
2 days 04:30:00
Используем JUSTIFY_HOURS:
SELECT
id,
JUSTIFY_HOURS(NOW() - created_at) AS readable_age
FROM orders
WHERE status = 'processing';
Теперь PostgreSQL перенесёт каждые 24 часа в дни.
Было:
52:30:00
Стало:
2 days 04:30:00
Смысл тот же, но глазами воспринимается намного лучше.
Когда использовать JUSTIFY_HOURS
JUSTIFY_HOURS полезна, когда интервал получился в часах, а вы хотите показать его в днях и часах.
Например:
SELECT JUSTIFY_HOURS(INTERVAL '80 hours') AS result;
Результат:
3 days 08:00:00
Это удобно для:
- времени обработки заказа;
- длительности задачи;
- времени простоя сервиса;
- возраста заявки в поддержке;
- любых отчётов, где «80 часов» хуже читается, чем «3 дня 8 часов».
Важно: JUSTIFY_HOURS не трогает дни и месяцы. Она занимается только часами.
Когда использовать JUSTIFY_DAYS
JUSTIFY_DAYS берёт дни и переводит каждые 30 дней в месяц.
SELECT JUSTIFY_DAYS(INTERVAL '75 days') AS result;
Результат:
2 mons 15 days
Это бывает удобно, когда нужна грубая, отчётная нормализация.
Например, мы хотим посмотреть суммарный «возраст» записей по отделам:
SELECT
dept,
JUSTIFY_DAYS(SUM(NOW() - created_at)) AS dept_age
FROM employees
GROUP BY dept;
Но здесь нужно быть осторожным. Такой результат хорош для приблизительного отчёта, но не для расчёта денег, отпусков, компенсаций или юридических сроков.
Почему? Потому что JUSTIFY_DAYS считает:
30 days = 1 mon
А настоящий календарь так не работает.
Когда использовать JUSTIFY_INTERVAL
JUSTIFY_INTERVAL — самый полный вариант. Он нормализует и часы, и дни.
SELECT JUSTIFY_INTERVAL(INTERVAL '33 days 49 hours') AS result;
Сначала 49 hours превратятся в 2 days 01:00:00.
Получится:
35 days 01:00:00
Потом 30 days превратятся в 1 mon.
Итог:
1 mon 5 days 01:00:00
Обычно JUSTIFY_INTERVAL удобно брать, когда интервал может содержать всё сразу: месяцы, дни, часы, минуты и секунды.
Например:
SELECT
name,
JUSTIFY_INTERVAL(salary_review_at - hired_at) AS service_period
FROM employees
ORDER BY service_period DESC;
Такой запрос делает вывод аккуратнее: вместо смеси больших чисел в днях и часах вы получаете более читаемый интервал.
Главная ловушка: 30 дней — это не календарный месяц
Самая опасная часть JUSTIFY_DAYS и JUSTIFY_INTERVAL — правило про 30 дней.
Для этих функций:
30 days = 1 mon
Но в реальной жизни месяцы разные:
- в феврале 28 или 29 дней;
- в апреле 30 дней;
- в июле 31 день.
Поэтому такой результат может обмануть:
SELECT JUSTIFY_INTERVAL(INTERVAL '60 days') AS result;
PostgreSQL вернёт:
2 mons
Но это не значит «два настоящих календарных месяца» от какой-то даты. Это значит только:
60 days = 2 * 30 days
То есть JUSTIFY_INTERVAL не знает, от какой даты вы считаете. А без начальной даты невозможно понять, сколько дней было в конкретных месяцах.
JUSTIFY_* и AGE: в чём разница
Для человекочитаемой нормализации интервала используйте JUSTIFY_*.
Для календарного возраста между двумя датами используйте AGE.
Сравним идею:
SELECT
AGE(TIMESTAMP '2024-03-01', TIMESTAMP '2024-02-01') AS calendar_age,
JUSTIFY_INTERVAL(INTERVAL '29 days') AS justified_interval;
AGE смотрит на реальные даты. Она понимает, что между 1 февраля 2024 года и 1 марта 2024 года прошёл календарный месяц, потому что 2024 год был високосным.
А JUSTIFY_INTERVAL смотрит только на сам интервал. Для неё 29 days — это просто 29 дней. До месяца не хватает, потому что по её правилу месяц равен 30 дням.
Запомнить можно так:
AGE отвечает на вопрос:
Сколько прошло по календарю между двумя датами?
JUSTIFY_* отвечает на другой вопрос:
Как красивее разложить этот интервал на месяцы, дни и часы?
Это разные задачи.
Где JUSTIFY_* использовать безопасно
Функции JUSTIFY_* хорошо подходят для последнего шага — вывода результата на экран.
Например:
SELECT
id,
JUSTIFY_HOURS(NOW() - created_at) AS readable_processing_time
FROM orders
WHERE status = 'processing';
Здесь мы не принимаем финансовое или юридическое решение. Мы просто показываем пользователю длительность в удобном виде.
Хорошие сценарии:
- отчёты;
- дашборды;
- внутренние админки;
- человекочитаемые подписи;
- приблизительная аналитика;
- вывод длительности задач, заказов, тикетов.
Плохие сценарии:
- расчёт зарплаты;
- расчёт отпусков;
- расчёт штрафов;
- расчёт стажа для выплат;
- юридические сроки;
- точные календарные дедлайны.
В таких случаях лучше считать через реальные даты, AGE, прямую разницу дат или бизнес-логику, где явно прописаны правила.
Почему не стоит нормализовать слишком рано
Распространённая ошибка — применить JUSTIFY_* в середине расчётов, а потом использовать результат дальше.
Например, так делать опасно:
SELECT
dept,
SUM(JUSTIFY_DAYS(NOW() - hired_at)) AS total_service
FROM employees
GROUP BY dept;
Проблема в том, что вы сначала превращаете каждые 30 дней в условный месяц для каждого сотрудника, а потом суммируете эти условные месяцы. Ошибка может накопиться.
Лучше сначала выполнить расчёт, а нормализацию оставить на финальный вывод:
SELECT
dept,
JUSTIFY_DAYS(SUM(NOW() - hired_at)) AS total_service
FROM employees
GROUP BY dept;
Даже этот вариант подходит скорее для отчётной оценки, а не для точных выплат. Но принцип правильный: сначала считаем, потом красиво показываем.
Отрицательные интервалы
JUSTIFY_INTERVAL также полезна, когда в интервале появляются смешанные знаки.
Например, интервал может выглядеть странно: месяц в одну сторону, дни или часы — в другую. JUSTIFY_INTERVAL старается привести такой интервал к более согласованному виду.
SELECT JUSTIFY_INTERVAL(INTERVAL '1 mon -1 hour') AS result;
Результат будет нормализован так, чтобы интервал выглядел логичнее для чтения.
С отрицательными интервалами особенно важно проверять граничные случаи. Если вы переносите такую логику в другую СУБД или пишете ручную нормализацию, обязательно проверьте:
- ровно
24 hours;
- ровно
30 days;
- отрицательные значения;
- интервалы, где есть месяцы, дни и часы одновременно.
Именно на таких местах чаще всего появляются расхождения.
Аналоги в MySQL и ClickHouse
JUSTIFY_* — это особенность PostgreSQL. В других популярных СУБД прямых аналогов обычно нет.
В MySQL нет такого же полноценного типа interval, как в PostgreSQL. Часто длительность считают в секундах или днях, а потом вручную раскладывают по частям.
Например, если у вас есть количество секунд, дни можно получить так:
SELECT
seconds_value DIV 86400 AS days_part,
seconds_value MOD 86400 AS rest_seconds
FROM durations;
Здесь 86400 — количество секунд в сутках.
В ClickHouse часто используют функции вроде dateDiff, а затем тоже раскладывают результат вручную:
SELECT
dateDiff('day', started_at, finished_at) AS days_count
FROM events;
Если нужно получить отдельно месяцы, дни и часы, правила придётся описывать самостоятельно.
И здесь важно помнить: как только вы пишете ручную нормализацию, вы сами отвечаете за правила. Особенно за то, что считать месяцем, как округлять значения и что делать с отрицательными интервалами.
Практическое правило
Используйте JUSTIFY_*, когда хотите сделать интервал красивым и понятным для человека.
Не используйте JUSTIFY_*, когда от результата зависят деньги, сроки, права, дедлайны или точные календарные вычисления.
Хорошая привычка:
- Сначала честно посчитать интервал.
- Выполнить нужные проверки и бизнес-расчёты.
- Только в самом конце применить
JUSTIFY_HOURS, JUSTIFY_DAYS или JUSTIFY_INTERVAL для вывода.
Пример:
SELECT
id,
created_at,
NOW() - created_at AS raw_age,
JUSTIFY_HOURS(NOW() - created_at) AS readable_age
FROM orders
WHERE status = 'processing';
Так вы видите и исходную длительность, и красивую версию для отчёта.
Главное
JUSTIFY_* в PostgreSQL — это семейство функций для нормализации интервалов.
JUSTIFY_HOURS переносит часы в дни:
36 hours -> 1 day 12:00:00
JUSTIFY_DAYS переносит дни в месяцы по правилу 30 дней:
90 days -> 3 mons
JUSTIFY_INTERVAL делает оба переноса сразу:
1 mon 33 days 27 hours -> 2 mons 4 days 03:00:00
Главное — не путать красивый вывод с точной календарной арифметикой.
JUSTIFY_* не знает реальный календарь. Для неё месяц — это 30 дней, а день — это 24 часа. Поэтому она отлично подходит для отчётов, но не подходит для точного расчёта стажа, выплат, отпусков и юридических сроков.
Для календарной разницы между датами используйте AGE или явную бизнес-логику. А JUSTIFY_* оставьте там, где она действительно хороша: на последнем шаге, когда нужно показать интервал человеку красиво и понятно.
Когда в PostgreSQL вычитаете одну дату из другой или складываете интервалы, результат не всегда выглядит так, как ожидает человек.
База данных может честно вернуть:
36 hours;90 days;800 minutes;52:30:00.Для компьютера всё нормально: длительность посчитана правильно. Но человеку в отчёте удобнее увидеть не «52 часа», а «2 дня и 4 часа». Вот здесь и пригодится семейство функций
JUSTIFY_*.Эти функции приводят интервал к более аккуратному виду: лишние часы переносят в дни, а лишние дни — в месяцы.
Но сразу важная мысль:
JUSTIFY_*не пересчитывает время по настоящему календарю. Это не волшебная функция для точного возраста, стажа или срока договора. Это скорее «косметическая уборка» интервала, чтобы он выглядел понятнее.Например,
JUSTIFY_HOURSсчитает просто:И всё. Она не знает, был ли в этот день переход на летнее время, короткий февраль или длинный июль. Она работает с интервалом как с длительностью, а не как с реальным календарным периодом.
Что делает семейство JUSTIFY_*
В PostgreSQL есть три основные функции:
JUSTIFY_HOURS(interval)— переводит каждые 24 часа в 1 день.JUSTIFY_DAYS(interval)— переводит каждые 30 дней в 1 месяц.JUSTIFY_INTERVAL(interval)— делает оба переноса сразу: часы в дни, дни в месяцы, а ещё приводит знаки к более согласованному виду.Посмотрим на простом примере:
SELECT JUSTIFY_HOURS(INTERVAL '36 hours') AS hours_result, JUSTIFY_DAYS(INTERVAL '90 days') AS days_result, JUSTIFY_INTERVAL(INTERVAL '1 mon 33 days 27 hours') AS full_result;Результат будет примерно таким:
hours_result -> 1 day 12:00:00 days_result -> 3 mons full_result -> 2 mons 4 days 03:00:00Разберём последний пример.
Было:
1 mon 33 days 27 hoursJUSTIFY_INTERVALделает два шага:27 hoursпревращает в1 day 03:00:00.33 days + 1 dayпревращает в34 days.34 daysзабирает30 daysи превращает их в1 mon.Получается:
2 mons 4 days 03:00:00Выглядит аккуратнее и читается легче.
Важная деталь: interval — это не просто секунды
У новичков часто возникает ощущение, что интервал — это просто количество секунд, а PostgreSQL потом красиво его показывает. Но в PostgreSQL всё интереснее.
Интервал внутри хранится не одним числом, а несколькими частями:
Именно поэтому
1 monи30 days— не совсем одно и то же. В одних ситуациях они могут выглядеть близко, но при прибавлении к реальной дате дадут разный результат.Например, месяц от 1 февраля и месяц от 1 июля — это разные по длине периоды в днях. А
30 days— это всегда просто 30 дней.Функции
JUSTIFY_*не превращают интервал в абсолютное количество секунд. Они лишь перекладывают значения между частями интервала по простым правилам.Пример: сколько заказ находится в обработке
Представим таблицу заказов:
SELECT id, created_at, NOW() - created_at AS raw_age FROM orders WHERE status = 'processing';Такой запрос показывает, сколько времени прошло с момента создания заказа.
Результат может выглядеть так:
raw_age -> 52:30:00Технически всё правильно: заказ обрабатывается 52 часа 30 минут. Но менеджеру, который смотрит отчёт, это читать неудобно. Ему проще увидеть:
2 days 04:30:00Используем
JUSTIFY_HOURS:SELECT id, JUSTIFY_HOURS(NOW() - created_at) AS readable_age FROM orders WHERE status = 'processing';Теперь PostgreSQL перенесёт каждые 24 часа в дни.
Было:
52:30:00Стало:
2 days 04:30:00Смысл тот же, но глазами воспринимается намного лучше.
Когда использовать JUSTIFY_HOURS
JUSTIFY_HOURSполезна, когда интервал получился в часах, а вы хотите показать его в днях и часах.Например:
SELECT JUSTIFY_HOURS(INTERVAL '80 hours') AS result;Результат:
3 days 08:00:00Это удобно для:
Важно:
JUSTIFY_HOURSне трогает дни и месяцы. Она занимается только часами.Когда использовать JUSTIFY_DAYS
JUSTIFY_DAYSберёт дни и переводит каждые 30 дней в месяц.SELECT JUSTIFY_DAYS(INTERVAL '75 days') AS result;Результат:
2 mons 15 daysЭто бывает удобно, когда нужна грубая, отчётная нормализация.
Например, мы хотим посмотреть суммарный «возраст» записей по отделам:
SELECT dept, JUSTIFY_DAYS(SUM(NOW() - created_at)) AS dept_age FROM employees GROUP BY dept;Но здесь нужно быть осторожным. Такой результат хорош для приблизительного отчёта, но не для расчёта денег, отпусков, компенсаций или юридических сроков.
Почему? Потому что
JUSTIFY_DAYSсчитает:30 days = 1 monА настоящий календарь так не работает.
Когда использовать JUSTIFY_INTERVAL
JUSTIFY_INTERVAL— самый полный вариант. Он нормализует и часы, и дни.SELECT JUSTIFY_INTERVAL(INTERVAL '33 days 49 hours') AS result;Сначала
49 hoursпревратятся в2 days 01:00:00.Получится:
35 days 01:00:00Потом
30 daysпревратятся в1 mon.Итог:
1 mon 5 days 01:00:00Обычно
JUSTIFY_INTERVALудобно брать, когда интервал может содержать всё сразу: месяцы, дни, часы, минуты и секунды.Например:
SELECT name, JUSTIFY_INTERVAL(salary_review_at - hired_at) AS service_period FROM employees ORDER BY service_period DESC;Такой запрос делает вывод аккуратнее: вместо смеси больших чисел в днях и часах вы получаете более читаемый интервал.
Главная ловушка: 30 дней — это не календарный месяц
Самая опасная часть
JUSTIFY_DAYSиJUSTIFY_INTERVAL— правило про 30 дней.Для этих функций:
30 days = 1 monНо в реальной жизни месяцы разные:
Поэтому такой результат может обмануть:
SELECT JUSTIFY_INTERVAL(INTERVAL '60 days') AS result;PostgreSQL вернёт:
2 monsНо это не значит «два настоящих календарных месяца» от какой-то даты. Это значит только:
60 days = 2 * 30 daysТо есть
JUSTIFY_INTERVALне знает, от какой даты вы считаете. А без начальной даты невозможно понять, сколько дней было в конкретных месяцах.JUSTIFY_* и AGE: в чём разница
Для человекочитаемой нормализации интервала используйте
JUSTIFY_*.Для календарного возраста между двумя датами используйте
AGE.Сравним идею:
SELECT AGE(TIMESTAMP '2024-03-01', TIMESTAMP '2024-02-01') AS calendar_age, JUSTIFY_INTERVAL(INTERVAL '29 days') AS justified_interval;AGEсмотрит на реальные даты. Она понимает, что между 1 февраля 2024 года и 1 марта 2024 года прошёл календарный месяц, потому что 2024 год был високосным.А
JUSTIFY_INTERVALсмотрит только на сам интервал. Для неё29 days— это просто 29 дней. До месяца не хватает, потому что по её правилу месяц равен 30 дням.Запомнить можно так:
AGEотвечает на вопрос:JUSTIFY_*отвечает на другой вопрос:Это разные задачи.
Где JUSTIFY_* использовать безопасно
Функции
JUSTIFY_*хорошо подходят для последнего шага — вывода результата на экран.Например:
SELECT id, JUSTIFY_HOURS(NOW() - created_at) AS readable_processing_time FROM orders WHERE status = 'processing';Здесь мы не принимаем финансовое или юридическое решение. Мы просто показываем пользователю длительность в удобном виде.
Хорошие сценарии:
Плохие сценарии:
В таких случаях лучше считать через реальные даты,
AGE, прямую разницу дат или бизнес-логику, где явно прописаны правила.Почему не стоит нормализовать слишком рано
Распространённая ошибка — применить
JUSTIFY_*в середине расчётов, а потом использовать результат дальше.Например, так делать опасно:
SELECT dept, SUM(JUSTIFY_DAYS(NOW() - hired_at)) AS total_service FROM employees GROUP BY dept;Проблема в том, что вы сначала превращаете каждые 30 дней в условный месяц для каждого сотрудника, а потом суммируете эти условные месяцы. Ошибка может накопиться.
Лучше сначала выполнить расчёт, а нормализацию оставить на финальный вывод:
SELECT dept, JUSTIFY_DAYS(SUM(NOW() - hired_at)) AS total_service FROM employees GROUP BY dept;Даже этот вариант подходит скорее для отчётной оценки, а не для точных выплат. Но принцип правильный: сначала считаем, потом красиво показываем.
Отрицательные интервалы
JUSTIFY_INTERVALтакже полезна, когда в интервале появляются смешанные знаки.Например, интервал может выглядеть странно: месяц в одну сторону, дни или часы — в другую.
JUSTIFY_INTERVALстарается привести такой интервал к более согласованному виду.SELECT JUSTIFY_INTERVAL(INTERVAL '1 mon -1 hour') AS result;Результат будет нормализован так, чтобы интервал выглядел логичнее для чтения.
С отрицательными интервалами особенно важно проверять граничные случаи. Если вы переносите такую логику в другую СУБД или пишете ручную нормализацию, обязательно проверьте:
24 hours;30 days;Именно на таких местах чаще всего появляются расхождения.
Аналоги в MySQL и ClickHouse
JUSTIFY_*— это особенность PostgreSQL. В других популярных СУБД прямых аналогов обычно нет.В MySQL нет такого же полноценного типа
interval, как в PostgreSQL. Часто длительность считают в секундах или днях, а потом вручную раскладывают по частям.Например, если у вас есть количество секунд, дни можно получить так:
SELECT seconds_value DIV 86400 AS days_part, seconds_value MOD 86400 AS rest_seconds FROM durations;Здесь
86400— количество секунд в сутках.В ClickHouse часто используют функции вроде
dateDiff, а затем тоже раскладывают результат вручную:SELECT dateDiff('day', started_at, finished_at) AS days_count FROM events;Если нужно получить отдельно месяцы, дни и часы, правила придётся описывать самостоятельно.
И здесь важно помнить: как только вы пишете ручную нормализацию, вы сами отвечаете за правила. Особенно за то, что считать месяцем, как округлять значения и что делать с отрицательными интервалами.
Практическое правило
Используйте
JUSTIFY_*, когда хотите сделать интервал красивым и понятным для человека.Не используйте
JUSTIFY_*, когда от результата зависят деньги, сроки, права, дедлайны или точные календарные вычисления.Хорошая привычка:
JUSTIFY_HOURS,JUSTIFY_DAYSилиJUSTIFY_INTERVALдля вывода.Пример:
SELECT id, created_at, NOW() - created_at AS raw_age, JUSTIFY_HOURS(NOW() - created_at) AS readable_age FROM orders WHERE status = 'processing';Так вы видите и исходную длительность, и красивую версию для отчёта.
Главное
JUSTIFY_*в PostgreSQL — это семейство функций для нормализации интервалов.JUSTIFY_HOURSпереносит часы в дни:36 hours -> 1 day 12:00:00JUSTIFY_DAYSпереносит дни в месяцы по правилу 30 дней:90 days -> 3 monsJUSTIFY_INTERVALделает оба переноса сразу:1 mon 33 days 27 hours -> 2 mons 4 days 03:00:00Главное — не путать красивый вывод с точной календарной арифметикой.
JUSTIFY_*не знает реальный календарь. Для неё месяц — это 30 дней, а день — это 24 часа. Поэтому она отлично подходит для отчётов, но не подходит для точного расчёта стажа, выплат, отпусков и юридических сроков.Для календарной разницы между датами используйте
AGEили явную бизнес-логику. АJUSTIFY_*оставьте там, где она действительно хороша: на последнем шаге, когда нужно показать интервал человеку красиво и понятно.