如何使用 OS X 上的日期命令在任何时区回显自午夜以来的分钟数?

How can I echo minutes since midnight in any timezone using the date command on OS X?

这是不起作用的:

> echo $(( ($(date +%s) - $(date +%s -d$(date +%Y-%m-%d))) / 60 ))
date: illegal time format
usage: date [-jnu] [-d dst] [-r seconds] [-t west] [-v[+|-]val[ymwdHMS]] ... 
            [-f fmt date | [[[mm]dd]HH]MM[[cc]yy][.ss]] [+format]

我也试过:

> echo $(date +%s -f%Y-%m-%d $(date +%Y-%m-%d))

以下有效,但仅适用于标准时间会中断的固定 UTC 偏移量:

> echo $[ ( ( $(date "+%s") - 28800 ) % 86400 ) / 60 ]

参考:OS X date manual

您第一次尝试的问题是您试图将 gnu 日期选项应用于 OSX 上的 BSD 日期。这让我很困惑,因为我试图让脚本在两个平台之间兼容。

一种方法是:

seconds_now=$(date +%s)
seconds_midnight=$(date -j -f'%Y-%m-%d %H:%M:%S' "$(date +%Y-%m-%d) 00:00:00" +%s)
minutes_now=$(((seconds_now - seconds_midnight) / 60))

你必须使用完整的时间格式,否则 date 会取当前时间的实际小时、分钟和秒,这不是你想要的。

另一种方式是:

使用 date +%z 获取与 UTC 的偏移量,并将其应用于当天午夜后的分钟数。

offset=$(date +%z) # get TZ offset as [+-]<HH><MM> - for *now*
sign=${offset:0:1} # get sign
hours=${offset:1:2} # get hours
mins=${offset:3:2} # get minutes
minoff=$((10#$hours * 60 + 10#$mins)) # offset in minutes from UTC
from_midnight_utc_mins=$((($(date +%s) % 86400) / 60))
from_midnight_local=$(($from_midnight_utc_mins $sign $minoff))

不过,这真的很糟糕。

I use 10# for all the numbers in the minoff calculation to prevent the case where two digit numbers with a leading 0 are interpreted as octal, which can yield miscalculations/errors.

自午夜以来的分钟数(或秒数)可以直接根据时间单独计算。

echo $(( $(date "+10#%H * 60 + 10#%M") ))  # Minutes since midnight
echo $(( $(date "+(10#%H * 60 + 10#%M) * 60 + 10#%S") ))  # Seconds since midnight

请注意,这只需要 date 的最低限度支持,因此可用于 GNU 或 BSD date

这通过让 date 输出一个字符串来实现,该字符串可以直接传递给 shell 的算术表达式构造。

感谢 Petesh 指出需要强制将带前导零的数字视为小数。