n天前从命令行上的给定日期开始

时间:2017-01-18 12:59:59

标签: linux shell date unix gnu

例如,给定日期为2016-12-31',n为2,预期输出为2016-12-29'。

我调查date命令并且从当前日期开始n天前很容易:
date -d "2 days ago" +%Y-%m-%d

2 个答案:

答案 0 :(得分:9)

只需提及您想要提取两天的日期:

$ date -d "2016-12-31 2 days ago" +%Y-%m-%d
2016-12-29

或者语法更好一点:

$ date -d "2016-12-31 -2 days" +%Y-%m-%d
2016-12-29

答案 1 :(得分:1)

如果你没有GNU日期,也许你有BSD date。在这种情况下,您可以这样做:

date -jf %s $(( $(date +%s) - 86400 * 2 ))

请注意,这不是POSIX,也不是GNU。

这告诉BSD日期不要更改时钟(-j)并将输入作为UNIX time(1970/01/01 00:00:00 UTC之后的秒,-f %s )。提供的时间是当前时间的数学替换($(date +%s),使用相同的格式但作为输出)减去一天中的秒数(86400)乘以2。

在过去,我编写的代码用于查找GNU,然后故障转移到BSD:

# Usage: _epoch2datefmt UNIX_TIME [+FORMAT]
if date -d @1484850180 +%s >/dev/null 2>&1
  then _epoch2datefmt() { date -d @"$@"; }    # GNU
  else _epoch2datefmt() { date -jf %s "$@"; } # BSD
fi

对于这个问题,我们还需要走另一个方向。 BSD日期也需要格式:

# Usage: _date2epoch YYYY-MM-DD [INPUT_FORMAT]
if date -d 2017-01-19 +%s >/dev/null 2>&1
  then _yyyymmdd2epoch() { date -d "$1" +%s; }       # GNU
  else _yyyymmdd2epoch() { date -jf "$2" "$1" +%s; } # BSD
fi

以下是如何将这些组合在一起,以便在给定日期前两天使用GNU或BSD:

_epoch2datefmt $(( $(_date2epoch 2016-12-31 %Y-%m-%d) - 2 * 86400 )) +%Y-%m-%d

从内到外,这将2016-12-31转换为UNIX时间,减去两天(一天中有86400秒),然后将生成的UNIX时间(答案)传递回YYYY-MM -DD格式。

如果你想在一个函数中使用它,可能是:

# Usage: _date_helper INPUT_FORMAT DATE [+OUTPUT_FORMAT]
if date -d@1484850180 +%s >/dev/null 2>&1
  then _date_helper() { local A=; [ "$1" = %s ] && A=@; shift; date -d "$A$@"; }
  else _date_helper() { date -jf "$@"; }
fi

(由于GNU的%s需要一个前导date -d,因此我必须处理输入UNIX时间(由第一个参数@表示)有点棘手。这样可以节省如果需要,在$A中填写前缀,清除格式(GNU是智能的,否则不需要它),然后将其余部分传递给GNU date命令.BSD版本应该是不言自明的。 )

以下是如何使用此功能运行它以“2016-12-31之前两天”:

_date_helper %s $(( $(_date_helper %Y-%m-%d 2016-12-31 +%s) - 86400 * 2)) +%Y-%m-%d