Как проанализировать даты ISO8601 с командой даты Linux

/etc/resolv.conf определяет, как компьютер разрешает имена хостов (например, который, если таковые имеются, ищутся доменные имена по умолчанию, когда Вы пытаетесь разрешить non-FQDN имя хоста.... поиск для пустого www становится www.yourdomain.example.com), и какие серверы имен используются, чтобы сделать поиск.

Одна из причин и наиболее вероятное, что клиенты VPN могли бы изменить/etc/resolv.conf, состоят в том, чтобы заставить компьютер клиента VPN использовать конкретный сервер имен для разрешения сетевых имен - например, если маршрутизатор VPN выполняет кэширующийся сервер имен.

Нет ничего мешающего Вам возвратить/etc/resolv.conf к тому, чем Вы хотите, чтобы он был, и программное обеспечение клиента VPN может даже предоставить Вам некоторый автоматизированный метод выполнения этого (иначе просто CP резервная копия resolv.conf назад в место)...., но Вы можете испытать затруднения при разрешении некоторых имен (например, некоторые домены настраиваются с общедоступными и частными представлениями - посторонние видят только "общедоступные" имена, в то время как инсайдеры - включая клиентов VPN - видят все внутренние, частные имена также).

Одним способом решить это была бы к CP не резервная копия исходного resolv.conf, а измененная копия и с Вашими предпочтительными серверами имен и с областями поиска, а также что хочет программное обеспечение клиента VPN.

15
04.01.2014, 02:47
5 ответов

Вы просите "известные обходные решения". Вот простой:

$ date -d "$(echo 20140103T1422 | sed 's/T/ /')"
Fri Jan  3 14:22:00 PST 2014

Это использует sed заменять "T" пространством. Результатом является формат это date понимает.

Если мы добавляем секунды на дату ISO8601, то date требует большего количества изменений:

$ date -d "$(echo 20140103T142211 | sed -r 's/(.*)T(..)(..)(..)/\1 \2:\3:\4/')"
Fri Jan  3 14:22:11 PST 2014

В вышеупомянутом, sed заменяет "T" пространством и также разделяет HHMMSS на HH:MM:SS.

9
27.01.2020, 19:49
  • 1
    Работы для меня, если + удален. Однако это не работает на вторые метки времени точности, только мелкая точность. –  alex.forencich 04.01.2014, 01:52
  • 2
    @alex.forencich обновляется с точностью секунд. Сообщите мне, не является ли формат секунд, который я выбрал, тем, Вам нужно. –  John1024 04.01.2014, 02:38

GNU coreutils только поддерживал даты ISO 8601, как введено начиная с версии 8.13 (выпущенный 08.09.2011). Необходимо использовать более старую версию.

Под более старыми версиями необходимо заменить T пространством. Иначе это интерпретируется как американский военный часовой пояс.

Даже под последними версиями, только полностью акцентированная форма распознана, не основной формат только с цифрами и a T в середине.

# Given a possibly abbreviated ISO date $iso_date...
date_part=${iso_date%%T*}
if [ "$date_part" != "$iso_date" ]; then
  time_part=${abbreviated_iso_date#*T}
  case ${iso_date#*T} in
    [!0-9]*) :;;
    [0-9]|[0-9][0-9]) time_part=${time_part}:00;;
    *)
      hour=${time_part%${time_part#??}}
      minute=${time_part%${time_part#????}}; minute=${minute#??}
      time_part=${hour}:${minute}:${time_part#????};;
  esac
else
  time_part=
fi
date -d "$date_part $time_part"
6
27.01.2020, 19:49

В coreutils информационных документах говорится, что ISO 8601 "расширенный формат" поддерживается.

Необходимо будет добавить дефисы, двоеточия и a +%z заставить его работать.

$ date +"%Y-%m-%dT%H:%M:%S%z"
2014-01-03T16:08:23-0800
$ date -d 2014-01-03T16:08:23-0800
Fri Jan  3 16:08:23 PST 2014

Ответить на Вашу вторую часть вопроса...

Так как формат даты только содержит числа и символы, Вы могли заменить каждый символ уникальной буквой, например, использование tr

$ ts="$(date +"%Y-%m-%dT%H:%M:%S%z" | tr -- '-:+' 'hcp')"; echo "$ts"
2014h01h03T16c18c04h0800
$ date -d "$(echo "$ts" | tr -- 'hcp' '-:+')"
Fri Jan  3 16:18:04 PST 2014

Или Вы могли проанализировать его с помощью T и - или + как разделители, например, использующий оболочку ${var%word} и ${var#word} расширение

$ ts="$(date +"%Y%m%dT%H%M%S%z")"; echo "$ts"
20140103T162228-0800
$ date=${ts%T*}; time=${ts#*T}
etc.    

или использование bash соответствие регулярного выражения

$ ts="$(date +"%Y%m%dT%H%M%S%z")"; echo "$ts"
20140103T165611-0800
$ [[ "$ts" =~ (.*)(..)(..)T(..)(..)(..)(.....) ]]
$ match=("${BASH_REMATCH[@]}")
$ Y=${match[1]}; m=${match[2]}; d=${match[3]}; H=${match[4]}; M=${match[5]}; S=${match[6]}; z=${match[7]}
$ date -d "$Y-$m-$d"T"$H:$M:$S$z"
Fri Jan  3 16:56:11 PST 2014

или Perl, Python, и т.д. и т.д.

8
27.01.2020, 19:49
  • 1
    Метка времени не может иметь никаких специальных символов в ней. Вы знаете о хорошем способе включить, они отступают автоматически? –  alex.forencich 04.01.2014, 02:13

Я действительно замечал это примечание в странице справочника для date.

DATE STRING
      The --date=STRING is a mostly free format human readable date string
      such as "Sun, 29 Feb 2004 16:21:42 -0800"  or  "2004-02-29
      16:21:42"  or  even  "next Thursday".  A date string may contain 
      items indicating calendar date, time of day, time zone, day of
      week, relative time, relative date, and numbers.  An empty string 
      indicates the beginning of the day.  The date  string  format
      is more complex than is easily documented here but is fully described 
      in the info documentation.

Это не окончательно, но это явно не показывает строку формата времени, которая включает T поскольку Вы пытаетесь для [ISO 8601]. Как @Gilles обозначенный ответ, поддержка ISO 8601 в GNU CoreUtils является относительно новой.

Переформатирование строки

Можно использовать Perl для переформулирования строки.

Пример:

$ date -d "$(perl -pe 's/(.*)T(\d{2})(\d{2})(\d{2})/$1 $2:$3:$4/' \
    <<<"20140103T142233")"
Fri Jan  3 14:22:33 EST 2014

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

20140103T1422:

$ date -d "$(perl -pe 's/^(.*)T(\d{2})(\d{2})(\d{2})$/$1 $2:$3:$4/ || \
     s/^(.*)T(\d{2})(\d{2})$/$1 $2:$3:00/' <<<"20140103T1422")"
Fri Jan  3 14:22:00 EST 2014

20140103T142233:

$ date -d "$(perl -pe 's/^(.*)T(\d{2})(\d{2})(\d{2})$/$1 $2:$3:$4/ || \
     s/^(.*)T(\d{2})(\d{2})$/$1 $2:$3:00/' <<<"20140103T142233")"
Fri Jan  3 14:22:33 EST 2014
2
27.01.2020, 19:49
  • 1
    @alex.forencich - альтернативная команда, которая обработает оба формата времени. Сделайте мне одолжение и удалите комментарии выше этого, больше не релевантны. –  slm♦ 04.01.2014, 04:18

Согласно странице справочника даты, формат, который Вы производите, не является тем же как какой date ожидает, как введено. Это - то, что говорит страница справочника:

date [-u|--utc|--universal] [MMDDhhmm[[CC]YY][.ss]]

Таким образом, Вы могли сделать это как это:

# date +%m%d%H%M%Y
010402052014
# date 010402052014
Sat Jan  4 02:05:00 EAT 2014

Поскольку в переменных, которые используются для определения выходной строки, +%m%d%H%M%Y было бы равно тому, что это ожидает, как введено.

1
27.01.2020, 19:49
  • 1
    Затем можно ли обеспечить команду для отображения даты формата ISO8601 в то, чего требует дата? Фактические сохраненные метки времени должны быть в формате ISO8601, таким образом, они могут быть отсортированы по дате. –  alex.forencich 04.01.2014, 01:10

Теги

Похожие вопросы