18

I have written a script that notifies me when a value is not within a given range. All values "out of range" are logged in a set of per day files.

Every line is timestamped in a proprietary reverse way: yyyymmddHHMMSS

Now, I would like to refine the script, and receive notifications just when at least 60 minutes are passed since the last notification for the given out of range value.

I already solved the issue to print the logs in reverse ordered way with:

for i in $(ls -t /var/log/logfolder/*); do zcat $i|tac|grep \!\!\!|grep --color KEYFORVALUE; done

that results in:

...
20170817041001 - WARNING: KEYFORVALUE=252.36 is not between 225 and 245 (!!!)
20170817040001 - WARNING: KEYFORVALUE=254.35 is not between 225 and 245 (!!!)
20170817035001 - WARNING: KEYFORVALUE=254.55 is not between 225 and 245 (!!!)
20170817034001 - WARNING: KEYFORVALUE=254.58 is not between 225 and 245 (!!!)
20170817033001 - WARNING: KEYFORVALUE=255.32 is not between 225 and 245 (!!!)
20170817032001 - WARNING: KEYFORVALUE=254.99 is not between 225 and 245 (!!!)
20170817031001 - WARNING: KEYFORVALUE=255.95 is not between 225 and 245 (!!!)
20170817030001 - WARNING: KEYFORVALUE=255.43 is not between 225 and 245 (!!!)
20170817025001 - WARNING: KEYFORVALUE=255.26 is not between 225 and 245 (!!!)
20170817024001 - WARNING: KEYFORVALUE=255.42 is not between 225 and 245 (!!!)
20170817012001 - WARNING: KEYFORVALUE=252.04 is not between 225 and 245 (!!!)
...

Anyway, I'm stuck at calculating the number of seconds between two of those timestamps, for instance:

20170817040001
20160312000101

What should I do in order to calculate the time elapsed between two timestamps?

13
  • Are you looking for time delta expressed in a particular format, I.E. "HH:MM:SS"? Also, why not just log UNIX timestamps?
    – 111---
    Aug 18, 2017 at 16:21
  • 1
    @Marco see the link in my comment for several ways to calculate the unix timestamp.
    – jesse_b
    Aug 18, 2017 at 16:29
  • 1
    @Jesse_b found it, TY!
    – Marco
    Aug 18, 2017 at 16:32
  • 1
    Oh I also just noticed you are parsing ls in your script. You shouldn't do this. You can do for i in "/var/log/logfolder/*"; instead. mywiki.wooledge.org/ParsingLs
    – jesse_b
    Aug 18, 2017 at 16:43
  • 2
    @Jesse_b that's not really any different to using ls -t; you're still parsing the output of a command that generates a list of filenames. (Oh, -name "*" is almost a no-op; you wouldn't need it here. And how would sort -n be able to sort file names numerically?) Aug 18, 2017 at 21:44

3 Answers 3

25

With the GNU implementation of date or compatible, this will give you the date in seconds (since the UNIX epoch)

date --date '2017-08-17 04:00:01' +%s    # "1502938801"

And this will give you the date as a readable string from a number of seconds

date --date '@1502938801'    # "17 Aug 2017 04:00:01"

So all that's needed is to convert your date/timestamp into a format that GNU date can understand, use maths to determine the difference, and output the result

datetime1=20170817040001
datetime2=20160312000101

# ksh93 string manipulation (also available in bash, zsh and
# recent versions of mksh)
datestamp1="${datetime1:0:4}-${datetime1:4:2}-${datetime1:6:2} ${datetime1:8:2}:${datetime1:10:2}:${datetime1:12:2}"
datestamp2="${datetime2:0:4}-${datetime2:4:2}-${datetime2:6:2} ${datetime2:8:2}:${datetime2:10:2}:${datetime2:12:2}"

# otherwise use sed
# datestamp1=$(echo "$datetime1" | sed -nE 's/(....)(..)(..)(..)(..)(..)/\1-\2-\3 \4:\5:\6/p')
# datestamp2=$(echo "$datetime2" | sed -nE 's/(....)(..)(..)(..)(..)(..)/\1-\2-\3 \4:\5:\6/p')

seconds1=$(date --date "$datestamp1" +%s)
seconds2=$(date --date "$datestamp2" +%s)

# standard sh integer arithmetics
delta=$((seconds1 - seconds2))
echo "$delta seconds"    # "45197940 seconds"

We've not provided timezone information here so it assumes local timezone. Your values for the seconds from the datetime will probably be different to mine. (If your values are UTC then you can use date --utc.)

1
  • When I started writing this post, I was almost sure it would have ended with sed doing the dirty job. TY @roaima
    – Marco
    Aug 18, 2017 at 16:44
14

This is easy with datediff command provided in dateutils package.

datediff -i '%Y%m%d%H%M%S' 20170817040001 20160312000101

See the download page fotlr the latest package and installation file to how to install.

See also project homepage for other distributions installation.

6
  • this on ubuntu 16.04 LTS user@host:/~# apt-get install dateutils [...] Setting up dateutils (0.2.5-1) ... user@host:/~# datediff datediff: command not found user@host:/~#
    – Marco
    Aug 18, 2017 at 19:28
  • 6
    Or dateutils.ddiff
    – MatsK
    Aug 18, 2017 at 20:40
  • This solution is very intresting too, but I keep the sed one in my script; as I find it's most compatible with any GNU Linux and saves me one more dependency.
    – Marco
    Aug 19, 2017 at 6:32
  • 3
    Also, please note that the correct name for this command in Linux Ubuntu 16.04 is dateutils.ddiff
    – Marco
    Aug 19, 2017 at 6:35
  • Anyway I can use dateutils.ddiff to compute the difference between two time durations ?
    – ychaouche
    Jan 18, 2021 at 9:29
-6

Use the expr command, like:

expr 20170817040001 - 20160312000101

Then you have difference between two values in seconds:

expr 20170817040001 - 20160312000101
10505039900
2
  • 2
    Come on, think about it. For simplicity, look at only HHMMSS (assume two entries from the same day). What’s the elapsed time between 12:00:00 and 12:01:00? It’s one minute; i.e., 60 seconds. But 120100−120000 is 100. Apr 18, 2020 at 0:04
  • Obviously he didn't read the question because the main point is exactly getting rid of this customized timestamp. BTW after years I want to inform people that I solved the problem switching to a Unix timestamp, it is not as human readable as this custom one, but you'd better write a log parser script that shows you date in human readable form and let the system work on its own true low level time handling (seconds elapsed since 1/1/70).
    – Marco
    Apr 18, 2020 at 4:04

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .