Dateutils — это набор инструментов, которые вращаются вокруг работы с датами и временем в командной строке, уделяя особое внимание вариантам использования, возникающим при работе с большими объемами финансовых данных.
Dateutils размещаются в основном на github:
страница GitHub: https://github.com/hroptatyr/dateutils
домашняя страница проекта: http://www.fresse.org/dateutils/
загрузки: https://bitbucket.org/hroptatyr/dateutils/downloads
Ниже приведен краткий список примеров, демонстрирующих возможности dateutils. Полные характеристики можно найти на страницах информации и руководства. Инструкции по установке см. в файле INSTALL.
Команды Dateutils имеют префикс date
, но в остальном напоминают известные команды Unix по интуитивным соображениям. Единственным исключением является strptime
, аналог одноименной функции libc.
strptime
Версия командной строки функции C
dateadd
Добавить продолжительность к датам или времени
dateconv
Преобразование дат и времени между календарями
datediff
Вычислить продолжительность между датами или временем
dategrep
Grep даты или время во входных потоках
dateround
Округление даты или времени до «более полных» значений
dateseq
Генерировать последовательность дат или времени
datesort
Сортировка в хронологическом порядке.
datetest
Сравнить даты и время
datezone
Массовое преобразование даты/времени в часовые пояса
Мне нравится, когда все объясняется на примерах, чтобы составить первое впечатление. Итак, вот оно.
Инструмент, имитирующий seq(1), но входные данные которого относятся к области дат, а не целых чисел. Обычно сценарии используют что-то вроде
$ for i in $(seq 0 9); do date -d "2010-01-01 +${i} days" "+%F" done
который теперь можно сократить до
$ dateseq 2010-01-01 2010-01-10
с дополнительным преимуществом, заключающимся в том, что дату окончания можно указать непосредственно, а не вычислять на основе даты начала и интервала в днях. Кроме того, он предоставляет функции, специфичные для даты, которые можно было бы реализовать с помощью PITA с использованием описанного выше подхода seq(1)/date(1), например, пропуск определенных дней недели:
$ dateseq 2010-01-01 2010-01-10 --skip sat,sun => 2010-01-01 2010-01-04 2010-01-05 2010-01-06 2010-01-07 2010-01-08
dateseq также работает по времени:
$ dateseq 12:00:00 5m 12:17:00 => 12:00:00 12:05:00 12:10:00 12:15:00
а также дата-время:
$ dateseq --compute-from-last 2012-01-02T12:00:00 5m 2012-01-02T12:17:00 => 2012-01-02T12:02:00 2012-01-02T12:07:00 2012-01-02T12:12:00 2012-01-02T12:17:00
Инструмент для преобразования дат между различными календарными системами и/или часовыми поясами. В то время как другие подобные инструменты обычно сосредоточены на преобразовании дат по григорианскому календарю, скажем, в китайский календарь, dconv нацелен на поддержку календарных систем, которые необходимы в финансовом контексте.
Чтобы преобразовать (григорианскую) дату в так называемое представление ymcw:
$ dateconv 2012-03-04 -f "%Y-%m-%c-%w" => 2012-03-01-00
и наоборот:
$ dateconv 2012-03-01-Sun -i "%Y-%m-%c-%a" -f '%F' => 2012-03-04
где представление ymcw означает %c
-th %w
месяца в данном году. Это полезно, если указаны даты, например, третий четверг мая.
dateconv также можно использовать для преобразования вхождений дат, времени или даты во входной поток на лету.
$ dateconv -S -i '%b/%d %Y at %I:%M %P' <<EOF Remember we meet on Mar/03 2012 at 02:30 pm EOF => Remember we meet on 2012-03-03T14:30:00
и, что особенно важно, для преобразования между часовыми поясами:
$ dateconv --from-zone "America/Chicago" --zone "Asia/Tokyo" 2012-01-04T09:33:00 => 2012-01-05T00:33:00 $ dateconv --zone "America/Chicago" now -f "%d %b %Y %T" => 05 Apr 2012 11:11:57
Инструмент для сравнения дат в оболочке, он создан по образцу test(1)
но с соответствующими параметрами командной строки.
$ if datetest today --gt 2010-01-01; then echo "yes" fi => yes
Инструмент для выполнения арифметических операций с датами (математических операций с датами) в оболочке. Учитывая дату и список продолжительностей, будут рассчитаны новые даты. Учитывая продолжительность и список дат, будут рассчитаны новые даты.
$ dateadd 2010-02-02 +4d => 2010-02-06 $ dateadd 2010-02-02 +1w => 2010-02-09 $ dateadd -1d <<EOF 2001-01-05 2001-01-01 EOF => 2001-01-04 2000-12-31
Добавление длительности ко времени:
$ dateadd 12:05:00 +10m => 12:15:00
и даже дата-время:
$ dateadd 2012-03-12T12:05:00 -1d4h => 2012-03-11T08:05:00
Если это поддерживается системной базой данных Zoneinfo, возможны расчеты с поправкой на високосную секунду. Используйте единицу rs
для обозначения «реальных» секунд:
$ dateadd '2012-06-30 23:59:30' +30rs => 2012-06-30T23:59:60
в отличие от:
$ dateadd '2012-06-30 23:59:30' +30s => 2012-07-01T00:00:00
Инструмент для расчета разницы между двумя (или более) датами. Это в некоторой степени противоположность папе. Выходными данными будут длительности, которые при добавлении к первой дате дают вторую дату.
Получите количество дней между двумя датами:
$ datediff 2001-02-08 2001-03-02 => 22
Форматом продолжительности можно управлять с помощью переключателя -f
:
$ datediff 2001-02-08 2001-03-09 -f "%m month and %d day" => 1 month and 1 day
dateiff также принимает отметки времени в качестве входных данных:
$ datediff 2012-03-01T12:17:00 2012-03-02T14:00:00 => 92580s
Переключатель -f
делает правильное действие:
$ datediff 2012-03-01T12:17:00 2012-03-02T14:00:00 -f '%dd %Ss' => 1d 6180s
сравнить с:
$ datediff 2012-03-01T12:17:00 2012-03-02T14:00:00 -f '%dd %Hh %Ss' => 1d 1h 2580s
Если это поддерживается системной базой данных Zoneinfo, можно выполнить расчеты с поправкой на високосную секунду. Используйте спецификатор формата %rS
, чтобы получить прошедшее время в «реальных» секундах:
datediff '2012-06-30 23:59:30' '2012-07-01 00:00:30' -f '%rS' => 61
Инструмент для извлечения строк из входного потока, соответствующих определенным критериям, показывающий либо строку, либо совпадение:
$ dategrep '<2012-03-01' <<EOF Feb 2012-02-28 Feb 2012-02-29 leap day Mar 2012-03-01 Mar 2012-03-02 EOF => Feb 2012-02-28 Feb 2012-02-29 leap day
Инструмент для «округления» дат или отметок времени до повторяющегося момента времени, например следующего/предыдущего января или следующего/предыдущего четверга.
Округляем (назад) до первого числа текущего месяца:
$ dateround '2011-08-22' -1 => 2011-08-01
Найдите следующий понедельник от текущей даты (сегодня 08.01.2016):
$ dateround today Mon => 2015-01-11
Вернитесь к прошлому сентябрю, а затем округлите до конца месяца:
$ dateround today -- -Sep +31d => 2015-09-30
Округлите поток дат строго до первого числа следующего месяца:
$ dateround -S -n 1 <<EOF pay cable 2012-02-28 pay gas 2012-02-29 pay rent 2012-03-01 redeem loan 2012-03-02 EOF => pay cable 2012-03-01 pay gas 2012-03-01 pay rent 2012-04-01 redeem loan 2012-04-01
Округлите временной ряд до следующей минуты (т. е. секундная часть равна 00), а затем до следующей половины прошедшего времени (и преобразуйте в ISO):
$ dateround -S 0s30m -i '%d/%m/%Y %T' -f '%F %T' <<EOF 06/03/2012 14:27:12 eventA 06/03/2012 14:29:59 eventA 06/03/2012 14:30:00 eventB 06/03/2012 14:30:01 eventB EOF => 2012-03-06 14:30:00 eventA 2012-03-06 14:30:00 eventA 2012-03-06 14:30:00 eventB 2012-03-06 15:30:00 eventB
В качестве альтернативы, если вы разделите день на полчаса, вы можете округлить их до одного из них, используя обозначение совместного класса:
$ dateround -S /30m -i '%d/%m/%Y %T' -f '%F %T' <<EOF 06/03/2012 14:27:12 eventA 06/03/2012 14:29:59 eventA 06/03/2012 14:30:00 eventB 06/03/2012 14:30:01 eventB EOF => 2012-03-06 14:30:00 eventA 2012-03-06 14:30:00 eventA 2012-03-06 14:30:00 eventB 2012-03-06 15:00:00 eventB
Это во многом идентично предыдущему примеру, за исключением того, что возможным целевым округлением является полный час (который кратен получасам).
Инструмент для приведения строк файла в хронологический порядок.
На данный момент инструмент datesort
зависит от sort(1)
с поддержкой полей, в частности -t
для выбора разделителя и -k
для сортировки по определенному полю.
$ datesort <<EOF 2009-06-03 caev="DVCA" secu="VOD" exch="XLON" xdte="2009-06-03" nett/GBX="5.2" 2011-11-16 caev="DVCA" secu="VOD" exch="XLON" xdte="2011-11-16" nett/GBX="3.05" 2013-11-20 caev="DVCA" secu="VOD" exch="XLON" xdte="2013-11-20" nett/GBX="3.53" 2012-06-06 caev="DVCA" secu="VOD" exch="XLON" xdte="2012-06-06" nett/GBX="6.47" 2013-06-12 caev="DVCA" secu="VOD" exch="XLON" xdte="2013-06-12" nett/GBX="6.92" 2010-11-17 caev="DVCA" secu="VOD" exch="XLON" xdte="2010-11-17" nett/GBX="2.85" EOF => 2009-06-03 caev="DVCA" secu="VOD" exch="XLON" xdte="2009-06-03" nett/GBX="5.2" 2010-11-17 caev="DVCA" secu="VOD" exch="XLON" xdte="2010-11-17" nett/GBX="2.85" 2011-11-16 caev="DVCA" secu="VOD" exch="XLON" xdte="2011-11-16" nett/GBX="3.05" 2012-06-06 caev="DVCA" secu="VOD" exch="XLON" xdte="2012-06-06" nett/GBX="6.47" 2013-06-12 caev="DVCA" secu="VOD" exch="XLON" xdte="2013-06-12" nett/GBX="6.92" 2013-11-20 caev="DVCA" secu="VOD" exch="XLON" xdte="2013-11-20" nett/GBX="3.53"
Инструмент для быстрой проверки значений даты и времени в разных часовых поясах. Результатом будет матрица, показывающая каждое значение даты и времени в каждом часовом поясе:
$ datezone Europe/Berlin Australia/Sydney now 2014-06-30T05:00:00 => 2014-01-30T17:37:13+01:00 Europe/Berlin 2014-01-31T03:37:13+11:00 Australia/Sydney 2014-06-30T07:00:00+02:00 Europe/Berlin 2014-06-30T15:00:00+10:00 Australia/Sydney
Инструмент datezone
также можно использовать для получения следующего или предыдущего перехода на летнее время относительно заданной даты/времени:
$ datezone --next Europe/Berlin Australia/Sydney 2013-02-19 => 2013-03-31T02:00:00+01:00 -> 2013-03-31T03:00:00+02:00 Europe/Berlin 2013-04-07T03:00:00+11:00 -> 2013-04-07T02:00:00+10:00 Australia/Sydney
где левая отметка времени обозначает текущее смещение зоны, а правая — смещение зоны после перехода. Дата/время указывают точный момент, когда должен произойти переход.
По сути, datezone
— это лучший вариант zdump(8)
.
Инструмент, который обеспечивает гибкость strptime(3)
в командной строке. Хотя (по крайней мере GNU) date(1)
поддерживает форматы вывода, ему не хватает какой-либо поддержки для чтения произвольных входных данных из области дат, в частности, когда формат ввода точно известен заранее и должны быть указаны только совпадающие даты/время. обдуманный.
Когда инструмент strptime
читает такие странные даты, как Mon, May-01/2000
становится вопросом
strptime -i "%a, %b-%d/%Y" "Mon, May-01/2000" => 2000-05-01
так же, как вы бы сделали это в C.
Обратите внимание, что strptime
на самом деле использует процедуру strptime из системной библиотеки libc, а для вывода — системную процедуру strftime. Поэтому модификаторы ввода и вывода будут различаться в зависимости от системы.
Для портативной комбинации парсера и принтера используйте dateconv
как описано выше. Его спецификаторы формата ввода и вывода не зависят от среды выполнения C.
В произвольном порядке и без претензии на полноту:
dateexpr: http://www.eskimo.com/~scs/src/#dateexpr
dateutils allanfalloon: https://github.com/alanfalloon/dateutils
да http://yest.sourceforge.net/
пдд https://github.com/jarun/pdd
Используйте тот, который лучше всего соответствует вашим целям. И если моя вам понравилась, проголосуйте: страница openhub dateutils