快速计算日期差异

dan*_*ann 118 date

我经常想做一些快速的日期计算,例如:

  • 这两个日期有什么区别?
  • 在另一个日期之后n周是什么日期?

我通常打开日历并计算天数,但我认为应该有一个程序/脚本可以用来进行这些类型的计算。有什么建议?

cam*_*amh 143

使用 GNU date(1) 可以轻松实现“日期后 n 周”:

$ date -d 'now + 3 weeks'
Tue Dec  6 23:58:04 EST 2011
$ date -d 'Aug 4 + 3 weeks'
Thu Aug 25 00:00:00 EST 2011
$ date -d 'Jan 1 1982 + 11 weeks'
Fri Mar 19 00:00:00 EST 1982
Run Code Online (Sandbox Code Playgroud)

我不知道计算两个日期之间差异的简单方法,但是您可以使用 shell 函数在 date(1) 周围包装一些逻辑。

datediff() {
    d1=$(date -d "$1" +%s)
    d2=$(date -d "$2" +%s)
    echo $(( (d1 - d2) / 86400 )) days
}
$ datediff '1 Nov' '1 Aug'  # Note: answer should be 92 days but in my timezone, DST starts between the dates.
91 days
Run Code Online (Sandbox Code Playgroud)

交换d1d2如果你想以另一种方式计算日期,或者变得更有趣,让它无关紧要。此外,如果间隔中有非 DST 到DST 的转换,其中一天将只有 23 小时;您可以通过在总和上增加 ½ 天来补偿。

echo $(( (((d1-d2) > 0 ? (d1-d2) : (d2-d1)) + 43200) / 86400 )) days
Run Code Online (Sandbox Code Playgroud)

  • @kennyut 答案实际上应该是 92 天。我的示例中的问题是,在我的时区中,夏令时在两个日期之间开始,因此两个日期之间的秒数短了 3600(1 小时)。如果您所在的时区没有 DST(或者有但 DST 在日期之间结束),那么您将得到 92 天的正确答案。请参阅 Gilles 的修订以了解正确的计算 (2认同)

hro*_*tyr 55

对于一组便携式工具,请尝试我自己的dateutils。你的两个例子可以归结为单行:

ddiff 2011-11-15 2012-04-11
=>
  148
Run Code Online (Sandbox Code Playgroud)

或以周和天为单位:

ddiff 2011-11-15 2012-04-11 -f '%w %d'
=>
  21 1
Run Code Online (Sandbox Code Playgroud)

dadd 2011-11-15 21w
=>
  2012-04-10
Run Code Online (Sandbox Code Playgroud)

关于 Ubuntu 安装的重要说明:

这些非常相同的 dateutils 可作为Ubuntu 软件包使用,因此可以通过sudo apt install dateutils.

但是,命令前面需要有dateutils.前缀,如dateutils.ddiff 2019-03-28 2019-05-16

它们也可以在 Fedora 和 Fedora EPEL for RHEL 或 CentOS 中使用sudo dnf install dateutils。在 Fedora 中,这些包不需要前缀而是使用长名称——例如,datediffanddateadd代替ddiffand dadd

对于 Arch Linux,使用sudo pacman -Sy dateutils. 二进制文件被称为datediffand dateadd,就像在 Fedora 中一样。

  • +1 你的工具摇滚(尽管 `dateadd -i '%m%d%Y' 01012015 +1d` 似乎不起作用,它只是无限期地挂在那里......如果日期规格由字符分隔,它确实有效,任何字符......知道出了什么问题吗?) (3认同)
  • @don_crissti 解析器无法区分纯数字日期和持续时间,它已在当前主文件中修复 (d0008f98) (2认同)
  • 这些完全相同的“dateutils”可作为 [Ubuntu 软件包](https://manpages.ubuntu.com/manpages/bionic/man1/dateutils.dateutils.1.html) 提供,因此可以通过“sudo apt install dateutils”进行安装但是,命令前面需要加上“dateutils.”前缀,如“dateutils.ddiff 2019-03-28 2019-05-16” (2认同)

Dan*_*und 36

用于计算我在地球上行走的天数的 Python 示例:

$ python
>>> from datetime import date as D
>>> print (D.today() - D(1980, 6, 14)).days
11476
Run Code Online (Sandbox Code Playgroud)

  • 以防万一有人希望它像单个命令一样运行,而不是在交互式解释器中输入:`ychaouche@ychaouche-PC ~ $ python -c "from datetime import date as d; print (d.today() - d (1980, 6, 14)).days"` `12813` `ychaouche@ychaouche-PC ~ $` (3认同)
  • 这对我有用 python3 -c "from datetime import date as d; print (d.today() - d(2016, 1, 9))" 不需要最后的天数 (2认同)

Mat*_*nco 15

我通常更喜欢 unix utime 格式的时间/日期(自七十年代开始的纪元以来的秒数,UTC)。这样它总是归结为简单的减法或加法秒。

问题通常是将日期/时间转换为这种格式。

在 shell 环境/脚本中,您可以使用date '+%s' 在撰写本文时,当前时间为1321358027.

与 2011-11-04(我的生日)相比,date '+%s' -d 2011-11-04, yield 1320361200。减去:expr 1321358027 - 1320361200给出996827秒,即expr 996827 / 86400= 11 天前。

使用标准库将 utime(1320361200 格式)转换为日期非常简单,例如在 C、PHP 或 perl 中。对于 GNU date-d可以在参数前面加上@“自纪元以来的秒数”格式。


Pet*_*des 10

这是在date -d "$death_date - $y years - $m months - $d days"用于获取出生日期(用于家谱)时出现的。该命令是错误的。月份的长度不尽相同,因此(date + offset) - offset != date. 年龄,以年/月/日为单位,是从出生日期开始计算的量度。

$ date --utc -d 'mar 28 1867 +72years +11months +2days'
Fri Mar  1 00:00:00 UTC 1940

$ date --utc -d 'mar 1 1940 -72years -11months -2days'
Sat Mar 30 00:00:00 UTC 1867
# (2 days later than our starting point)
Run Code Online (Sandbox Code Playgroud)

Date 在两种情况下都给出了正确的输出,但在第二种情况下,您问错了问题。在添加/减去天数之前,+/- 11 涵盖一年中的 11 个月很重要。例如:

$ date --utc -d 'mar 31 1939  -1month'
Fri Mar  3 00:00:00 UTC 1939
$ date --utc -d 'mar 31 1940  -1month' # leap year
Sat Mar  2 00:00:00 UTC 1940
$ date --utc -d 'jan 31 1940  +1month' # leap year
Sat Mar  2 00:00:00 UTC 1940
Run Code Online (Sandbox Code Playgroud)

为了使减法成为加法的逆运算,必须颠倒运算顺序。添加会增加年,然后是月,然后是天。如果减法使用相反的顺序,那么您将回到起点。如果天数偏移量在不同长度的月份中跨越月份边界,则不会,因此您不会。

如果您需要从结束日期和年龄向后工作,您可以通过多次调用date. 先减去天数,然后减去月数,然后减去年数。(我认为在一次date调用中组合年份和月份是不安全的,因为闰年​​会改变二月的长度。)


qua*_*gar 8

如果图形工具适合你,我衷心推荐qalculate(一个强调单位转换的计算器,它带有一个 GTK 和 KDE 界面,IIRC)。在那里你可以说例如

days(1900-05-21, 1900-01-01)
Run Code Online (Sandbox Code Playgroud)

获取日期之间的天数(140,因为 1900 年不是闰年),但当然您也可以对时间执行相同的操作:

17:12:45 ? 08:45:12
Run Code Online (Sandbox Code Playgroud)

产生8.4591667小时,或者,如果您将输出设置为时间格式,则8:27:33.

  • 这很棒,而且更是如此,因为 qalculate _确实_有一个 CLI。尝试`qalc`,然后是`help days`。 (3认同)

小智 5

您可以使用另一种方法来计算同一日历年的两个日期之间的差异:

date_difference.sh
1  #!/bin/bash
2  DATEfirstnum=`date -d "2014/5/14" +"%j"`
3  DATElastnum=`date -d "12/31/14" +"%j"`
4  DAYSdif=$(($DATElastnum - $DATEfirstnum))
5  echo "$DAYSdif"
Run Code Online (Sandbox Code Playgroud)
  • 第 1 行向 shell 声明要使用哪个解释器。
  • 第 2 行将 out 中的值赋给date变量 DATEfirstnum。该-d标志以时间格式显示字符串(在本例中为 2014 年 5 月 14 日),并+"%j"指示date将输出格式设置为一年中的某一天 (1-365)。
  • 第 3 行与第 2 行相同,但日期不同,字符串格式也不同:2014 年 12 月 31 日。
  • 第 4 行将值赋给DAYSdif两天的差值。
  • 第 5 行显示 的值DAYSdif

这适用于 GNU 版本的date,但不适用于 PC-BSD/FreeBSD 版本。我coreutils从 ports 树安装并使用命令/usr/local/bin/gdate


Kir*_*nta 5

在丹纳斯解决方案的帮助下,这可以通过以下代码一行完成:

python -c "from datetime import date as d; print(d.today() - d(2016, 7, 26))"
Run Code Online (Sandbox Code Playgroud)

(适用于 Python 2.x 和 Python 3。)