Найти в Дзене
Блокнот математика

Рубрика "Секреты Вим". Даты и календари

Привет, коллеги. Сегодня, в преддверии Нового Года, поговорим о датах и календарях. Вим здесь будет скорее как повод.

Впрочем, мы уже обсуждали способ реализовать арифметику дат в Вим. Это несложно сделать с помощью внешней утилиты date (я всегда исхожу из того, что у Вас Линукс или другая POSIX-совместимая система). Давайте обсудим эту утилиту поподробнее, а еще я расскажу про утилиту cal (как вариант, ncal): она выводит календарь.

Всё это в контексте Вим, так что распланировать отпуск Вам будет предельно легко.

Начнем с того, что вставить в Вим выдачу в поток STDOUT ("на экран", если вы новичок) от любой внешней программы можно с помощью команды :r с применением восклицательного знака (который не часть команды, как это часто бывает, попробуйте :help! а обращение к bash). Например,

:r !cal 2024

Одиннадцать символов и энтер - и у вас в буфере календарь на весь год.

:r!cal 2024
:r!cal 2024

По мне, так круто. Можно пробел перед ! не ставить, и даже на один символ меньше выходит.

Ну давайте с утилиты cal и начнем. Она генерирует календарь, и есть в двух ипостасях: cal и ncal. Вторая немного гибче и выдает немного другой формат календаря.

Без параметров команда выводит календарь на текущий месяц, обозначив сегодняшний день. Кстати, обозначение сегодняшнего дня инверсией цветов в Вим вставляется неправильно - но обозначение это можно отключить ключом -h

Можно указать год или месяц и год, например cal 2024 или cal may 2024.

Можно вывести юлианский календарь, добавив ключ -j. При этом выводятся не числа месяца, с первого по какое там последнее, а номера дня в году.

Ключ -o выводит дату православной Пасхи. С ключом -j - по юлианском календарю. А ключ -е - для католической Пасхи. Интересно, что только Пасхи удостоились своих ключей. Видимо, потому, что они плавающие. Если вы не знали, то оrthodox - это именно "православный", если речь о христианстве.

Можно вывести по месяцу до и после заказанного календаря, ключам -3 (это "тройка"). Можно вывести сколько угодно месяцев до и после, ключами -А 3 и -В 4, указав любые числа.

Можно вывести номера недель, даты перехода на григорианский календарь и что только ещё не.

Даты перехода на григорианский календарь: ncal -p
Даты перехода на григорианский календарь: ncal -p

Теперь утилита date.

Она много чего позволяет делать, но нас интересует преобразование строки с датой, в каком угодно формате (утилита постарается понять, что вам надо, даже "next friday", "yesterday", "fortnight" поймет) в другой формат.

Ключ -d укажет, что надо работать со строкой, а не с текущей датой, а формат после знака "плюс" опишет, как вы хотите это дату получить. В строке формата можно указывать поля с символом %, как у функции printf, но с другим смыслом.

Например, %d/%m/%y выведет дату в виде 01/12/2023, а можно вывести день недели, число, месяц, год, номер дня в году, время, и что хотите и в разных видах (2023 или 23).

Помните, что американцы самым гадским образом ставят месяц раньше числа! Это нереально бесит, когда код валится на каком-нибудь 11/22/22, и ты понимаешь, что до этого всё работало неправильно на всяких двусмысленных 12/11/20.

%c выводит дату и время по вашей локали, то есть есть по-русски и с учетом прочих местных нюансов: Сб 26 ноя 2022 22:23:41

И имейте в виду, что утилита выводит-то по русски как предписано локалью, но вот понимать русские месяцы она не умеет. Поэтому такую дату - "Сб 26 ноя 2022" - она не переварит. А вот "Sat 26 nov 2022" - запросто.

%F выводит дату, например 2022-11-26

Время можно вывести как в 24-формате (%H), так и в 12-часовом (%I): так, date +'time is %H:%M or %I:%M' выведет time is 20:30 or 10:30. Можете просто вывести время через %R или %r. Можно с секундами, через %T.

Можно вывести часовой пояс через %z или %:z, а также %Z - это выводит код зоны, например MSK в моем случае.

Удобно переводить время между зонами, и для этого можно сделать команду Вим:

date -d'16:42CET' +%T%Z выдаст 18:42:00MSK

Полезно поле %s, выводящее число секунд с некоторой фиксированной даты в прошлом. Очень ненаглядно, но полезно для арифметики. Например, date -d 01jan2024 +%s выдаст 1704056400, а для 2 января это будет 1704142800, и разность в точности равна длине суток в секундах: 86400. Так легко вычислить разность дат в сутках.

Только помните, что прибавить к дате некоторое число дней очень просто, и тогда 1 января плюс 1 день есть 2 января, всё логично; но тогда 2 января минус 1 января должно давать 1 день! Тоже логично, но для бухгалтерии (и всех остальных тоже) период с 1 по 2 января - это ДВА дня. Так что в арифметике разумно иметь отдельно функции разности дат и расстояния в днях между датами. Они отличаются на единицу.

И для времени то же самое! date -d '15:57' +%s выдаст число, которое потом можете использовать для арифметики.

Сконвертировать число секунд обратно во время и дату можно так:

date -d '@1669491456'

получится Сб ноя 26 22:37:36 MSK 2022

При этом я могу задать любой желаемый формат. Например,

date -d '@1669491456' +'%A, %d %B, %Y; %H:%M%Z; неделя номер %V'

выдаст Суббота, 26 Ноябрь, 2022; 22:37MSK; неделя номер 47

Удачи, коллеги!

Научно-популярные каналы на Дзене: путеводитель
Новости популярной науки12 марта 2022