Привет, коллеги. Сегодня, в преддверии Нового Года, поговорим о датах и календарях. Вим здесь будет скорее как повод.
Впрочем, мы уже обсуждали способ реализовать арифметику дат в Вим. Это несложно сделать с помощью внешней утилиты date (я всегда исхожу из того, что у Вас Линукс или другая POSIX-совместимая система). Давайте обсудим эту утилиту поподробнее, а еще я расскажу про утилиту cal (как вариант, ncal): она выводит календарь.
Всё это в контексте Вим, так что распланировать отпуск Вам будет предельно легко.
Начнем с того, что вставить в Вим выдачу в поток STDOUT ("на экран", если вы новичок) от любой внешней программы можно с помощью команды :r с применением восклицательного знака (который не часть команды, как это часто бывает, попробуйте :help! а обращение к bash). Например,
:r !cal 2024
Одиннадцать символов и энтер - и у вас в буфере календарь на весь год.
По мне, так круто. Можно пробел перед ! не ставить, и даже на один символ меньше выходит.
Ну давайте с утилиты cal и начнем. Она генерирует календарь, и есть в двух ипостасях: cal и ncal. Вторая немного гибче и выдает немного другой формат календаря.
Без параметров команда выводит календарь на текущий месяц, обозначив сегодняшний день. Кстати, обозначение сегодняшнего дня инверсией цветов в Вим вставляется неправильно - но обозначение это можно отключить ключом -h
Можно указать год или месяц и год, например cal 2024 или cal may 2024.
Можно вывести юлианский календарь, добавив ключ -j. При этом выводятся не числа месяца, с первого по какое там последнее, а номера дня в году.
Ключ -o выводит дату православной Пасхи. С ключом -j - по юлианском календарю. А ключ -е - для католической Пасхи. Интересно, что только Пасхи удостоились своих ключей. Видимо, потому, что они плавающие. Если вы не знали, то оrthodox - это именно "православный", если речь о христианстве.
Можно вывести по месяцу до и после заказанного календаря, ключам -3 (это "тройка"). Можно вывести сколько угодно месяцев до и после, ключами -А 3 и -В 4, указав любые числа.
Можно вывести номера недель, даты перехода на григорианский календарь и что только ещё не.
Теперь утилита 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
Удачи, коллеги!