2

I am trying to convert timestamps read from a file from string to date format so that I can find the difference of 2 dates/timestamps. most of the threads/discussions on web show usage of date argument '-d' to convert the string to epoch or to find the difference of two timestamps Find difference between two dates in bash

But it looks like my environment/OS doesn't support -d date argument. Below are the details of my env:

bash --version
GNU bash, version 3.2.52(1)-release (i386-pc-solaris2.10)
Copyright (C) 2007 Free Software Foundation, Inc.

uname -a
SunOS s01***** 5.10 Generic_147148-26 i86pc i386 i86pc

Sample dates read from file:

START_TIME="09/03/16 - 01:04:56"
END_TIME="09/03/16 - 05:10:44"

Code that I have tried I have tried to mimic the below code from Find difference between two dates in bash

!# /usr/bin/sh

date1="Sat Dec 28 03:22:19 2013"
date2="Sun Dec 29 02:22:19 2013"
date -d @$(( $(date -d "$date2" +%s) - $(date -d "$date1" +%s) )) -u +'%H:%M:%S'

bash test.sh
date: illegal option -- d
usage:  date [-u] mmddHHMM[[cc]yy][.SS]
        date [-u] [+format]
        date -a [-]sss[.fff]
date: illegal option -- d
usage:  date [-u] mmddHHMM[[cc]yy][.SS]
        date [-u] [+format]
        date -a [-]sss[.fff]
test.sh: line 5: -  : syntax error: operand expected (error token is " ")

I don't think syntax error on line 5 is the main culprit cause I didnot find option -d in my date's man page.

In response to comments:

>>> date --version
    date: illegal option -- version
    usage:  date [-u] mmddHHMM[[cc]yy][.SS]
            date [-u] [+format]
            date -a [-]sss[.fff]
    >>> date --help
    date: illegal option -- help
    usage:  date [-u] mmddHHMM[[cc]yy][.SS]
            date [-u] [+format]
            date -a [-]sss[.fff]
    >>> echo $0
    bash

Even these arguments are not supported. Apologies if I am committing any silly mistake.

Could someone please give me the equivalent of -d for the env details shared above or a way to find the difference between two dates without using -d.

Thanks in advance

Community
  • 1
  • 1
whirlcano
  • 43
  • 1
  • 9
  • 2
    IMHO, better post `date --version` and `date --help` (`date --help | fgrep -- -d` for shorter output) instead of `bash --version`. Or, in addition to `bash --version`. – Sasha May 26 '16 at 10:16
  • Can you post the actual error as well please. – 123 May 26 '16 at 10:54
  • 1
    Uer Perl. See: http://stackoverflow.com/a/95539/3776858 – Cyrus May 26 '16 at 10:56
  • The bash version is completely irrelevant -- you'd have this problem with any version of bash, or not using bash at all. (And since you could reproduce the problem without bash, what's the `bash` tag doing here on the question?) – Charles Duffy May 27 '16 at 02:53
  • Hello Cyrus, thanks for the suggestion. I have initially started off with perl for this task and realised that most of the perl date modules like 'Date', 'Time' etc., are not available on my machine. So I was forced to switch to bash. – whirlcano May 27 '16 at 02:56
  • See if you have GNU date installed somewhere. Perhaps under the name `gdate`. – rob mayoff May 27 '16 at 05:39

2 Answers2

1

awk mktime has a decent chance of existing on your system:

#!/bin/bash

START_TIME="09/03/16 - 01:04:56"
END_TIME="09/03/16 - 05:10:44"

echo -e "$START_TIME\n$END_TIME" |
  tr '/:-' ' ' |
  awk '{print "20"$3" "$2" "$1" "$4" "$5" "$6}' |
  awk '{printf "%s ", mktime($0)}' |
  awk '{print $2 - $1}'

explanation:

  1. echo both time strings
  2. tr converts 09/03/16 - 01:04:56 to 09 03 16 01:04:56
  3. first awk changes 09 03 16 01 04 56 to 2016 03 09 01 04 56
  4. second awk converts 2016 03 09 01 04 56 to epoch time: 1457514296 and prints both on one line: 1457514296 1457529044
  5. third awk subtracts first from second, giving difference in seconds: 14748

the awks could also easily be merged, but here i kept each separate for clarity.

webb
  • 4,180
  • 1
  • 17
  • 26
  • mktime [is nonstandard](http://pubs.opengroup.org/onlinepubs/9699919799/utilities/awk.html#tag_20_06_13_14) and may not exist under OP's `awk`. – Kevin May 27 '16 at 06:06
  • Hi Webb, thanks for the step-by-step walkthrough, I have understood what you have suggested but when I tried to mimic the same code, the result is annoying. For any values of start and end times, I am getting the same result "2013". Even when both timestamps are exactly the same. Then I realised, the third awk is doing "2016-03=2013" instead of "end_time - start_time". I guess, as Kevin stated mktime is not supported by my env. Any suggestions to overcome this? Thanks. – whirlcano May 30 '16 at 03:56
  • first, try with `gawk` instead of `awk` in case that exists on your system. otherwise, there is a sub-optimal solution, which is to get to seconds by multiplying the minute field by 60, hour by 60*60, day by 60*60*24, month by... well, have an `if` statement that multiplies each month by the number of seconds in that month... and then year field by 365.25*24*60*60. – webb May 30 '16 at 07:45
0

According to the POSIX standard, date does not do date and time math for you. It gets or sets the system date and time, possibly with timezone adjustments. See date(1) and note the lack of a -d option (or indeed, any interesting options!).

The question becomes "How do we do date and time math without date?" The timestamps you provided do not have time zone information, so the usual behavior is to assume local time. Local time is bad. Seriously. Some time zones have crazy discontinuities or didn't meaningfully exist hundreds of years ago (e.g. most American time zones). So while you might be able to hack together a custom solution that works in your particular part of the world during the recent past, it simply will not be robust.

If you can get your timestamps into Unix time, you can just subtract them, and that will give you a mostly but not entirely correct answer. Unfortunately, to the best of my knowledge, that can't be done at the command line. Unix provides strptime(3) to do this from C (and from there you go on to mktime(3), as shown in this answer), but I don't believe there is any fully standard utility which provides a command-line interface for this. You may have to write and compile your own.

Correcting for leap seconds is difficult in the extreme because, to the best of my knowledge, POSIX has never provided a standard interface for finding out when leap seconds have happened in the past. Such an interface would require internet connectivity in order to remain up-to-date, which is likely a non-starter for a number of implementations. Without knowing more about your system and its capabilities, I simply cannot begin to guess at what will or will not work for your use case.

Community
  • 1
  • 1
Kevin
  • 28,963
  • 9
  • 62
  • 81