使用时at midnight next month
,1 月 31 日,它会表现如何?是3月4日还是2月28日?还是3月31日?
答案1
此答案的目标是补充您已经收到的其他(正确)答案,并提供一些额外的技术信息。
当at
commands获取命令时NEXT <inc_dec_period>
1,将当前日期作为时间结构(struct tm
2),并且在指定期间加“1”。
因此,如果at
指示运行NEXT MONTH
,它将采用当前日期,并将“1”添加到月份3,以便 0(一月)变为 1(二月),1 变为 2(三月),依此类推。这相当于date -d 'now + 1 month'
命令。
现在,这是重要的部分:两者date
和at
然后,命令获取操作后创建的新时间结构,并将其用作mktime(3)
返回新绝对时间4的库调用的参数。mktime(3)
文档中指出:
该
mktime()
函数修改了Tm值2结构如下:[...]如果结构成员超出其有效区间,它们将被标准化(例如,10 月 40 日更改为 11 月 9 日));
因此,例如:
- 如果当前日期是 2023-08-31,
- 命令是
next month
, - 新的时间结构为 2023 年 9 月 31 日。
由于 31 超出了 9 月的有效间隔,因此,正如文档所阐明的,它将正常化为 2023 年 10 月 1 日。
$ date -d '2023-08-31 + 1 month' --rfc-3339=date
2023-10-01
如果当前日期是 2023-01-31,则同一命令的结果at
是时间结构 2023-02-31,然后将其标准化为 2023-03-03。
$ date -d '2023-01-31 + 1 month' --rfc-3339=date
2023-03-03
$ date -d '2024-01-31 + 1 month' --rfc-3339=date # leap year
2024-03-02
1
哪里inc_dec_period
是以下之一:
MINUTE | HOUR | DAY | WEEK | MONTH | YEAR
2的tm
结构至少包括以下成员:
int tm_sec seconds [0,61]
int tm_min minutes [0,59]
int tm_hour hour [0,23]
int tm_mday day of month [1,31]
int tm_mon month of year [0,11]
int tm_year years since 1900
int tm_wday day of week [0,6] (Sunday = 0)
int tm_yday day of year [0,365]
int tm_isdst daylight savings flag
3如果月份的结果> 11,年份字段也会加1。
4 返回表示日历时间的mktime
数据类型。time_t
当解释为绝对时间值时,它表示自纪元 1970-01-01 00:00:00 +0000 (UTC) 以来经过的秒数。
答案2
3 月 3 日。
“下个月”的意思是前进一个月,到相同数字的那一天。所以从 1 月 31 日开始,“下个月”就是 2 月 31 日,但这相当于(用手指数...29、30、31)3 月 3 日。如果是闰年,则为 3 月 2 日。同样,3 月 31 日+一个月就是 5 月 1 日,因为 4 月 31 日距离 4 月底只有 1 天休息日。
# date --set '2023-01-31 12:00'
Tue Jan 31 12:00:00 PM UTC 2023
# date
Tue Jan 31 12:00:00 PM UTC 2023
# at midnight next month
warning: commands will be executed using /bin/sh
at Fri Mar 3 00:00:00 2023
at> echo foo
at> <EOT>
job 2 at Fri Mar 3 00:00:00 2023
类似地date
:
# date -d 'now + 1 month'
Fri Mar 3 12:01:32 PM UTC 2023
无论如何,这就是它在我的 Ubuntu 系统上的工作原理。
答案3
要获取当前日期之后的下个月的最后一天,您可以使用date
强制当前日期远离本月的结束日期(以避免超出额外的一个月),date
再次跳转两个月,将天数设置为 01 ,并有一天回去。这是一条单行线。
编辑:发布的第一个版本在四个日期失败,其中下一个月比当前的短:12 月 29 日至 31 日和 7 月 31 日。
$ date # To show where we are now.
Tue 29 Aug 16:29:44 BST 2023
$ echo | at "$( date -d "$( date '+%Y-%m-15' ) + 2 months" '+%Y-%m-01') - 1 day"
warning: commands will be executed using /bin/sh
job 73 at Sat Sep 30 16:29:00 2023
$ atq
73 Sat Sep 30 16:29:00 2023 a paul
这个想法的一些扩展将能够使用%w
(星期几)选项将日期转移到该月的最后一个星期五(例如)。