Хотя очевидно, что формат даты ОП основан на Unix, стоит упомянуть, что в игре есть два основных календаря. Юлианский календарь и Григорианский календарь . Оба календаря имеют разное представление о том, что такое високосный год.
примечание: в настоящее время большинство стран принимают григорианский календарь . Однако он не был официально принят всеми странами. Об этом следует помнить при проведении исторических исследований. Например, в Великобритании это изменение было внесено еще в 1752 г. н.э., а в Турции - не ранее 1927 г. (Ссылка на астрономические алгоритмы Жана Мееуса)
Имея это в виду и в зависимости от того, был ли ваш цифровой файл из Турции 1920 или 2011 года или Великобритании из 1740 или 1789 года, я представляю два awk
решения
В високосном году месяц февраль имеет 29 дней, а в обычном году - 28 дней.
В юлианском календаре год является високосным (или биссекстильным) годом, составляющим 366 дней, если его числовое обозначение делится на 4. Все остальные годы являются обычными годами (365 дней).
Используя awk
, так как это был запрос OP, мы можем написать следующую функцию, которая будет выполнять запрошенное преобразование:
awk 'function julian(str, y,m,d) {
y=substr(str,1,4); m=substr(str,6,2)+0;
if (m==1) {y=y-1; m=12} else {m=m-1}
if (((m-1)%7)%2==0) {d=31} else {d=30}
if (m==2) { d = (y%4==0) ? 29 : 28 }
return sprintf("%0.4d-%0.2d-%0.2d",y,m,d)
}
{ print $14, julian($14) }' <file>
В григорианском календаре действует то же правило, что и в юлианском календаре, со следующим исключением: центориальные годы, которые не делятся на 400, являются общими годами.
awk 'function gregorian(str, y,m,d) {
y=substr(str,1,4); m=substr(str,6,2)+0;
if (m==1) {y=y-1; m=12} else {m=m-1}
if (((m-1)%7)%2==0) {d=31} else {d=30}
if (m==2) { d = (y%4!=0) ? 28 : (y%100==0 && y%400!=0 ? 28 : 29 ) }
return sprintf("%0.4d-%0.2d-%0.2d",y,m,d)
}
{ print $14, gregorian($14) }' <file>
Поскольку календарь UNIX григорианский, мы также можем использовать GNU Awk Time Functions . Однако это будет работать только с 1970-02-01 по 2038-01-19 для 32-битных систем и 292277026596-04-01 для 64-битных систем (см. здесь )
awk 'function unix(str, tmp) {
tmp=substr(str,1,7)" 01 00 00 00"; gsub("-"," ",tmp);
return strftime("%Y-%m-%d",mktime(tmp) - 1) }
{ print $14, unix($14) }' <file>