Shell time comparisons

June 13, 2014

Applying an operation based on datetime

I just received a question today from a scientist asking how to apply some operation to particular files that fall within some temporal range.

I whipped up a quick example where I convert timestamps to UNIX integer time values (seconds since 1970-01-01 00:00:00) and compare them, then apply some operation.

# Some dummy times.
TIMESTAMPS=$(echo 2010-01-{10..11}T{01..11}:00:00)

STARTTIME=1263074400 # Start somewhere after the begining
STOPTIME=1263160800  # End before the last time

for TIMESTAMP in ${TIMESTAMPS}; do # Loop over all TIMESTAMPS
    UNIXTIME=$(date -d"${TIMESTAMP}" +%s) # Convert timestamp string to integer
    # Test if current timestamp is within target range
    if [[ $UNIXTIME -gt $STARTTIME && $UNIXTIME -lt $STOPTIME ]]; then
        echo "Process file"
    else
        echo "File outside range, do nothing"
    fi
done

Breaking it down

We use shell expansion notation to give us a list of dummy timestamps for testing purposes:

TIMESTAMPS=$(echo 2010-01-{10..11}T{01..11}:00:00)
echo $TIMESTAMPS
2010-01-10T1:00:00 2010-01-10T2:00:00 2010-01-10T3:00:00 2010-01-10T4:00:00 2010-01-10T5:00:00 2010-01-10T6:00:00 2010-01-10T7:00:00 2010-01-10T8:00:00 2010-01-10T9:00:00 2010-01-10T10:00:00 2010-01-10T11:00:00 2010-01-11T1:00:00 2010-01-11T2:00:00 2010-01-11T3:00:00 2010-01-11T4:00:00 2010-01-11T5:00:00 2010-01-11T6:00:00 2010-01-11T7:00:00 2010-01-11T8:00:00 2010-01-11T9:00:00 2010-01-11T10:00:00 2010-01-11T11:00:00

Then we get the UNIX time epoch for the start and stop time:

date -d"2010-01-10T5:00:00" +%s
date -d"2010-01-11T5:00:00" +%s

Now we loop over all TIMESTAMPS:

for TIMESTAMP in ${TIMESTAMPS}; do # Loop over all TIMESTAMPS
    ## DO work in here
done

Inside the loop we convert the ISO time to a UNIX epoch time:

UNIXTIME=$(date -d"${TIMESTAMP}" +%s) # Convert timestamp string to integer

Then test to see if the value is in the range of start - stop time:

if [[ $UNIXTIME -gt $STARTTIME && $UNIXTIME -lt $STOPTIME ]]; then
        echo "Process file"
    else
        echo "File outside range, do nothing"
fi

Output:

File outside range, do nothing
File outside range, do nothing
File outside range, do nothing
File outside range, do nothing
File outside range, do nothing
Process file
Process file
Process file
Process file
Process file
Process file
Process file
Process file
Process file
File outside range, do nothing
File outside range, do nothing
File outside range, do nothing
File outside range, do nothing
File outside range, do nothing
File outside range, do nothing  

Tasking this a bit further and refactoring:

We define a function that operates on our timestamps

dotask() {
    TS=$1
    echo "Process file, $TS"
}

We define a function which takes a list of times, a start and stop time and applys some function to things that fall within the start and stop times.

applywithin() {
## Apply some program/task within a temporal range
    TIMESTAMPS=$1
    STARTTIME=$2
    STOPTIME=$3
    TASK=$4

    for TIMESTAMP in ${TIMESTAMPS}; do # Loop over all TIMESTAMPS
        UNIXTIME=$(date -d"${TIMESTAMP}" +%s) # Convert timestamp string to integer
        # Test if current timestamp is within target range
        if [[ $UNIXTIME -gt $STARTTIME && $UNIXTIME -lt $STOPTIME ]]; then
            $TASK $TIMESTAMP
        else
            echo "File outside range, doing nothing"
        fi
    done

}

TIMESTAMPS=$(echo 2010-01-{10..11}T{01..11}:00:00)
applywithin $TIMESTAMPS 1263074400 1263160800 dotask

Now we can apply any operation we want based on each timestamp.

comments powered by Disqus
Shell time comparisons - June 13, 2014 - Jonah Duckles