0

I have a file with the following sample records for buy and sell events

Buy at time=Thu Aug 03 2023 14:13:08 GMT+0200 (Central European Summer Time)

Sell-at time=Thu Aug 03 2023 14:53:02 GMT+0200 (Central European Summer Time)

I want to get whole UTC string from all the lines and get time difference between these records, however, i am not able to extract whole date time string to get differnce between them. i have tried this but not able to get time. Can any one help me out.

while read line
do
    name=$line

    echo $name | sed -e 's/time=\(.*\)(Central/\1/'

done < $1

Solution using shell, awk or sed is required. i can also use GNU date if required

5
  • 1
    Will the two times ever be in different time zones (e.g., when switching to daylight saving time)?
    – Kusalananda
    Commented Aug 5, 2023 at 7:38
  • No, they all are for same time zone. Commented Aug 5, 2023 at 9:25
  • 4
    Please edit your question and add i) your operating system, and whether we can assume you can use GNU tools, especially GNU date (the default on Linux systems) and ii) the exact output you would like to see from your example input. Can you also clarify why you can only use those three specific tools? Would a Perl one liner not be acceptable, for instance?
    – terdon
    Commented Aug 5, 2023 at 13:18
  • Related - Bash: calculate the time elapsed between two timestamps Commented Aug 6, 2023 at 19:46
  • What's a UTC string? Commented Aug 7, 2023 at 6:35

3 Answers 3

2

The dconv of dateutils (called dateutils.dconv on Debian-derived systems) has a sed mode to convert dates. So you could convert your timestamps to epoch time with it and awk to print differences between Sell and Buy dates in seconds:

dateutils.dconv -SE -i ' time=%a %b %d %Y %T GMT%Z' -f '=%s=' < your-file |
  awk -F= '$1 == "Buy at"  {buy = $2; next}
           $1 == "Sell-at" {print $2 - buy}'
1

Assuming you have Bash and GNU/date.

This cuts off the unwanted parts of the date, and then converts a date to epoch (seconds since 01-Jan-1970).

$ Sell='Sell-at time=Thu Aug 03 2023 14:53:02 GMT+0200 (Central European Summer Time)'
$ declare -p Sell
declare -- Sell="Sell-at time=Thu Aug 03 2023 14:53:02 GMT+0200 (Central European Summer Time)"
$ Sell="${Sell/ (*/}"
$ declare -p Sell
declare -- Sell="Sell-at time=Thu Aug 03 2023 14:53:02 GMT+0200"
$ Sell="${Sell/*=}"
$ declare -p Sell
declare -- Sell="Thu Aug 03 2023 14:53:02 GMT+0200"
$ Sell=$( date -d "${Sell}" '+%s' )
$ declare -p Sell
declare -- Sell="1691067182"
$ date -d "@${Sell}"  #.. Check correctness (in UK time).
Thu  3 Aug 13:53:02 BST 2023

Do the same for Buy (maybe declare a function to use twice), and subtract to get the difference in seconds.

2
  • 1
    Using Sell="${Sell% (*}"; Sell="${Sell#*=}" instead of ksh93-style ${Sell/pattern} would make it standard sh syntax and remove the need to install bash or other ksh93-like shell. Commented Aug 7, 2023 at 6:33
  • @StéphaneChazelas Very true. I suspect I was thinking in awk sub() and converting that to Bash. Past my bed-time, I guess. Commented Aug 7, 2023 at 12:18
0

Based on How can I output different data from each line?

You need bash and GNU date command.

With ./data-diff-records.sh script:

#! /usr/bin/env bash

declare -r input_filename="$1"

function get_date () {
    local -r -n l_str="$1"
    local -n li_date="$2"
    local l_date="${l_str#*time=}"
    l_date="${l_date% (Central *}"
    # date transformation to seconds since 1st January 1970
    li_date=$(date -d "$l_date" +'%s')
    # printf "date=<%s>=>%d\n" "$l_date" "$li_date"
}

function diff_date () {
    local -r -n l_start_date="$1"
    local -r -n l_end_date="$2"
    local -n l_seconds_diff="$3"
    local -n l_minutes_diff="$4"
    local -n l_hours_diff="$5"
    l_seconds_diff=$(( l_end_date - l_start_date ))
    l_minutes_diff=$(( l_seconds_diff / 60 ))
    l_seconds_diff=$(( l_seconds_diff - ( l_minutes_diff * 60 ) ))
    l_hours_diff=$(( l_minutes_diff / 60 ))
    l_minutes_diff=$(( l_minutes_diff - ( l_hours_diff * 60 ) ))
}

declare -i date_buy=0
declare -i date_sell=0
declare -i seconds_diff=0
declare -i minutes_diff=0
declare -i hours_diff=0
while read -r line; do
    first_token="${line%% *}"
    case "$first_token" in
        "Buy")
            get_date line date_buy
            # echo "first_token=<$first_token> date=<$date_buy>"
        ;;
        "Sell-at")
            get_date line date_sell
            # echo "first_token=<$first_token> date=<$date_sell>"
            diff_date date_buy date_sell seconds_diff minutes_diff hours_diff
            printf "%02d:%02d:%02d\n" "$hours_diff" "$minutes_diff" "$seconds_diff"
        ;;
    esac
done < "$input_filename"

and:

chmod +x ./data-diff-records.sh

Use it like this (where records.log is the input file):

./data-diff-records.sh records.log

You must log in to answer this question.

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