这两个日期之间有什么区别?
这个另一个日期之后n周的日期是什么?
我通常打开日历并计算天数,但是我认为应该有一个程序/脚本可用于进行这类计算。有什么建议吗?
#1 楼
使用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
我不知道一种简单的方法来计算两个日期之间的差,但是您可以使用shell函数在date(1)周围包裹一些逻辑。
datediff() {
d1=$(date -d "" +%s)
d2=$(date -d "" +%s)
echo $(( (d1 - d2) / 86400 )) days
}
$ datediff '1 Nov' '1 Aug'
91 days
如果希望以其他方式进行日期计算,请交换
d1
和d2
,或者变得有点幻想,不要紧。此外,如果在此时间间隔内有非DST到DST的过渡,则一天中只有23小时长;您可以在总数上加½天作为补偿。echo $(( (((d1-d2) > 0 ? (d1-d2) : (d2-d1)) + 43200) / 86400 )) days
评论
我正在尝试实现“添加n分钟”,我的问题是我在可变的timeStudy中记录了分钟数,而找不到在3(代替您的代码)中插入它的方法。有什么帮助吗?
–汤马索(Tommaso Seneci)
20 Mar 23 '20 at 19:55
@TommasoSeneci:date -d“ now + $ {timeStudy}分钟”-使用双引号而不是单引号可以在字符串中进行变量扩展。
– camh
20-3-23在21:59
太好了,问题解决了!!
–汤马索(Tommaso Seneci)
20 Mar 24 '20 at 12:15
#2 楼
对于一组便携式工具,请尝试我自己的dateutils。您的两个示例可以归结为一类:ddiff 2011-11-15 2012-04-11
=>
148
或几周又几天:
ddiff 2011-11-15 2012-04-11 -f '%w %d'
=>
21 1
和
dadd 2011-11-15 21w
=>
2012-04-10
关于Ubuntu安装的重要说明:
这些非常相同的dateutils可作为Ubuntu软件包提供,因此可以通过
sudo apt install dateutils
安装。但是,命令之前必须带有
dateutils
。前缀,如dateutils.ddiff 2019-03-28 2019-05-16
中所示,它们也可以在Fedora和Fedora EPEL中用于带有
sudo dnf install dateutils
的RHEL或CentOS。在Fedora中,这些软件包不需要前缀,而是使用长名称-例如,datediff
和dateadd
代替ddiff
和dadd
。评论
为您的工具+1(尽管dateadd -i'%m%d%Y'01012015 +1似乎无效,它无限期地挂在那里...如果日期规范用字符分隔,则确实有效)字符...任何想法出什么事了吗?)
–don_crissti
15年11月22日在2:17
@don_crissti解析器无法区分仅数字的日期和持续时间,它已在当前主文件中固定(d0008f98)
–hroptatyr
2015年11月23日下午6:21
您是否有窗口的dateutils二进制分配?
–莫什
17年2月12日在4:18
@mosh不,我没有尝试的设施。
–hroptatyr
17年2月12日在8:21
这些非常相同的dateutils可作为Ubuntu软件包使用,因此可以通过sudo apt install dateutils安装。但是,命令必须在dateutils之前。如dateutils.ddiff中的前缀2019-03-28 2019-05-16
– Serge Stroobandt
19年5月16日在9:27
#3 楼
用于计算我在地球上行走的天数的python示例:$ python
>>> from datetime import date as D
>>> print (D.today() - D(1980, 6, 14)).days
11476
评论
万一有人希望它像一个命令一样工作,而不是输入交互式解释器:ychaouche @ ychaouche-PC〜$ python -c“ from datetime import date as d; print(d.today()-d( 1980,6,14))。days“ 12813 ychaouche @ ychaouche-PC〜$
–ychaouche
15年7月14日在14:56
这对我有用python3 -c“从datetime导入日期作为d;打印(d.today()-d(2016,1,9))”不需要最后天
– Kiran K Telukunta
16-10-14在5:18
#4 楼
我通常更喜欢将时间/日期设置为unix utime格式(自新纪元(七十年代开始以来的秒数,UTC))。这样,它总是归结为简单的减法或秒的加法。通常的问题是将日期/时间转换为这种格式。
在shell环境/脚本中您可以使用
date '+%s'
来获取它。在撰写本文时,当前时间是
1321358027
。与2011-11-04(我的生日)进行比较,
date '+%s' -d 2011-11-04
产生1320361200
。减去:expr 1321358027 - 1320361200
给出996827
秒,即expr 996827 / 86400
= 11天前。使用标准库,例如从C,PHP或Perl转换为utime(1320361200格式)到日期非常简单。 。
对于GNU
date
,可以在-d
之前加上@
参数,以指示“自大纪元以来的秒数”格式。#5 楼
这是在使用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)
日期在两种情况下均提供正确的输出,但在第二种情况下你问错了问题。重要的是一年中的+/- 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
要使减法成为加法的逆运算,则必须颠倒运算的顺序。加数会增加年份,然后增加几个月,然后增加几天。如果减法使用相反的顺序,那么您将回到起点。如果不是,那么您就不会这样做,如果天数偏移量跨越了另一个长度月份中的月份边界。
如果您需要从结束日期和年龄倒退,则可以这样做与
date
的多个调用。首先减去日期,然后减去月份,然后减去年份。 (由于think年会更改2月的长度,因此我不认为将年和月合并在单个date
调用中是不安全的。)#6 楼
如果图形工具适合您,我衷心推荐qalculate
(一个强调单位转换的计算器,它带有GTK和KDE接口IIRC)。您可以在其中说出例如days(1900-05-21, 1900-01-01)
以获取日期之间的天数(140,因为1900年不是a年),但是您当然也可以这样做时间相同:
17:12:45 − 08:45:12
产生
8.4591667
小时,或者,如果将输出设置为时间格式,则产生8:27:33
。评论
很好,甚至更多,因为qalculate确实具有CLI。尝试使用qalc,然后再帮助几天。
– Sparhawk
2014年7月4日在12:19
qcalc示例:qalc -t'days(1900-05-21,1900-01-01)'-> 140
– sierrasdetandil
19 Mar 25 '19在15:39
#7 楼
计算同一日历年的两个日期之间差异的另一种方法是: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"
第1行向外壳声明要使用的解释器。
第2行将
date
之外的值分配给变量DATEfirstnum。
-d
标志以时间格式显示字符串,格式为2014年5月14日,
+"%j"
告诉date
将输出格式格式化为一年中的第一天(1-365)。3与第2行相同,但日期不同,并且字符串的格式不同,2014年12月31日。
第4行将值
DAYSdif
分配给两个天的差额。
第5行显示
DAYSdif
的值。这适用于
date
的GNU版本,但不适用于PC-BSD / FreeBSD版本。我从端口树安装了coreutils
,并改用了命令/usr/local/bin/gdate
。评论
该脚本将无法运行。最后一行有一个错字,变量赋值周围有空格,因此bash尝试运行一个带有两个参数的名为DATEfirst name的程序。尝试以下操作:DATEfirstnum = $(date -d“ $ 1” +%s)DATElastnum = $(date -d“ $ 2” +%s)此外,此脚本将无法计算两个不同年份之间的差额。 +%j代表一年中的某天(001..366),因此./date_difference.sh 12/31/2001 12/30/2014输出-1。正如其他答案所指出的那样,您需要将两个日期都转换为自1970-01-01 00:00:00 UTC以来的秒数。
–六
15年2月28日在13:29
您不需要$在算术表达式内:$((DATElastnum-DATEfirstnum))也将起作用。
–俄罗斯
18年6月2日在14:26
#8 楼
借助dannas解决方案,可以使用以下代码在一行中完成此操作:python -c "from datetime import date as d; print(d.today() - d(2016, 7, 26))"
(在Python 2.x和Python 3中均可使用)。
#9 楼
我经常使用SQL进行日期计算。例如MySQL,PostgreSQL或SQLite:bash-4.2$ mysql <<< "select datediff(current_date,'1980-06-14')"
datediff(current_date,'1980-06-14')
11477
bash-4.2$ psql <<< "select current_date-'1980-06-14'"
?column?
----------
11477
(1 row)
bash-4.2$ sqlite2 <<< "select julianday('now')-julianday('1980-06-14');"
11477.3524537035
其他时候,我只是对JavaScript有心情。例如SpiderMonkey,WebKit,Seed或Node.js:
bash-4.2$ js -e 'print((new Date()-new Date(1980,5,14))/1000/60/60/24)'
11477.477526192131
bash-4.2$ jsc-1 -e 'print((new Date()-new Date(1980,5,14))/1000/60/60/24)'
11477.47757960648
bash-4.2$ seed -e '(new Date()-new Date(1980,5,14))/1000/60/60/24'
11477.4776318287
bash-4.2$ node -pe '(new Date()-new Date(1980,5,14))/1000/60/60/24'
11624.520061481482
(当将月份传递给JavaScript
Date
对象的构造函数时要小心。从0开始。)#10 楼
date
和bash可以进行日期差异(显示OS X选项)。将后一个日期放在第一位。echo $((($(date -jf%D "04/03/16" +%s) - $(date -jf%D "03/02/16" +%s)) / 86400))
# 31
评论
-jf%D OSX日期选项代表什么?
–SebMa
20年6月29日在12:47
#11 楼
还有结合了GNU日期的GNU单位时间计算:$ gunits $(gdate +%s)sec-$(gdate +%s -d -1234day)sec 'yr;mo;d;hr;min;s'
3 yr + 4 mo + 16 d + 12 hr + 37 min + 26.751072 s
$ gunits $(gdate +%s -d '2015-1-2 3:45:00')sec-$(gdate +%s -d '2013-5-6 7:43:21')sec 'yr;mo;d;hr;min;s'
1 yr + 7 mo + 27 d + 13 hr + 49 min + 26.206759 s
(Linux中的单位是单位,gdate是日期)
#12 楼
github:gist上的datediff.sh#!/bin/bash
#Simplest calculator two dates difference. By default in days
# Usage:
# ./datediff.sh first_date second_date [-(s|m|h|d) | --(seconds|minutes|hours|days)]
first_date=$(date -d "" "+%s")
second_date=$(date -d "" "+%s")
case "" in
"--seconds" | "-s") period=1;;
"--minutes" | "-m") period=60;;
"--hours" | "-h") period=$((60*60));;
"--days" | "-d" | "") period=$((60*60*24));;
esac
datediff=$(( ($first_date - $second_date)/($period) ))
echo $datediff
#13 楼
camh的答案可以解决大部分问题,但是我们可以进行改进以处理舍入,时区等问题,此外,我们还可以提供一些额外的精度和选择单位的能力:datediff() {
#convert dates to decimal seconds since 1970-01-01 00:00:00 UTC
date1seconds=$(date +%s.%N -d "$date1")
date2seconds=$(date +%s.%N -d "$date2")
#Calculate time difference in various time units
timeseconds=$(printf "%0.8f\n" $(bc <<<"scale=9; ($date2sec-$date1sec)"))
timeminutes=$(printf "%0.8f\n" $(bc <<<"scale=9; ($date2sec-$date1sec)/60"))
timehours=$(printf "%0.8f\n" $(bc <<<"scale=9; ($date2sec-$date1sec)/3600"))
timedays=$(printf "%0.8f\n" $(bc <<<"scale=9; ($date2sec-$date1sec)/86400"))
timeweeks=$(printf "%0.8f\n" $(bc <<<"scale=9; ($date2sec-$date1sec)/604800"))
}
-d
告诉date
我们提供了要转换的日期时间。 +%s.%N
从1970-01-01 00:00:00 UTC将日期时间更改为seconds.nanoseconds。 bc
计算两个数字之间的差,并且除法因子得到不同的单位。如果需要,printf
在小数点前添加0(bc
不需要),并确保舍入到最接近的值(bc
只是截断)。您也可以使用awk
。 现在让我们用一个时髦的测试用例来运行它,
date1='Tue Jul 9 10:18:04.031 PST 2020'
date2='Wed May 8 15:19:34.447 CDT 2019'
datediff "$date1" "$date2"
echo $timeseconds seconds
-36971909.584000000 seconds
echo $timeminutes minutes
-616198.493066667 minutes
echo $timehours hours
-10269.974884444 hours
echo $timedays days
-427.915620185 days
echo $timeweeks weeks
-61.130802884 weeks
请注意,由于一个月或一年的长度并不总是同样,这里没有一个“正确”的答案,尽管现在可以使用365.24天作为合理的近似值。
#14 楼
这是一个比较旧的线程,但是我发现了一些有趣的东西。我被困在带有BusyBox(v1.19)的嵌入式系统上,对超级方便的now - 10 days
标记在那里失败感到有些失望。实际上,-d
选项提供的输入格式集非常有限。Recognized TIME formats:
hh:mm[:ss]
[YYYY.]MM.DD-hh:mm[:ss]
YYYY-MM-DD hh:mm[:ss]
[[[[[YY]YY]MM]DD]hh]mm[.ss]
但是,可以对输入日期进行一些数学运算。
鉴于这些格式,我发现将日期的显示日期设置为零会给您上个月的最后一天:
$ date -d 2020.03.00-12:00
Sat Feb 29 12:00:00 EST 2020
输入负数会更进一步:
$ date -d 2020.03.-10-12:00
Wed Feb 19 12:00:00 EST 2020
谁能确认这是否也适用于GNU日期? (尽管
now - 10 days
更好)#15 楼
date -d
特定于GNU日期,未由POSIX定义:https://pubs.opengroup.org/onlinepubs/9699919799/utilities/date.html
已经提到过,这可能更适合于
正确的编程语言。例如PHP:
<?php
$o1 = date_create('2020-02-26');
$o2 = date_create('2020-02-16');
$o3 = date_diff($o2, $o1);
echo 'days: ', $o3->d, "\n";
结果:
days: 10
#16 楼
这是一个相当老的线程,但是我在BusyBox中发现了一些有趣的东西,至少与从已知日期开始添加和减去N个时间单位有关。但是,用另一种方法来确定两个已知日期之间的时间间隔并没有太多。我被困在带有BusyBox的嵌入式系统上,超级方便的
now - 10 days
表示法在这里失败了。实际上,-d
选项提供的输入格式集非常有限。$ busybox date --help
BusyBox v1.19.0 (2019-07-14 10:52:19 UTC) multi-call binary.
Usage: date [OPTIONS] [+FMT] [TIME]
Display time (using +FMT), or set time
[-s,--set] TIME Set time to TIME
-u,--utc Work in UTC (don't convert to local time)
-R,--rfc-2822 Output RFC-2822 compliant date string
-I[SPEC] Output ISO-8601 compliant date string
SPEC='date' (default) for date only,
'hours', 'minutes', or 'seconds' for date and
time to the indicated precision
-r,--reference FILE Display last modification time of FILE
-d,--date TIME Display TIME, not 'now'
-D FMT Use FMT for -d TIME conversion
Recognized TIME formats:
hh:mm[:ss]
[YYYY.]MM.DD-hh:mm[:ss]
YYYY-MM-DD hh:mm[:ss]
[[[[[YY]YY]MM]DD]hh]mm[.ss]
但是,可以对输入日期进行一些数学运算。给定这些格式,我发现将输入日期的天数设置为零会给您上个月的最后一天:
$ date -d 2020.03.00-12:00
Sat Feb 29 12:00:00 EST 2020
此外,输入负数会不断减去向后,我当然没想到:
$ date -d 2020.03.-10-12:00
Wed Feb 19 12:00:00 EST 2020
所以您可以在已知的日期做一些快速数学运算,以生成值以馈入BusyBox
-d
中的date
选项呼叫:#!/bin/bash
#Other shells not tested.
start_year=2020
start_month=1
start_day=20
offset_year=-2
offset_month=4
offset_day=5
new_year=$(( $start_year + $offset_year ))
new_month=$(( $start_month + $offset_month ))
new_day=$(( $start_day + $offset_day ))
new_date$( busybox date -d $new_year.$new_month.$new_day-12:00 +%Y-%m-%d )
echo $new_date
输出:
2018-05-25
谁能确认这是否也适用于GNU,BSD,或MacOS
date
?我当然很欣赏GNU now - 10 days
的性能要好得多,但是我有兴趣使它尽可能地便携。我已经确认Android完全不同(两种方法都无法正常工作)。#17 楼
对于简单的日子,我们可以使用命令date: $ dateA="2020-11-10"
$ dateB="2020-12-28"
$ echo "(`date -d $dateB +%s` - `date -d $dateA +%s`)/86400" | bc
48
-d, --date=STRING display time described by STRING
%s seconds since 1970-01-01 00:00:00 UTC
86400
表示一天中的秒数echo
命令将仅使用所需的数学表达式构建一个字符串,然后bc对其进行解析。对于请添加
n
周,我认为@camh的答案是一种很好的方法: $ dateA="2020-11-10"
$ date -d "$dateA + 3 weeks"
ter dez 1 00:00:00 -03 2020
此外,您可以几天更改
weeks
,月,年等评论
是否有理由为什么要通过bc传递数据,而不是在shell中使用算术替换(使用$((... ...)))来计算结果?另外,您似乎只解决了一半的问题。
– Kusalananda♦
20 Nov 10在12:52
使用较早的命令替换``和bc的唯一原因是使其更简洁。我也更改了答案以涵盖第二个问题。谢谢你的提示。
–丹尼尔·罗莎(Daniel da Rosa)
20 Nov 11在13:57
评论
另请参见UNIX中的工具,以在GNU日期不可用时减去日期。