我想创建一个名为的命令Age
来调用此脚本:
From=$(stat / | grep "Birth" | sed 's/Birth: //g' | cut -b 2-11)
echo $From
Now=$(date)
echo $Now
但是,我一直在减去这两个日期。
我怎样才能减去它们并确保它不会像2022-05-07
with那样与日期时间混淆2022-07-05
?我的意思是,是哪一个月,哪一天是哪一天?
我认为我应该更改命令的格式stat
以使其更具描述性,以防止这种混乱,然后确保两个日期的格式相同,然后减去它们。但我找不到如何做。
答案1
这个答案是错误的!!!应根据秒数手动计算差异。用命令显示date
只显示月份,当天的天数,距离 如此多的秒数1970-01-01
。
我会这样做:
#!/bin/bash
d1=$(date -d "$(stat / | grep "Birth" | sed 's/Birth: //g')" +%s)
d2=$(date +%s)
date -d "@$(($d2 - $d1))" +'%m months, %d days, %H hours'
在几秒钟内获得两次。减去它们并以您选择的格式显示它们。在本例中,它以月、日和小时为单位。您可以根据自己的喜好更改它。尝试man date
看看您有哪些输出格式选项。
关于日期格式 YYYY-MM-DD 的混淆,我从未见过计算机将其错误地解释为 YYYY-DD-MM。
根据 muru 的评论添加(oneliner):
date -d "@$(($(date +%s) - $(stat / --format %W)))" +'%m months, %d days, %H hours'
在@Saeed Neamati 评论后添加。以下答案提供了更好的解决方案。他们仍然不是100%正确。
第一个选项 如果计算差异,然后将该差异添加到 1970-01-01,则可以显示与 1970-01-01 的年、月和日差异。由于月份长度不同且存在闰年,结果并不准确:
seconds=$(date -d "@$(($(date +%s) - $(stat / --format %W)))" +%s)
years=$(($(date -d @$seconds +%Y) - 1970))
months=$(($(date -d @$seconds +%m) - 1))
days=$(($(date -d @$seconds +%d)))
echo $years years, $months months, $days days
第二个选择 另一种方法是获取两个日期并计算它们之间的差异。天数可能不正确,因为并非所有月份都是 31 天长:
d1_year=$(date -d @$(stat / --format %W) +%Y)
d1_month=$(date -d @$(stat / --format %W) +%-m)
d1_day=$(date -d @$(stat / --format %W) +%-d)
d2_year=$(date +%Y)
d2_month=$(date +%-m)
d2_day=$(date +%-d)
years=$(($d2_year - $d1_year))
months=$(($d2_month - $d1_month))
if (( $months < 0 )); then
months=$(($months + 12))
years=$(($years - 1))
fi
days=$((d2_day - $d1_day))
if (( $days < 0 )); then
days=$(($days + 31))
months=$((months -1))
fi
echo $years years, $months months, $days days
答案2
2022-05-07,与 05/07/22 或 07/05/2022 相反,是明确的标准日期格式,始终为 YYYY-MM-DD。但是,在这里,您不需要解析日历日期时间,您可以获取自纪元以来的秒数原始数据。
与 GNU stat
(最近足够并使用最近的 glibc 和 Linux 内核,因此它报告诞生时间)和ddiff
来自dateutils
(dateutils.ddiff
在 Debian 及其衍生版本中)的命令:
ddiff -i %s -f %d "$(stat -c%W /)" now
或者近似计算一天为 86400 秒(它们是 86400 Unix 秒,但由于某些时区的 DST,计算在极少数情况下可能会偏差一天):
echo "$(( ($(date +%s) - $(stat -c%W /)) / 86400 ))"
使用 zsh 之后zmodload zsh/datetime
或使用最新版本的bash
,$(date +%s)
可以替换为$EPOCHSECONDS
.
ts
来自 moreutils,with -r
,可以解析时间戳并将其转换为某种61d25m ago
/166d7h ago
格式。它可以识别多种时间戳格式,包括 ISO-8600 格式,因此您需要stat
稍微转换 的输出,并获取 UTC 时间,因为我认为不会ts
解释时区部分:
TZ=UTC0 stat -c%w / |
sed 's/ /T/;s/ .*/Z/' |
ts -r
或者使用 GNUfind
而不是stat
withTZ=UTC0 find / -prune -printf '%BFT%BTZ\n'
从一开始就以正确的格式获取时间戳(同样,需要最新版本的 findutils、glibc、Linux)。