![UNIX(非 posix)从提供的日期算起是一年中的哪一天?](https://linux22.com/image/92069/UNIX%EF%BC%88%E9%9D%9E%20posix%EF%BC%89%E4%BB%8E%E6%8F%90%E4%BE%9B%E7%9A%84%E6%97%A5%E6%9C%9F%E7%AE%97%E8%B5%B7%E6%98%AF%E4%B8%80%E5%B9%B4%E4%B8%AD%E7%9A%84%E5%93%AA%E4%B8%80%E5%A4%A9%EF%BC%9F.png)
我一直在寻找一种现有的解决方案来从 UNIX 平台上的现有日期获取一年中的某一天(不是儒略日期)。
我确信它存在,但我还没有找到它,并且不确定在考虑闰年等时执行准确结果的数学。
答案1
你的标签上写着,solaris
所以我认为这就是你正在使用的平台。
如果您有 Solaris 11 的标准安装,那么您可能已经gdate
安装了
在我的安装上:
lrwxrwxrwx 1 root root 15 Aug 3 13:21 /usr/bin/gdate -> ../gnu/bin/date*
所以你可以使用 GNUdate-d
标志:
例如
% gdate +%j
222
% gdate -d "1970/06/23" +%j
174
答案2
如果你安装了python:
python -c 'import datetime; d=datetime.date(2016, 8, 9); print(d.timetuple().tm_yday)'
或者如果环境变量中有日期:
DATE=2016-08-09
python -c 'import datetime; d=datetime.strptime("'"$DATE"'", "%Y-%m-%d"); print(d.timetuple().tm_yday)'
(您必须调整%Y-%m-%d
才能解析不同的格式)。
两者都作为输出给出222
。
答案3
在 Solaris 11 上(其中/bin/sh
和/bin/ksh
基于ksh93
):
$ /bin/ksh -c 'printf "%(%-j)T\n" 2016-01-01 2016-08-09'
1
222
对于 Solaris 10 及更早版本,您始终可以使用perl
:
$ perl -MPOSIX -le '($y,$m,$d)=@ARGV;
print strftime "%j", 0,0,0, $d,$m-1,$y-1900
' 2016 8 9
222
POSIXly(因此 UNIXly 以及 UNIX 一致性意味着 POSIX 一致性),您可以使用这些 POSIXsh
函数(请注意,在 Solaris 上,POSIX/UNIXsh
位于/usr/xpg*/bin/sh
)https://raw.githubusercontent.com/stephane-chazelas/misc-scripts/master/wide_strftime.sh:
$ timegm 2016 08 09 && wide_strftime '' "$REPLY" && echo "$T_j"
222
(请注意,与perl
的解决方案一样,它是 0 填充的(1 是 001),%-j
要删除不支持填充(它在最新版本中受支持,perl
但在 Solaris 10 上发现的非常旧的 5.8.4 版本中不支持),但您可以调整这些函数来删除填充)。
儒略日数本身位于$T_J
:
$ echo "$T_J"
2457609
答案4
感谢大家的回答,但似乎 Solaris 10 必须实施数学才能实现这一目标。
我决定用另一种方式解决这个问题,即使用 bash & bc 来计算一年中的儒略日。公式描述了这里。原来的函数可以找到这里
下面修改后的函数可以进行转换,然后您可以比较两个日期。
function conv_date_to_julian()
{
local cdate="$(date +%d:%m:%Y)"
local day="${1:=$(echo ${cdate} | cut -d: -f1)}"
local month="${2:=$(echo ${cdate} | cut -d: -f2)}"
local year="${3:=$(echo ${cdate} | cut -d: -f3)}"
local jdoy
if [ ${month} -le 2 ]; then
year=$(( ${year} - 1))
month=$(( ${month} + 12))
fi
jdoy=$(echo "2 - ${year} / 100 + ${year} / 400" | bc)
jdoy=$(echo "(${jdoy} + 365.25 * (${year} + 4716))/1" | bc)
jdoy=$(echo "(${jdoy} + 30.6001 * (${month} + 1))/1" | bc)
echo $(echo "(${jdoy} + ${day} - 1524.5)" | bc)
}
用法示例:
[ $(expr $(conv_date_to_julian 31 12 2017) - $(conv_date_to_julian)) -gt 30 ] && echo true