TypeCodes

shell遍历输出两个日期范围内所有的日期

在平常c/c++开发中经常遇到日期处理的情形,例如求两个给定的日期之间相差的天数或者需要使用map存储两个固定日期范围内的所有日期。前段时间项目中需要用shell脚本批量处理给定的两个日期范围内所有日期产生的日志,当时以为shell处理不方便就用c++来处理了。后面用shell实现了下,发现也挺简单的。

shell遍历输出两个日期范围内所有的日期

1 思路流程

1、显然不能直接把这两个日期当作整数相减得到差值然后把初始日期不断累加1得到所有的日期,而且要考虑大小月的问题。

2、为了以后开发的方便,需要把这个求两个固定上期范围内的所有日期功能封装在一个函数(即下面脚本中的genAlldate)中。

但是shell的function不能像C/C++那样能return一个数据类型,也没有引用或者指针的功能,所以在需要先声明一个数组变量DATE_ARRAY用于存放计算出来的所有日期,然后在函数遍历中直接写入每个日期数据。

3、最后使用了3种方法来遍历输出数组DATE_ARRAY存放的所有日期。

4、输出的日期格式尽量能够自定义,例如2017-03-30、2017.06.18和20170618等等。

2 shell程序

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
#!/bin/bash
# FileName:      alldateduringtwodays1.sh
# Description:   Print all the date during the two days you inpute.
# Simple Usage:  ./alldateduringtwodays1.sh 2017-04-01 2017-06-14 or ./alldateduringtwodays1.sh 20170401 20170614 [-]
# (c) 2017.6.15 vfhky https://typecodes.com/linux/alldateduringtwodays1.html
# https://github.com/vfhky/shell-tools/blob/master/datehandle/alldateduringtwodays1.sh


if [[ $# -le 2 || $# -gt 3 ]]; then
    echo "Usage: $0 2017-04-01 2017-06-14 [-]  or  $0 20170401 20170614 [-] ."
    exit 1
fi

START_DAY=$(date -d "$1" +%s)
END_DAY=$(date -d "$2" +%s)
# The spliter bettwen year, month and day.
SPLITER=${3}


# Declare an array to store all the date during the two days you inpute.
declare -a DATE_ARRAY


function genAlldate
{
    if [[ $# -ne 3 ]]; then
        echo "Usage: genAlldate 2017-04-01 2017-06-14 [-]  or  genAlldate 20170401 20170614 [-] ."
        exit 1
    fi

    START_DAY_TMP=${1}
    END_DAY_TMP=${2}
    SPLITER_TMP=${3}
    I_DATE_ARRAY_INDX=0

    # while [[ "${START_DAY}" -le "${END_DAY}" ]]; do
    while (( "${START_DAY_TMP}" <= "${END_DAY_TMP}" )); do
        cur_day=$(date -d @${START_DAY_TMP} +"%Y${SPLITER_TMP}%m${SPLITER_TMP}%d")
        DATE_ARRAY[${I_DATE_ARRAY_INDX}]=${cur_day}

        # We should use START_DAY_TMP other ${START_DAY_TMP} here.
        START_DAY_TMP=$((${START_DAY_TMP}+86400))
        ((I_DATE_ARRAY_INDX++))

        #sleep 1
    done
}

# Call the funciotn to generate date during the two days you inpute.
genAlldate "${START_DAY}" "${END_DAY}" "${SPLITER}"


# [Method 1] Traverse the array.
echo -e "[Method 1] Traverse the array."
for SINGLE_DAY in ${DATE_ARRAY[@]};
do
    echo ${SINGLE_DAY}
done


# [Method 2] Traverse the array.
echo -e "\n[Method 2] Traverse the array."
for i in "${!DATE_ARRAY[@]}"; do 
    printf "%s\t%s\n" "$i" "${DATE_ARRAY[$i]}"
done


# [Method 3] Traverse the array.
echo -e "\n[Method 3] Traverse the array."
i=0
while [ $i -lt ${#DATE_ARRAY[@]} ]
do
    echo ${DATE_ARRAY[$i]}
    let i++
done

# If you do not need this array any more, you can unset it.
# unset DATE_ARRAY

exit 0

3 测试

该shell脚本支持的输入日期格式为2017-04-0120170401这两种,输出的日期格式格式很灵活,只要在执行程序时再追加一个任意日期分隔符(例如常见的.-等)即可,最后由脚本中的SPLITER变量做输出格式控制。

这里使用./alldateduringtwodays1.sh 2017-03-30 2017-04-02 .进行测试,效果如下图所示。

shell遍历输出两个日期范围内所有的日期

4 脚本管理

目前已经把这个脚本放在Github了,地址是https://github.com/vfhky/shell-tools,以后脚本的更新或者更多好用的脚本也都会加入到这个工程中。

打赏支持

Comments »