2

我想在纪元时间内“下一次出现下午 3 点”。

这里的例子: http ://www.gnu.org/software/coreutils/manual/html_node/Examples-of-date.html

和这里的手册: http ://www.gnu.org/software/coreutils/manual/html_node/Relative-items-in-date-strings.html#Relative-items-in-date-strings

似乎没有涵盖这种情况。

需要明确的是,如果当前日期是 8 月 20 日下午 5 点,我希望它返回 8 月 21 日下午 3 点的纪元秒数。如果当前日期是 8 月 20 日下午 2 点,我希望它返回 8 月 20 日下午 3 点的纪元秒数。

我尝试了以下方法,但它总是在今天下午 3 点返回:

date -d "15:00:00" +%s
4

3 回答 3

5

由于我的声誉,无法编辑或评论@paxdiablo 的答案,所以我会写在这里:

首先,它是行不通的。date+%H可以返回以“0”开头的数字。例如,在 09:00 它会抛出这个错误:

bash: [[: 09: value too great for base (error token is "09")

所以不要使用+%H你应该使用+%kor +%_H(这两个是完全相同的)

另一件事是我不建议将[[ ]]其用于数学。仅仅因为 bash 具有(( ))此功能,并且有正常的运算符,例如>=而不是-ge参数。

此外," "如果您不使用变量,请不要使用。使用' '. 这样代码更清晰,更容易理解。

所以,固定版本在这里:

if (( $(date +%_H) >= 15 )); then
    date -d 'tomorrow 15:00' +%s
else
    date -d '15:00' +%s
fi

这是略有不同的版本。我更喜欢这个,因为这样更容易维护代码。

nextHour=15
dateStr="$nextHour:00"
(( $(date +%_H) >= nextHour )) && dateStr="tomorrow $dateStr"
date -d "$dateStr" +%s

好的!如果您不需要确切的时间,这将起作用。现在,如果您想使用准确的时间怎么办?喜欢15:27

方法略有不同:

nextTime='15:27'
secondsEarly=$(date -d "$nextTime" +%s)
secondsLate=$(date -d "tomorrow $nextTime" +%s)
secondsNow=$(date +%s)
(( secondsEarly > secondsNow )) && echo "$secondsEarly" || echo "$secondsLate"

我希望这回答了你的问题。我建议您使用最后一个变体。

PS哦,最后一段代码在使用早期日期的情况下做了一个不需要的操作。这是一个稍微优化的代码:

nextTime='15:27'
secondsEarly=$(date -d "$nextTime" +%s)
(( secondsEarly > $(date +%s) )) && echo "$secondsEarly" || date -d "tomorrow $nextTime" +%s

但如果我是你,我不会使用它,因为以前的代码更具可读性。

于 2013-08-21T06:23:12.410 回答
1

您总是可以先检查小时,例如:

if [[ $(date +1%H) -ge 115 ]] ; then
    date -d "tomorrow 15:00:00" +%s
else
    date -d "15:00:00" +%s
fi

1日期格式和小时前面的是15为了确保返回的两种可能性date +%H不会被视为无效的八进制数(0809)。这实际上有点杂乱无章,因此您可以将数字比较与date自身结合使用:

if [[ $(date +%s) -ge $(date -d "15:00" +%s) ]] ; then
    date -d "tomorrow 15:00" +%s
else
    date -d "15:00" +%s
fi

这不会生成以开头的数字,0因此八进制问题是无关紧要的。它也适用于任意时间,例如13:22:17.

以下记录表明这是行动:

pax> date
Wednesday 21 August  15:46:16 WST 2013

pax> if [[ $(date +%s) -ge $(date -d "15:00" +%s) ]]
...>     then date -d "tomorrow 15:00"
...>     else date -d "15:00"
...> fi
Thursday 22 August  15:00:00 WST 2013

pax> if [[ $(date +%s) -ge $(date -d "16:00" +%s) ]]
...>     then date -d "tomorrow 16:00"
...>     else date -d "16:00"
...> fi
Wednesday 21 August  16:00:00 WST 2013

也许更好的方法是使用以下功能:

#!/bin/bash

nexttime() {
    if [[ $(date +%s) -ge $(date -d $1 +%s) ]] ; then
        date -d "tomorrow $1"
    else
        date -d $1
    fi
}

echo $(nexttime $1)

当您在不同时间使用各种选项运行它时,您可以看到它是如何工作的:

pax> date
Wednesday 21 August  15:59:24 WST 2013

pax> qq.sh 16:00
Wednesday 21 August 16:00:00 WST 2013

... waits a few minutes

pax> date
Wednesday 21 August  16:04:51 WST 2013

pax> qq.sh 16:00
Thursday 22 August 16:00:00 WST 2013

而且,在任意时间,您可以看到它从今天切换到明天:

pax> date ; qq.sh 16:08:32
Wednesday 21 August  16:08:25 WST 2013
Wednesday 21 August 16:08:32 WST 2013

pax> date ; qq.sh 16:08:32
Wednesday 21 August  16:08:28 WST 2013
Wednesday 21 August 16:08:32 WST 2013

pax> date ; qq.sh 16:08:32
Wednesday 21 August  16:08:30 WST 2013
Wednesday 21 August 16:08:32 WST 2013

pax> date ; qq.sh 16:08:32
Wednesday 21 August  16:08:32 WST 2013
Thursday 22 August 16:08:32 WST 2013

pax> date ; qq.sh 16:08:32
Wednesday 21 August  16:08:34 WST 2013
Thursday 22 August 16:08:32 WST 2013
于 2013-08-21T03:08:12.863 回答
1

使用小的 If/Else 语句

还有其他方法,但一种方法是简单地将当前时间与今天的目标时间进行比较,看看现在是早于还是晚于目标时间。例如:

# Store some timestamps for comparison.
_now=$(date +%s)
_3pm_today=$(date -d "15:00:00 today" +%s)
_3pm_tomorrow=$(date -d "15:00:00 tomorrow" +%s)

# If target time is in the future, show stores today's value. Else store 
# tomorrow's value instead.
if [[ $_3pm_today -ge $_now ]]; then
    date=$_3pm_today
else
    date=$_3pm_tomorrow
fi
于 2013-08-21T06:56:00.090 回答