2015-04-09 6 views
6

из https://www.gnu.org/software/gawk/manual/html_node/Time-Functions.html Я понимаю, что gawk имеет только две функции для работы на дату/время mktime и strftime.AWK с датами до 1970

Таким образом, я могу разобрать любую дату, используя mktime, возвращающую длинные, так что я могу сделать любую математическую оп, и поэтому я могу форматировать выход желаемый с strftime

Это работает как шарм в любой день после "1970 01 01 00 00 00"

Использование awk, как я могу отформатировать даты до 1970 года?

$ awk 'BEGIN{t=mktime("1970 01 01 00 00 00"); print t; print strftime("%Y-%m-%d", t) }' 
10800 
1970-01-01 
$ awk 'BEGIN{t=mktime("1960 01 01 00 00 00"); print t; print strftime("%Y-%m-%d", t) }' 
-315608400 
awk: cmd. line:1: (FILENAME=- FNR=1) fatal: strftime: second argument less than 0 or too big for time_t 
+3

У вас есть использовать молоток и долото в их каменные плиты ;-) –

+0

Похоже, что strftime не принимает отрицательное значение для параметра timestamp (second), который представляет ts количество секунд с 1970 01 01 00 00 00 UTC. Время до этого будет иметь отрицательное количество секунд *, так как тогда. – ReluctantBIOSGuy

+1

Вы можете опустить 'echo '" | 'с помощью' awk' BEGIN {...} ' –

ответ

1

Итак, это ошибка ...

Я использую GNU AWK 4.0.2, Литт взгляд на источник и, кажется, легко исправить:

glaudiston:/sources/gawk-4.0.2$ diff builtin.c.orig builtin.c 
1701,1702c1701,1702 
<      if (clock_val < 0) 
<        fatal(_("strftime: second argument less than 0 or too big for time_t")); 
--- 
>      // if (clock_val < 0) 
>      //  fatal(_("strftime: second argument less than 0 or too big for time_t")); 
glaudiston:/sources/gawk-4.0.2$ echo "" | ./gawk '{ts="1969 12 31 23 00 00";format="%Y/%m/%d";tv=mktime(ts);print tv;print strftime(format, tv)}' 
7200 
1969/12/31 
glaudiston:/sources/gawk-4.0.2$ echo "" | ./gawk '{ts="1960 01 01 00 00 00";format="%Y/%m/%d";tv=mktime(ts);print tv;print strftime(format, tv)}' 
-315608400 
1960/01/01 

Для моей цели он работал, но я не уверен, была ли это хорошая идея. Я пошлю это для одобрения.

Обсуждение началось на: https://lists.gnu.org/archive/html/bug-gawk/2015-04/msg00012.html

Решение Обновление:

Команда AWK Дев исправлена ​​ошибка, так что просто обновить AWK до новой версии:

https://lists.gnu.org/archive/html/bug-gawk/2015-04/msg00036.html

1

К сожалению, как вы видели, gawk просто не может этого сделать напрямую. gawk manual говорит:

Все известные POSIX-совместимые метки времени системы поддержки от 0 до 2^31 - 1, что является достаточным для представления раз через 2038-01-19 3:14:07 UTC. Многие системы поддерживают более широкий диапазон временных меток, включая отрицательные временные метки, которые представляют время до эпохи.

В руководстве не указано, что такое strftime(), если задана дата выхода на дальность.

Но даже на моей системе, которая делает себя благоразумно для отрицательных значений time_t, простофиля-х strftime() функцию не поддерживает (хотя mktime() делает), и поэтому не может работать с датами до 1970 года, я считаю, что это ошибка, в gawk.

(Мой совет должен был бы использовать Perl вместо Awk, но это не дает ответа на вопрос, который вы просили.)

В принципе, вы можете изобретать колесо заново реализовать функцию как strftime() в AWK , Но это было бы излишним.

Если в вашей системе имеется команда GNU coreutils date, вы можете вызвать ее с gawk. Использование примера 1 января 1960 года:

$ cat 1960.awk 
#!/usr/bin/awk -f 

BEGIN { 
    timestamp = mktime("1960 00 00 00 00 00") 
    print "mktime() returned " timestamp 

    if (0) { 
     # This doesn't work 
     s = strftime("%Y-%m-%d %H:%M:%S", timestamp) 
     print "strftime() returned ", s 
    } 
    else { 
     # This works 
     "date '+%Y-%m-%d %H:%M:%S' -d @" timestamp | getline t 
     print "The date command printed \"" t "\"" 
    } 
} 
$ ./1960.awk 
mktime() returned -318355200 
The date command printed "1959-11-30 00:00:00" 
$ 

(. Я отказался от выяснить последовательность цитат и обратные косые черт, необходимых, чтобы сделать это как однострочник из командной строки оболочки)

Это, вероятно, имеет смысл, если у вас есть большая существующая awk-программа, и вам нужно добавить к ней эту функцию. Но если вы не застряли с этим в awk, вы можете подумать об использовании чего-то другого; awk не может быть правильным инструментом для того, что вы пытаетесь выполнить.

Или, если вы действительно амбициозны, вы можете изменить источники gawk, чтобы правильно обрабатывать этот случай.

+0

'mktime' не проблема, она работает нормально. проблема кажется strftime, и использовать дату не вариант, потому что слишком медленно и слишком дорого. Я посмотрю, как это сделать в perl. – ton

+0

@ton: Вы правы. Я обновил свой ответ (и предложил другую возможную альтернативу: исправление 'gawk'). –

Смежные вопросы