Home > database >  How to compare dates formatted as `Tue Aug 30 12:01:37 GMT 2022` in BusyBox/Alpine
How to compare dates formatted as `Tue Aug 30 12:01:37 GMT 2022` in BusyBox/Alpine

Time:06-04

In shell (no bash because of Alpine) using BusyBox, how can I compare two dates both formatted as Tue Aug 30 12:01:37 GMT 2022?

I want to know which one comes first. date doesn't support this input format. I'm only interested in whole days. The time isn't interesting for me. So two dates on the same day but a different time are equal to me.

Of course I could put all the names of the months in a lookup table and use the index of the month as its integer value (to be able to compare) but I have the feeling I shouldn't be the one programming that out...

Update:

/opt/scripts $ a="Tue Aug 30 12:01:37 GMT 2022"
/opt/scripts $ date -d "$a"  %s
date: invalid date 'Tue Aug 30 12:01:37 GMT 2022'
/opt/scripts $ date --help
BusyBox v1.34.1 (2022-04-04 10:19:27 UTC) multi-call binary.

Usage: date [OPTIONS] [ FMT] [[-s] TIME]

Display time (using  FMT), or set time

        -u              Work in UTC (don't convert to local time)
        [-s] TIME       Set time to TIME
        -d TIME         Display TIME, not 'now'
        -D FMT          FMT (strptime format) for -s/-d TIME conversion
        -r FILE         Display last modification time of FILE
        -R              Output RFC-2822 date
        -I[SPEC]        Output ISO-8601 date
                        SPEC=date (default), hours, minutes, seconds or ns

Recognized TIME formats:
        @seconds_since_1970
        hh:mm[:ss]
        [YYYY.]MM.DD-hh:mm[:ss]
        YYYY-MM-DD hh:mm[:ss]
        [[[[[YY]YY]MM]DD]hh]mm[.ss]
        'date TIME' form accepts MMDDhhmm[[YY]YY][.ss] instead
/opt/scripts $

CodePudding user response:

You may have to rely on awk:

/ # cat /etc/alpine-release
3.16.0

/ # echo $a
Tue Aug 30 12:01:37 GMT 2022

/ # TZ=GMT awk -v a="$a" 'BEGIN {
>     split("Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec", months)
>     split(a, date)
>     gsub(/:/, " ", date[4])
> 
>     for (i=1; i<=12; i  ) {
>         if (date[2] == months[i]) {
>             timestamp = date[6] " " i " " date[3] " " date[4]
>             print mktime(timestamp)
>             exit
>         }
>     }
> 
>     print "hmm, " date[2] " is an unknown month"
>     exit 1
> }'
1661860897

CodePudding user response:

Ok, my alpine busybox copy of date doesn't recognize strings as month either.

You want "slick", stick with Glenn's awk solution, so long as the time functions work for you. I hacked out the least-slick kluge using just echo, date, read, if's, and a lot of tempfiles - it's an ugly mess, but it works, and it was a fun exercise in using only the most basic stuff.

/tmp $ ./script
#! /bin/sh

cat "$0"
cd /tmp
echo "01">Jan
echo "02">Feb
echo "03">Mar
echo "04">Apr
echo "05">May
echo "06">Jun
echo "07">Jul
echo "08">Aug
echo "09">Sep
echo "10">Oct
echo "11">Nov
echo "12">Dec

echo "Tue Aug 30 12:01:37 GMT 2022">a_raw 
read -r a_raw<a_raw
echo "Fri Jun  3 09:26:55 CDT 2022">b_raw 
read -r b_raw<b_raw

read -r _ Mon DD tim z YYYY<a_raw
read -r MM<"$Mon"
date -d "$YYYY-$MM-$DD"  "%s">a_epoch
read -r a_epoch<a_epoch

read -r _ Mon DD tim z YYYY<b_raw
read -r MM<"$Mon"
date -d "$YYYY-$MM-$DD"  "%s">b_epoch
read -r b_epoch<b_epoch

if [ "$a_epoch" -lt "$b_epoch" ]
then echo "$a_raw ($a_epoch) is before $b_raw ($b_epoch)"
else if [ "$a_epoch" -gt "$b_epoch" ]
     then echo "$a_raw ($a_epoch) is after $b_raw ($b_epoch)"
     else if [ "$a_epoch" -eq "$b_epoch" ]
          then echo "$a_raw ($a_epoch) is same as $b_raw ($b_epoch)"
          fi
     fi
fi

rm Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec a_raw b_raw a_epoch b_epoch

Tue Aug 30 12:01:37 GMT 2022 (1661817600) is after Fri Jun  3 09:26:55 CDT 2022 (1654214400)

original

What do you mean "date doesn't support this input format"?

Something like this ought to work in sh, though I confess I don't have an alpine handy...

a="Tue Aug 30 12:01:37 GMT 2022"
b="Fri Jun  3 09:26:55 CDT 2022"
a_epoch=`date -d "$a"  %s`
b_epoch=`date -d "$b"  %s`
echo "A: [$a] ($a_epoch)"
echo "B: [$b] ($b_epoch)"
if [ "$a_epoch" -lt "$b_epoch" ]; then echo "$a is before $b"; fi
if [ "$a_epoch" -gt "$b_epoch" ]; then echo "$a is after $b"; fi
if [ "$a_epoch" -eq "$b_epoch" ]; then echo "$a is same as $b"; fi

Should say something like

A: [Tue Aug 30 12:01:37 GMT 2022] (1661860897)
B: [Fri Jun  3 09:26:55 CDT 2022] (1654266415)
Tue Aug 30 12:01:37 GMT 2022 is after Fri Jun  3 09:26:55 CDT 2022

There are cleaner ways, but this should get you started.

Lemme spin up a container and try there, brb...

  • Related