Date Comparison in Bash

Date comparison in Bash

You can compare lexicographically with the conditional construct [[ ]] in this way:

[[ "2014-12-01T21:34:03+02:00" < "2014-12-01T21:35:03+02:00" ]]

From the man:

[[ expression ]]

Return a status of 0 or 1 depending on the evaluation of the conditional expression expression.


New update:

If you need to compare times with different time-zone, you can first convert those times in this way:

get_date() {
date --utc --date="$1" +"%Y-%m-%d %H:%M:%S"
}

$ get_date "2014-12-01T14:00:00+00:00"
2014-12-01 14:00:00

$ get_date "2014-12-01T12:00:00-05:00"
2014-12-01 17:00:00

$ [[ $(get_date "2014-12-01T14:00:00+00:00") < $(get_date "2014-12-01T12:00:00-05:00") ]] && echo it works
it works

How to compare two dates of different format?

If you're getting dates in above format, then you need to convert 2nd data string to make it parseable by Unix date command first. Here is an example:

#!/usr/bin/env bash

dt1='Wed 31 Oct 2018 08:42:00 AM UTC'
dt2='12-10-2018 14:37:42'

dt2=$(sed -E 's/^([0-9]{2}-[0-9]{2})-([0-9]{4})/\2-\1/' <<< "$dt2")
echo "$dt2" # 2018-12-10 14:37:42

# compare EPOCH second values of both dates

if (( $(date -d "$dt1" '+%s') < $(date -d "$dt2" '+%s') )); then
echo "date1 is less than date2"
else
echo "date1 is >= than date2"
fi

Comparing two dates in Linux bash shell script

Just a couple simple syntax modifications:

#!/bin/bash

#Setting variable
now=$(date +"%m-%d-%Y")
#Testing variable
echo "Current System Date: $now"
#Setting variable
filedate=$(date -r hello.sh "+%m-%d-%Y")
#Testing variable
echo "hello.sh date: $filedate"

if [[ $now == $filedate ]]
then
echo "This statement works"
else
echo "This statement didnt work"
fi
  • in the if, you must put spaces after [ and before ]
  • you are comparing text, so -ge does not work. the "-" comparisons work for numbers. Here you want to use == to compare text.
  • Reflex for me, I put " around echo text.

This will work for cases where the dates are the same. If you need "greater than" or "smaller than", put the dates in timestamp format (+%s) and compare the numbers. Then you could use the -ge or others of the same type.

Compare a date in a bash script

With your date formats, a simple string comparison should yield the desired result:

#!/bin/bash
[[ 2022-05-20 > 2022-05-19 ]] && echo yes
[[ 2022-05-20 < 2022-05-19 ]] || echo no

Compare two dates in shell/bash script and find days difference

difference() {
date_one=$(date -d "$1" +%s)
date_two=$(date -d "$2" +%s)
echo $(( (date_one - date_two) / 86400 )) days
}

difference 'Fri May 06 02:46:25 IST 2016' $(date)
- 1572 days

"$1" = capture x argument

-d = display time described by string, from input

+%s = transform passed date to epoch time to get as integers

Once in epochs we calculate the seconds of difference and divide by 86400, which is how many seconds in one day, to calculate the number of days between the dates.

bash: date comparison and result steering within jq selection

Assuming that the PieceIDs are unique, here's a jq solution:

jq -Rn '
reduce (
inputs / "\t" |
try ( .[4] |= fromjson ) catch empty |
select(.[4].Action == "GET_AUDIT") |
[
( .[0] | sub("\\.\\d+Z$"; "Z") | strptime("%Y-%m-%dT%H:%M:%SZ") | mktime ),
.[3],
.[4]."Satellite ID",
.[4]."Piece ID"
]
) as [ $time, $event, $satelliteID, $pieceID ] (
[{},{}];
if $event == "download started"
then
.[1][$pieceID] = $time
else
if (.[1] | has($pieceID) | not) or ($time - .[1][$pieceID]) / 60 > 3
then
.[0][$satelliteID] += 1
else
.
end
end
) |
if .[0] != {} then .[0] else empty end
' /mnt/WD1003/logs/sn1.log

Given the following logfile for which I truncated the IDs to 8 chars, removed the irrelevant JSON keys, and marked the unused fields with -:

2022-07-24T02:37:47.570Z    -   -   download started    {"Piece ID": "CDTQRMUZ", "Satellite ID": "1wFTAgs9", "Action": "GET_AUDIT"}
2022-07-24T02:37:47.770Z - - download started {"Piece ID": "CDTQRMUZ", "Satellite ID": "1wFTAgs9", "Action": "GET_AUDIT"}
2022-07-24T02:37:47.815Z - - downloaded {"Piece ID": "CDTQRMUZ", "Satellite ID": "1wFTAgs9", "Action": "GET_AUDIT"}
2022-07-24T02:37:48.107Z - - downloaded {"Piece ID": "CDTQRMUZ", "Satellite ID": "1wFTAgs9", "Action": "GET_AUDIT"}
2022-07-26T15:47:12.285Z - - download started {"Piece ID": "CDTQRMUZ", "Satellite ID": "IADTQX62", "Action": "GET_AUDIT"}
2022-07-26T15:48:13.362Z - - download started {"Piece ID": "GFATHGO2", "Satellite ID": "4EXtmN5f", "Action": "GET_AUDIT"}
2022-07-26T15:48:13.693Z - - downloaded {"Piece ID": "GFATHGO2", "Satellite ID": "4EXtmN5f", "Action": "GET_AUDIT"}
2022-07-26T15:51:23.789Z - - downloaded {"Piece ID": "CDTQRMUZ", "Satellite ID": "IADTQX62", "Action": "GET_AUDIT"}
2022-07-26T16:11:30.625Z - - downloaded {"Piece ID": "MREMD5SU", "Satellite ID": "2LYZZEPV", "Action": "GET_AUDIT"}
2023-01-01T00:00:00.000Z - - "missing TABs" {"Action":"GET_AUDIT"}
2022-01-01T00:00:00.000Z - - "broken JSON" {
2023-01-01T00:00:00.000Z - - "not a JSON object" "string"
2023-01-01T00:00:00.000Z - - "no 'Action' key" {}

remark: you should have posted your input data in this simplified form :-P

The first (...) of reduce will yield something like:

[ 1658633867, "download started", "1wFTAgs9", "CDTQRMUZ" ]
[ 1658633867, "download started", "1wFTAgs9", "CDTQRMUZ" ]
[ 1658633867, "downloaded", "1wFTAgs9", "CDTQRMUZ" ]
[ 1658633868, "downloaded", "1wFTAgs9", "CDTQRMUZ" ]
[ 1658854032, "download started", "IADTQX62", "CDTQRMUZ" ]
[ 1658854093, "download started", "4EXtmN5f", "GFATHGO2" ]
[ 1658854093, "downloaded", "4EXtmN5f", "GFATHGO2" ]
[ 1658854283, "downloaded", "IADTQX62", "CDTQRMUZ" ]
[ 1658854800, "downloaded", "2LYZZEPV", "MREMD5SU" ]

remark: The "missing TABs" and "broken JSON" records are discarded by the try catch filter, while the "not a JSON object" and "no 'Action' key" records are discarded by the select filter

With the current logic the final result will be :

{
"IADTQX62": 1,
"2LYZZEPV": 1
}


Related Topics



Leave a reply



Submit