I need to substract some date from current date to determine the age of some connections. The date is in this format: YYMMDDHHMISS. The output can be pretty much anything that I can use to determine lets say oldest connection, number of connections older than 1 hour, 1 week, 1 month.

Example of input date: 211013134247

I got to the point of getting date in this format from date command (date '+%g%m%d%H%M%S'), but I don't know how to correctly substract this to get accurate result.

I tried this, but this get problematic as soon as one number from connection date (like seconds) is bigger than current date. Example: connection has 53 as seconds and current seconds are 47.

$line = connection date
$date = current date

  year=   $((${date:0:2} - ${line:0:2}))
  month=  $((${date:2:2} - ${line:2:2}))
  day=    $((${date:4:2} - ${line:4:2}))
  hour=   $((${date:6:2} - ${line:6:2}))
  minute= $((${date:8:2} - ${line:8:2}))
  second= $((${date:10:2} - ${line:10:2})) 


I also tried this (some code shamelessly stolen from stack exchange), but the output is wrong.. I would expect something like: 0607********, as in 6 years 7 months etc.. Input dates generally should not be years apart, so year calculation could be left out.

convert_date(){ printf `date '+%C'`'%s-%s-%s %s:%s:%s' ${1:0:2} ${1:2:2} ${1:4:2} ${1:6:2} ${1:8:2} ${1:10:2}; }
    TS1=$(date -d "$1" +%s)
    TS2=$(date -d "$2" +%s)
    TZ=UTC date -d @$((TS1-TS2)) +%g%m%d%H%M%S

date_converted=`convert_date $date`
echo $date_converted
line_converted=`convert_date $line`
echo $line_converted
diff_dates $date_converted $line_converted

root@SomeHost:~# date="211013150325"
root@SomeHost:~# line="150325113419"
root@SomeHost:~# convert_date(){ printf `date '+%C'`'%s-%s-%s %s:%s:%s' ${1:0:2} ${1:2:2} ${1:4:2} ${1:6:2} ${1:8:2} ${1:10:2}; }
root@SomeHost:~# diff_dates(){
>     TS1=$(date -d "$1" +%s)
>     TS2=$(date -d "$2" +%s)
>     TZ=UTC date -d @$((TS1-TS2)) +%g%m%d%H%M%S
>     #+%Y.%m.%d.%H:%M:%S
> }
root@SomeHost:~# date_converted=`convert_date $date`
root@SomeHost:~# echo $date_converted
2021-10-13 15:03:25
root@SomeHost:~# line_converted=`convert_date $line`
root@SomeHost:~# echo $line_converted
2015-03-25 11:34:19
root@SomeHost:~# diff_dates $date_converted $line_converted

Could I remove TZ=UTC date -d @$((TS1-TS2)) +%g%m%d%H%M%S and get better conversion with something else? With echo $(($TS2-$TS1)) I could get time in seconds, but I don't know how to convert that to a date that doesn't start with 1970...

Maybe (almost certainly) I'm doing this completely wrong and there is much less complicated way of doing this.
I pieced this question together over 2 hours so if there is something that doesn't make sense please point it out and I will try to fix it.

  • Is it the time in line="150325113419 in epoch format? Oct 13 at 14:03
  • No, this line is in YYMMDDHHMISS format.
    – pormulsys
    Oct 14 at 6:46

In zsh:

zmodload zsh/datetime
strftime -rs t %y%m%d%H%M%S $timestamp
print $(( EPOCHSECONDS - t ))

Note that %g is the iso week year, not what you're looking for. For instance on the first of January 2021 (here with the GNU implementation of date for that non-standard -d):

$ date -d 2021-01-01 +%gW%V-%A

It was the Friday of ISO week 53 of 2020, as since that week had more days in 2020 than in 2021, it was counted as a 2020 week, not a 2021 one.

You'd only want to use %g/%G in combination with %V (the ISO week number). %y/%Y is for the current year.

Standard date has no support for parsing dates and reformat them for output (as opposed to set the system time). Several of them support that as an extension in different and incompatible ways. Of those that do, most implementations support specifying the input format in strptime() style (like zsh's strftime builtin with -r above), but GNU date is a notable exception.

  • ast-open date (also the builtin date command of ksh93 if enabled at compile time):

    $ date -p %y%m%d%H%M%S -d 211013134247 +%FT%T%z
    $ date -p %y%m%d%H%M%S -d 211013134247 +%s
  • busybox date:

    $ date -D '%y%m%d%H%M%S' -d 211013134247 +%FT%T%z
    $ date -D '%y%m%d%H%M%S' -d 211013134247 +%s
  • BSD date:

    $ date -jf %y%m%d%H%M%S 211013134247 +%FT%T%z
    $ date -jf %y%m%d%H%M%S 211013134247 +%s

For GNU date, you need to convert the timestamp in one of the formats it supports.

Could be standard 2021-10-13T13:42:47 format with:

$ timestamp=211013134247
$ date -d "20$(echo "$timestamp" | fold -w2 | paste -sd--T::)" +"%s"

(assuming years are from 2000 to 2099 only).

Or using ksh93-style ${param:offset:length} as supported by a few shells now, including bash:

$ date -d "20${t:0:2}-${t:2:2}-${t:4:2}T${t:6:2}:${t:8:2}:${t:10:2}" +%s

With echo $(($TS2-$TS1)) I could get time in seconds, but I don't know how to convert that to a date

You can convert the seconds in hours, minutes, seconds with this command:

 date -d@$SECVAR -u +%H:%M:%S

where variable SECVAR contain the seconds

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.