如何使用 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 ]
您第一次尝试的问题是您试图将 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 指出需要强制将带前导零的数字视为小数。
这是不起作用的:
> 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 ]
您第一次尝试的问题是您试图将 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 theminoff
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 指出需要强制将带前导零的数字视为小数。