0

I have below output with jq command , where I want to compare all the date & time and tell which is the latest one

Mon Feb 20 09:22:25 2023
Mon Feb 20 17:42:13 2023
Thu Mar  2 05:55:07 2023
Tue Feb 28 16:02:40 2023

Please guide how I can do this I have seem multiple answers for comparing two dates not sure how I can compare date and time, Also to compare do I need to covert above timestamp to a particular format,

Please guide

Regards, SAMURAI

2
  • 1
    jq has strptime() and sort/sort_by(), so you should be able to do it there. Commented Mar 2, 2023 at 9:13
  • Can you show the actual JSON? This would be relatively easy to do with jq on the original JSON document.
    – Kusalananda
    Commented Mar 2, 2023 at 9:57

3 Answers 3

1

Assuming that you have some JSON document like this:

[
   { "datestring": "Mon Feb 20 09:22:25 2023" },
   { "datestring": "Mon Feb 20 17:42:13 2023" },
   { "datestring": "Thu Mar  2 05:55:07 2023" },
   { "datestring": "Tue Feb 28 16:02:40 2023" }
]

(You can create this from the data in the question using jq -Rn '[inputs] | map({datestring: .})', but I'm assuming that you have this data in some JSON document already.)

... then you may use jq to convert these date strings into Unix timestamps (which are integers) with strptime() and mktime, and then sort the original strings using these timestamps as the sorting key.

jq 'sort_by(.datestring|strptime("%a %b %e %H:%M:%S %Y")|mktime)' file

This computes the Unix timestamp for each entry in the top-level array in our example document. It does this by parsing the given date string with strptime() given a specific format string (see the manual for strptime on your system for what this format string means) and converting the generated time representation to a Unix timestamp integer with mktime. This Unix timestamp is then used by sort_by() to sort the entries in ascending order.

Given the example document above, this would produce the equivalent of the following:

[
   { "datestring": "Mon Feb 20 09:22:25 2023" },
   { "datestring": "Mon Feb 20 17:42:13 2023" },
   { "datestring": "Tue Feb 28 16:02:40 2023" },
   { "datestring": "Thu Mar  2 05:55:07 2023" }
]

A slightly more efficient way of doing this is to pre-calculate the Unix timestamps, sort using these, and then delete them again (a sort of Schwartzian transform):

jq 'map(.ts = (.datestring|strptime("%a %b %e %H:%M:%S %Y")|mktime)) | sort_by(.ts) | map(del(.ts))' file
0

you can use date command to convert those dates to unix timestamps and just sort them, and you can then convert them back to any format you want.

Example, converting date to timestamp and then back:

date -d "Mon Feb 20 09:22:25 2023" +%s
1676884945
date -d "@1676884945" +%c
Mon Feb 20 09:22:25 2023
  • -d says to show date/time expressed in the string, if you use unix time you need to put @ before the time
  • +%s says to show date in unix epoch time
  • +%c says show date in locale setting time format

You can then put those in some loops and convert time to unix epoch, sort easily and convert sorted back to any time format you want.

If you have dates in datefile, this would convert them to unix timestamp and sort them.

while IFS= read -r line; do date -d "$line" +%s; done < datefile  | sort -n

you can then convert those sorted one back to any format you want

for i in $(while IFS= read -r line; do date -d "$line" +%s; done < datefile  | sort -n); do date -d "@$i" +%c; done

For the example you gave you would get something like this

for i in $(while IFS= read -r line; do date -d "$line" +%s; done < datefile  | sort -n); do date -d "@$i" +%c; done
Mon Feb 20 09:22:25 2023
Mon Feb 20 17:42:13 2023
Tue Feb 28 16:02:40 2023
Thu Mar  2 05:55:07 2023

Note, when you use %c you will get output in the format with accordance your locale settings, so not necessary the format you want.

If you would want to be sure to get the format from your example you would need to use +'%a %b %d %T %Y'

for i in $(while IFS= read -r line; do date -d "$line" +%s; done < datefile  | sort -n); do date -d "@$i" +'%a %b %d %T %Y'; done
Mon Feb 20 09:22:25 2023
Mon Feb 20 17:42:13 2023
Tue Feb 28 16:02:40 2023
Thu Mar 02 05:55:07 2023
  • %a abbreviated three letter day
  • %b abbreviated three letter month
  • %d day of month
  • %T time with leading zero
  • %Y year

You can also do conversion to something like year, month, day, time in all numbers with no spaces like 20230220092225 with format '%Y%m%dH%M%S' and use that format for sorting or comparing dates

date -d "Mon Feb 20 09:22:25 2023" +'%Y%m%d%H%M%S'
20230220092225
2
  • Hello Ralz, Thanks for your time and guidance I have understood, here I am not sure how to do comparison of 4 dates like if [ date1 -ge date2 ] if it was same date then I can use [[ date1 = date2 && date3 == date4*]] this where I am not sure what to use and how
    – Samurai
    Commented Mar 2, 2023 at 9:11
  • if you convert the date to unix time, you can simply compare unix time which number is greater, if the dates are not the same convert them to unix time and compare which number is bigger, that would be the quickest thing to do, without parsing formating, you can also convert them to 20230220092225 format '%Y%m%dH%M%S'. see also this unix.stackexchange.com/questions/84381/…
    – ralz
    Commented Mar 2, 2023 at 9:20
0

With GNU sort or compatible, you can sort that input chronologically using:

LC_ALL=C sort -b -k5,5rn -k2,2rM -k3,3rn -k4,4r

Here in reverse from latest to oldest so you can pipe to head -n1 to get the the latest. The non-standard part is the M flag to the second sort key to sort based on month names or abbreviations (here using LC_ALL=C to force English ones).

Note that jq has time parsing and formatting functions, so you should be able to tell jq to sort that array of date directly from the jq invocation that produces your output in the first place.

You must log in to answer this question.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.