【问题标题】:Date values between two times for each day of the month一个月中每一天两次之间的日期值
【发布时间】:2019-08-16 08:03:39
【问题描述】:

我有一项任务需要从 API 中提取数据。我需要指定仅在给定月份的每天早上 7 点到晚上 9 点之间收集数据。

这将是一个 Bash 脚本,将使用 cron 在每月 1 日的 00:01 运行。

API 只接受 Epoch 时间的时间。脚本需要足够灵活,这样我就不必在一年中的每一天都编写代码。

我无法解决这个问题。我可以得到一个月的第一天,纪元时间为上午 7 点,纪元时间为晚上 9 点,API 将接受这两个纪元值并在两次之间查找。

我还可以在上午 7 点和晚上 9 点再次获取该月的最后一天。

我无法弄清楚早上 7 点和晚上 9 点之间的第一天和最后一天之间的天数。

START_LAST_MONTH=$(date "+%Y-%m-01" -d "-1 Month");
START_DAY_SEVEN_AM_EPOCH_DATE=$(date +%s -d"$START_LAST_MONTH 7am");
START_DAY_NINE_PM_EPOCH_DATE=$(date +%s -d"$START_LAST_MONTH 9pm");


END_LAST_MONTH=$(date "+%Y-%m-%d" -d "$START_LAST_MONTH +1 month -1 day");
END_DAY_SEVEN_AM_EPOCH_DATE=$(date +%s -d"$END_LAST_MONTH 7am");
END_DAY_NINE_PM_EPOCH_DATE=$(date +%s -d"$END_LAST_MONTH 9pm");

我正在考虑实现此目的的一种方法是在上午 7 点和晚上 9 点 START_DAY 变量中添加 86400 秒,通过这样做创建新变量,然后向上增加一天,直到 END_DAY 上午 7 点和晚上 9 点 Epoch 时间变量被命中。这对于每个月应该是灵活的,因为一个月的天数会有所不同。

但这超出了我的 bash 脚本编写技能,我正在学习如何实现这一点,所以任何帮助都将不胜感激,从另一个角度来看也很好。

更新:

我现在在 bash 脚本中有这个

#!/bin/sh -x

START_LAST_MONTH=$(date "+%Y-%m-01" -d "-1 Month");
START_DAY_SEVEN_AM_EPOCH_DATE=$(date +%s -d"$START_LAST_MONTH 7am");
START_DAY_NINE_PM_EPOCH_DATE=$(date +%s -d"$START_LAST_MONTH 9pm");


END_LAST_MONTH=$(date "+%Y-%m-%d" -d "$START_LAST_MONTH +1 month -1 day");
END_DAY_SEVEN_AM_EPOCH_DATE=$(date +%s -d"$END_LAST_MONTH 7am");
END_DAY_NINE_PM_EPOCH_DATE=$(date +%s -d"$END_LAST_MONTH 9pm");

until [ $END_DAY_SEVEN_AM_EPOCH_DATE ]
do
let ADD_ONE_DAY=$START_DAY_SEVEN_AM_EPOCH_DATE+86400
echo $ADD_ONE_DAY
done


但它根本没有回显 ADD_ONE_DAY 变量。使用 -X 调试时,它会到这里:直到 [ $END_DAY_SEVEN_AM_EPOCH_DATE ] 并且不做任何进一步的事情。

【问题讨论】:

    标签: linux bash date


    【解决方案1】:

    您更新的示例代码的问题在于,在循环条件下,您实际上只检查了$END_DAY_SEVEN_AM_EPOCH_DATE 不为空 - 这只是在上面设置了两行,因此永远不会执行循环体。

    要使您的示例按预期工作,请尝试以下修改:

    #!/bin/sh -x
    
    START_LAST_MONTH=$(date "+%Y-%m-01" -d "-1 Month");
    START_DAY_SEVEN_AM_EPOCH_DATE=$(date +%s -d"$START_LAST_MONTH 7am");
    START_DAY_NINE_PM_EPOCH_DATE=$(date +%s -d"$START_LAST_MONTH 9pm");
    
    
    END_LAST_MONTH=$(date "+%Y-%m-%d" -d "$START_LAST_MONTH +1 month -1 day");
    END_DAY_SEVEN_AM_EPOCH_DATE=$(date +%s -d"$END_LAST_MONTH 7am");
    END_DAY_NINE_PM_EPOCH_DATE=$(date +%s -d"$END_LAST_MONTH 9pm");
    
    ADD_ONE_DAY=$START_DAY_SEVEN_AM_EPOCH_DATE
    until [ "$ADD_ONE_DAY" -gt "$END_DAY_SEVEN_AM_EPOCH_DATE" ]
    do
    let ADD_ONE_DAY=$ADD_ONE_DAY+86400
    echo $ADD_ONE_DAY
    done
    
    1. 调整循环条件,测试$ADD_ONE_DAY是否大于$END_DAY_SEVEN_AM_EPOCH_DATE
    2. 用循环前$START_DAY_SEVEN_AM_EPOCH_DATE初始化$ADD_ONE_DAY
    3. 在循环内将$ADD_ONE_DAY 增加一天(而不是$START_DAY_SEVEN_AM_EPOCH_DATE,这会导致始终相同的值,即无限循环)

    使用seq 命令循环一个月的所有日子的另一种解决方案可能是:

    #!/bin/bash
    
    START_LAST_MONTH=$(date "+%Y-%m-01" -d "-1 Month")
    END_LAST_MONTH=$(date "+%Y-%m-%d" -d "$START_LAST_MONTH +1 month -1 day")
    
    CURRENT_YEAR=$(date +%Y -d "-1 Month")
    CURRENT_MONTH=$(date +%m -d "-1 Month")
    LAST_DAY_OF_MONTH=$(date +%d -d "$END_LAST_MONTH");
    
    for CURRENT_DAY in $(seq -w 1 "$LAST_DAY_OF_MONTH"); do
        CURRENT_DATE="$CURRENT_YEAR-$CURRENT_MONTH-$CURRENT_DAY"
        CURRENT_DAY_SEVEN_AM_EPOCH=$(date +%s -d"$CURRENT_DATE 7am")
        CURRENT_DAY_NINE_PM_EPOCH=$(date +%s -d"$CURRENT_DATE 9pm")
    
        echo "$CURRENT_DAY_SEVEN_AM_EPOCH - $CURRENT_DAY_NINE_PM_EPOCH"
    done
    

    这里seq -w 1 "$LAST_DAY_OF_MONTH" 将生成一个从1 到相应月份最后一天的序列,-w 输出等宽 的数字,如有必要,补0,即“01”, “02”,...

    【讨论】:

    • 感谢详细的回复,我会试试这个。很棒的帖子
    • 完美你的第二个代码运行良好,完全符合我想要的格式。我正在从中学习,所以谢谢你
    • 我能问一下您为什么在第二段代码中以这种方式命名变量。因为CURRENT_MONTH=$(date +%m -d "-1 Month") 这让我有点失望。它被称为当前月份,但您仍然减去 1 个月。我猜它只是变量的任意标签,仅此而已,因为在了解有关 seq 命令的更多信息后,我确实了解这段代码在做什么
    • 是的,命名可能有点随意(= 我将其命名为 CURRENT_MONTH 以在 CURRENT_DATE 中使用以读取为 当前在此循环迭代中处理的日期 .所以命名确实不一定完美。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2022-06-10
    • 1970-01-01
    • 1970-01-01
    • 2012-10-28
    • 2019-04-12
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多