This question already has an answer here:
How to compare two DateTime strings and return difference in hours? (bash shell)
(1 answer)
Closed 2 years ago.
Is there a way that we can get the time difference in hh:mm:ss format in a shell script?
E.g.,
"StartDateTime": "2020-10-06T20:36:15.706000+05:30",
"EndDateTime": "2020-10-06T21:15:44.505000+05:30",
I was trying to calculate the duration as (EndDateTime-StartDateTime) but doesn't seem to yield the desrired result. Can someone guide me ?
An awk solution with the example text in the file datestamp
awk -F [\"-.T] '
/^\"StartDateTime/ { yr=$5;
mn=$6;
dd=$7;
split($8,tim,":")
}
/^\"EndDateTime/ { yr1=$5;
mn1=$6;
dd1=$7;
split($8,tim1,":")
}
END { dat1=yr1" "mn1" "dd1" "tim1[1]" "tim1[2]"
"tim1[3];
dat2=yr" "mn" "dd" "tim[1]" "tim[2]"
"tim[3];
timdiff=mktime(dat1)-mktime(dat2);
print timdiff/60
}' datestamp
We set up field separators in order to parse the lines in order to extract years, months, days, hours, minutes and seconds. We set up variables for each of these referencing start and end dates/times. We then use awks mktime function to get the epoch format of the start and end dates, get the difference in epoch format and then get an approximate difference in seconds, dividing by 60 to get the difference in minutes.
Related
I have one requirement. in one of the source file I'm getting calendar date as input and while processing the file it has to convert Julian Date format. I just need a Script.
ex:Date: 10-Nov-2020
Julian Date: 2020314
The easiest way is
date -d 10-Nov-2020 +%Y%j
but it seems to count from 1, not 0, so it returns 2020315.
Perl's Time::Piece can be used to get the expected value:
perl -MTime::Piece -lwe '$t = localtime->strptime(shift, "%d-%b-%Y"); print $t->year, $t->yday' -- 10-Nov-2020
You might need sprintf "%03d", $t->yday instead of just $t->yday if you want 2020000 instead of 20200 for the first day.
I have a requirement where I need to kick off certain processes on end of every month. I am getting the date as an Input from previous process and date is in Julian format (for e.g. 2020105 CCYYDDD). I need to check if the date passed is month end. I'm thinking of 2 options:
Directly check if Julian date is month end date.
Convert Julian date to Gregorian or Regular date and then check if it is month end.
In either cases, please guide me to some materials I can refer.
I'm aware I can get the current date using echo $(date '+%Y-%m-%d') and then check if its the last day of the month. But I need to strongly consider the Julian date that is coming as the input to my process as it is being sent by the Business.
Thanks in advance for the help.
If you have Gnu date, you can use the following function:
next_day_of_month () {
date -d "${1:0:4}-01-01 $((10#${1:4:3})) days" +%-d
}
which takes a Julian date in the format you specify, and computes the day of the month of the following day.
If you want a pure bash solution (which, despite the fact that it calls no external utilities, is seriously slow), you can use the following.
There is a not-very-complicated formula which can be used to compute the month corresponding to the day number, but it requires the count of days starting with the previous March 1, rather than with January 1. Correcting the day number in that way requires knowing whether the year is a leap year or not, which makes things just a tad more complicated.
Anyway, here it is. [Note 1]
# Compute the month number (1-12) corresponding to a day in
# in "Julian" format YYYYJJJ (001 == Jan. 1; 365/6 == Dec. 31)
# Yes, I know it's full of magic numbers.
month_for_julian_day () {
local -i y=${1:0:4} j=10#${1:4:3} march1=60
if (( y % 400 == 0 )) || ! (( y % 100 == 0 )) && (( y % 4 == 0)); then
march1=61
fi
if (( j >= march1 )); then j=j-march1; else j=j+305; fi
local -i m=(j*5+461)/153
if (( m > 12 )); then m=m-12; fi
echo $m
}
To make use of this, it would be handy to have
# Advance a Julian date to the next day.
# Note: this one doesn't wrap around. Because of the way it's used
# here, that doesn't matter.
julian_next() { printf "%s%03d" ${1:0:4} $((10#${1:4:3})); }
Then you can define
# Succeeds if the Julian date is the last day of a month
is_last_day_of_month() {
(( $(month_for_julian_day $j) != $(month_for_julian_day $(next_julian $j)) ))
}
Notes:
After I pasted this, I noticed that the syntax highlighter being used here thinks that # starts a comment. That's not true. # only starts a comment if it's the first character in a word. In this case, the assignment j=10#${1:4:3} forces the last three digits of the supplied date to be interpreted in base 10.
I have a CSV file (output from a SQL Query). It has Start Time & Finish Time values given in different columns. I need to get the difference of Start Time and Finish Time and generate an HTML Report based on the difference value. For this, I wanted to include a new column, which will hold the output of "Finish Time" - "Start Time". columns are as below.
Time format is in the below format
START TIME: 2018-11-08 01:45:39.0
FINISH TIME:2018-11-06 06:48:20.0
I used below code, but I am not sure, whether its returning correct values. Any help on this will be appreciated.
Below are the 1st 3 lines of my CSV file
DESCRIPTION,SCHEDULE,JOBID,CLASSIFICATION,STARTTIME,FINISHTIME,NEXTRUNSTART,SYSTEM,CREATIONDATETIME,
DailyClearance,Everyday,XXXXXX, Standard,2018-11-08 01:59:59.0,2018-11-08 02:00:52.0,CAK-456,018-11-08 04:28:18,
Miscellinious,Everyday,XXXXXX, standart,2018-11-08 02:59:59.0,2018-11-08 03:29:39.0,2018-11-09 03:00:00.0,CAT-251,2018-11-08 04:28:18,
And this is my attempt
awk 'NR==1 {$7 = "DIFFMIN"} NR > 1 { $7 = $5 - $6} 1' <inputfile.csv
This might be of assistance to you. The idea is to use GNU awk which has time functions.
awk 'BEGIN{FS=OFS=","}
(NR==1){print $0 OFS "DURATION"; next}
{ tstart = $5; tend = $6
gsub(/[-:]/," ",tstart); tstart=mktime(tstart)
gsub(/[-:]/," ",tend); tend =mktime(tend)
$(NF+1)=tend-tstart;
print
}'
This should add the extra column. The time will be expressed in seconds.
The idea is to select the two columns and convert them into seconds since epoch (1970-01-01T00:00:00). This is done using the mktime function which expects a string of the form YYYY MM DD hh mm ss. That is why we first perform a substitution. Once we have the seconds since epoch for the start and end-time, we can just subtract them to get the duration in seconds.
note: there might be some problems during daylight saving time. This depends on the settings of your system.
note: subsecond accuracy is ignored.
So, I am not a coder but i have to write a shell script that can "call" a timestamp in format [A][21][16][30][4] where A is the Month (A for January, B for February, C for March and so on), 21 is the day, 16 is the hours, 30 is the minutes and 4 are the tenth of a milisecond (0-5). Brackets are only for visualization, so the timestamp should be A2116304
This needs to be either a shell script or a perl code, that is part of a shell script (i need to put this is an existing shell script).
I tried searching for solution, but couldnt find anything useful.
The idea is that i need to append this custom timestamp to a file name, like
FILENAME.TIMESTMAP
Thanks !
Assuming that:
time is now,
time zone is GMT,
you want a fixed length timestamp,
the last digit should be tens of seconds.
I suggest something like:
my ($s, $m, $h, $D, $M) = gmtime;
my $prefix = "snapshot";
my $filename = sprintf "%s.%s%02d%02d%02d%d",
$prefix, chr($M+ord "A"), $D, $h, $m, $s/10;
print $filename, "\n";
Output:
snapshot.J2612182
You can use localtime instead of gmtime if you don't want to use GMT.
Both *time functions take a UNIX timestamp as argument, in case you need something other than now.
This question already has an answer here:
take date from file in unix
(1 answer)
Closed 6 years ago.
I want to take two dates as argument from the user ( ) with
$./tool.sh --born-since <dateA> --born-until <dateB>
and from a file print the lines that are between those two dates.For example:
933|Mahinda|Perera|male|1989-12-03|2010-03-17T13:32:10.447+0000|192.248.2.123|Firefox
1129|Carmen|Lepland|female|1984-02-18|2010-02-28T04:39:58.781+0000|81.25.252.111|Internet Explorer
4194|Hồ ChÃ|Do|male|1988-10-14|2010-03-17T22:46:17.657+0000|103.10.89.118|Internet Explorer
So , i use awk command like this :
awk -F'|' '{print $4} [ file ... ]
to take the dates .. how can i use awk to make the dates from the txt to seconds form ?
if the date variables are in the same format, you can convert everything to numbers and use comparison.
awk -F'|' -v from=$dateA -v to=$dateB '{gsub("-","",$5);
gsub("-","",from); gsub("-","",to)}
from <= $5 && $5 <= to' file
Note, it's the fifth field in your file.
You can either call the /bin/date +"%s" --date="DATESTRING" through system() if the DATESTRING matches a format "/bin/date" understands, or you use the internal mktime() function. But then you need to split your date according to awk(1):
mktime(datespec)
Turn datespec into a time stamp of the same form as returned by systime(), and return the result. The datespec is a string of
the form YYYY MM DD HH MM SS[ DST]. The contents of the string are six or seven numbers representing respectively the full year
including century, the month from 1 to 12, the day of the month from 1 to 31, the hour of the day from 0 to 23, the minute from 0
to 59, the second from 0 to 60, and an optional daylight saving flag. The values of these numbers need not be within the ranges
specified; for example, an hour of -1 means 1 hour before midnight. The origin-zero Gregorian calendar is assumed, with year 0
preceding year 1 and year -1 preceding year 0. The time is assumed to be in the local timezone. If the daylight saving flag is
positive, the time is assumed to be daylight saving time; if zero, the time is assumed to be standard time; and if negative (the
default), mktime() attempts to determine whether daylight saving time is in effect for the specified time. If datespec does not
contain enough elements or if the resulting time is out of range, mktime() returns -1.
So you need to prepare your date fields to use the form given in the documentation.
split($5, D, "-");
DS = sprintf("%4d %2d %2d 00 00 00", D[1], D[2], D[3]);
T = mktime(DS);
should do the job.