I have a simple gnuplot command file:
....
set xdata time
set timefmt "%s"
set format x "%H:%M"
....
where x - timestamp column.
Result - time in UTC format. Can I change local timezome for x axis ?
Just came across this in the docs today:
The conversion to and from seconds assumes Universal Time (which is the same
as Greenwich Standard Time). There is no provision for changing the time
zone or for daylight savings. If all your data refer to the same time zone
(and are all either daylight or standard) you don't need to worry about these
things. But if the absolute time is crucial for your application, you'll
need to convert to UT yourself.
From help time/date
I just ran across this today. You don't need to change the format, just change the data. If data.txt contains timestamps in UTC, and you want to display them in PDT (-7 hours off from UTC), simply use:
plot 'data.txt' using ($1+(-7*3600)):2
This subtracts 7 hours (in seconds) from each x value.
A bit late to the party, and I don't have enough reputation points to comment, but to add to anthony and hermannk's answer, this is how I implemented it with their information:
in command.gnuplot, assuming that the first field contains the date/time and the second field contains the value for the Y axis:
plot "inputfile" using ($1 - offset):2
from the (bash) command line, when invoking gnuplot:
gnuplot -e "offset=$(date +%s -d '1 Jan 1970')" command.gnuplot
The offset generally will work OK because gnuplot internally interprets date/time as seconds from epoch. I don't know if the form "offset=$(date ...)" is a bash specific thing, but you could always use "offset=`date ...`" instead.
EDIT --
I found this not to work very well when dealing with DST/Summer Time changes. I changed the offset calc to this, and now it works better:
in command.gnuplot, assuming that the first field contains the date/time and the second field contains the value for the Y axis:
plot "inputfile" using ($1 + offset):2
from the (bash) command line, when invoking gnuplot:
gnuplot -e "offset=$(echo "$(date +%z) * 36" | bc)" command.gnuplot
How does this work?
date +%z provides the timezone offset in the form -0400 or similar, which means Local_Time = UTC - 4 hours. If we consider this a number (-400), then the offset, in seconds, is -400 / 100 * 3600 = -400 * 36.
Note that this won't work with timezones that have 30 minutes increments (India?), but I'm sure with some creating math, you can cover that as well.
In addition to previous correct answer, there is how I do this under bash
From version 4.1 of bash, you could avoid using forks to date for this:
printf -v tzoff "%(%z)T" -1
tzoff=${tzoff:0:1}$(( ( 10#${tzoff:1:2}* 3600 + 10#${tzoff:3:2}* 60 ) ))
Some samples:
TZ=Asia/Katmandu printf -v tzoff "%(%z)T" -1
echo $tzoff
+0545
tzoff=${tzoff:0:1}$(( ( 10#${tzoff:1:2}* 3600 + 10#${tzoff:3:2}* 60 ) ))
echo $tzoff
+20700
TZ=America/Chihuahua printf -v tzoff "%(%z)T" -1
echo $tzoff
-0700
tzoff=${tzoff:0:1}$(( ( 10#${tzoff:1:2}* 3600 + 10#${tzoff:3:2}* 60 ) ))
echo $tzoff
-25200
Then alternatively add this $tzoff to values while creating .dat file or by adding them in plot command file.
printf -v plotcmd 'plot \47file.dat\47 using ($1%s):2' $tzoff
echo "$plotcmd"
plot 'file.dat' using ($1-25200):2
The snippet posted here did not work for me, but this seems to do the trick:
TZ=Europe/Amsterdam tzoff=$(printf "%(%z)T")
tzoff=${tzoff:0:1}$(( ( 10#${tzoff:1:2} * 3600 + 10#${tzoff:3:2}* 60 ) ))
echo $tzoff
Related
Well I'm trying to get the difference between two dates in Seconds.MilliSeconds The dates are in Zulu format
I have tried these two approaches doesn't work out for me
ms1=$(date -d '2022-04-22T03:47:56.744551446Z' +%N)
ms2=$(date -d '2022-04-22T03:47:57.095419744Z' +%N)
msdiff=$((ms1 - ms2))
echo "$msdiff"
$ dateutils.ddiff 2022-04-22T03:47:56.744551446Z 2022-04-22T03:47:57.095419744Z -f '%N'
0s
Is there any better way to get the difference in Seconds.MilliSeconds In linux for Z format time zones
Suggesting
ms1=$(date -d '2022-04-22T03:47:56.744551446Z' +%s.%N)
ms2=$(date -d '2022-04-22T03:47:57.095419744Z' +%s.%N)
msdiff=$(awk "BEGIN{print $ms2 - $ms1}")
echo "msdiff=$msdiff"
Output:
msdiff=0.350868
I need to subtract the below 2 times using a shell script
var1=2019-11-14-03.00.02.000000
var2=2019-11-14-03.00.50.000000
The output should be 00-00-00-00.00.48.00000
First convert var1 and var2 to date in seconds (since epoch) with:
sec1=$(date --date $var1 +%s)
...
Use bash math operators to calculate the difference
delta=$((sec1 - sec2))
Finally convert it back to a readable format
date --date #1502938801"$delta"
As mentioned in my comment, var1 and var2 are not valid date formats for passing to GNU date with the -d option. Before you can convert the times to seconds from epoch, you must
remove the '-' between the date and time portions of each variable,
isolate the time alone,
remove the milliseconds
replace all '.' in the time with ':'
restore the milliseconds separated from the time with '.'
pass the reformatted string for each to date -d"$dt $tm" +%s with the reformatted date and time space-separated.
Bash provides parameter substitutions to handle each very easily.
After computing the time since epoch for both and taking the difference, you then have to manually compute the difference in years, months, days, hours, minutes, seconds and milliseconds in order to output the difference and you must format the output using printf and the integer conversion specifier using both the appropriate field-width and leading-zero modifiers.
Putting it altogether, (and using a 365-day/year and 30-day/mo approximation) you could do:
#!/bin/bash
var1=2019-11-14-03.00.02.000000
var2=2019-11-14-03.00.50.000000
dt1=${var1%-*} ## isolate date portion of variables
dt2=${var2%-*}
tm1=${var1##*-} ## isolate time portion of variables
tm2=${var2##*-}
ms1=${tm1##*.} ## isolate milliseconds portion of variables
ms2=${tm2##*.}
tm1=${tm1%.*} ## remove milliseconds from time
tm2=${tm2%.*}
tm1=${tm1//./:} ## substitute all . with : in times w/o milliseconds
tm2=${tm2//./:}
tm1=${tm1}.$ms1 ## restore milliseconds
tm2=${tm2}.$ms2
epoch1=$(date -d"$dt1 $tm1" +%s) ## get time since epoch for both
epoch2=$(date -d"$dt2 $tm2" +%s)
epochdiff=$((epoch2-epoch1)) ## get difference in epoch times
## Approximates w/o month or leap year considerations
y=$((epochdiff/(3600*24*365))) ## years difference
rem=$((epochdiff-y)) ## remainder
m=$((rem/(3600*24*30))) ## months difference (based on 30 day mo)
rem=$((rem-m)) ## remainder
d=$((rem/(3600*24))) ## days difference
rem=$((rem-m)) ## remainder
H=$((rem/3600)) ## hours difference
rem=$((rem-H)) ## remainder
M=$((rem/60)) ## minutes difference
S=$((rem-M)) ## secnds difference
ms=$((ms2-ms1)) ## millisecond difference
## format output
printf "%04d-%02d-%02d-%02d:%02d:%02d.%04d\n" $y $m $d $H $M $S $ms
(note: you can further fine-tune the month and year/leap-year calculations -- that is left to you)
Example Use/Output
$ bash ~/scr/dtm/fulltimediff.sh
0000-00-00-00:00:48.0000
Look things over and let me know if you have further questions.
This question already has answers here:
Extract data from log file in specified range of time [duplicate]
(5 answers)
Closed 6 years ago.
I'd like to merge several log files within a given date range. For example, I have 5 days of log files in a directory:
server.log.2016-04-14-00
server.log.2016-04-14-01
. . .
server.log.2016-04-18-23
server.log.2016-04-19-00
server.log.2016-04-19-01
I know I can use cat to merge the files, but how can I code in a shell script so that only the files between, for example, 2016-04-17-22 and 2016-04-18-01 are selected?
The following script accepts server's log file as its first argument.
Two important variables are from_date and to_date which control the from-to range. They're hard-coded in the script, and you might want to change this to enhance script's usage flexibility.
#!/bin/bash
# Server's log file.
server_log_file=$1
# The date from which the relevant part of the log file should be printed.
from_date='2016/04/14 00:00'
# The date until which the relevant part of the log file should be printed.
to_date='2016/04/19 01:00'
# Uses 'date' to convert a date to seconds since epoch.
# Arguments: $1 - A date acceptable by the 'date' command. e.g. 2016/04/14 23:00
date_to_epoch_sec() {
local d=$1
printf '%s' "$(date --date="$d" '+%s')"
}
# Convert 'from' and 'to' dates to seconds since epoch.
from_date_sec=$(date_to_epoch_sec "$from_date")
to_date_sec=$(date_to_epoch_sec "$to_date" )
# Iterate over log file entries.
while IFS=. read -r s l date; do
# Read and parse the date part.
IFS=- read -r y m d h <<< "$date"
# Convert the date part to seconds since epoch.
date_sec=$(date_to_epoch_sec "$y/$m/$d $h:00")
# If current date is within range, print the enire line as it was originally read.
if (( date_sec > from_date_sec && date_sec < to_date_sec )); then
printf '%s.%s.%s\n' "$s" "$l" "$date"
fi
done < "$server_log_file"
In order to test it I created the following file, named logfile:
server.log.2016-04-14-00
server.log.2016-04-14-01
server.log.2016-04-18-23
server.log.2016-04-19-00
server.log.2016-04-19-01
Usage example ( script name is sof ):
$ # Should print logs from 2016/04/14 00:00 to 2016/04/19 01:00
$ ./sof logfile
server.log.2016-04-14-01
server.log.2016-04-18-23
server.log.2016-04-19-00
From a shell prompt, what's the fewest-keystrokes way to calculate the mm:ss value of expressions such as
4:33 + 0:20 - 2:45 = 2:08 ?
This is for interactive use, not for use in a script, or measuring elapsed time, or anything fancy like that. No mouse. No GUI.
There are thousands of implementations of mm+60*ss and (mmss/60, mmss%60), in hundreds of languages. I could write a script in bash or ruby or C for this, to add yet another implementation. But it seems likely that this wheel doesn't need reinventing, when it's likely buried somewhere in bc, dc, irb, or maybe even in bash itself.
Although not perfect:
s="4:33 + 0:20 - 2:45"
n=$(sed 's/\([0-9]*\):\([0-9]*\)/(\1 * 60 + \2)/g' <<< "$s" | bc)
printf "%d:%02d\n" $(( $n / 60 )) $(( $n % 60 ))
The sed command outputs (4 * 60 + 33) + (0 * 60 + 20) - (2 * 60 + 45) to bc.
The output is: 2:08.
It is impossible in some few characters on prompt to calculate the time like this.
You can do for example something like:
date -d "4:33 + 2:22" +%H:%M
but you need to include time zone (and how time is being calculated), take the output, calculate again and! do not exceed 24hs. So this is ridiculous.
One of the possible solutions can be GNU/Units. It provides shorthand names for some common combinations:
hms -> hours, minutes, seconds
time -> years, days, hours, minutes and seconds
You have: 2 hours + 23 minutes + 32 seconds
You want: seconds
* 8612
/ 0.00011611705
Homepage: http://www.gnu.org/software/units/
In a Linux script: I have a file that has two time entries for each message within the file. A 'received time' and a 'source time'. there are hundreds of messages within the file.
I want to calculate the elapsed time between the two times.
2014-07-16T18:40:48Z (received time)
2014-07-16T18:38:27Z (source time)
The source time is 3 lines after the received time, not that it matters.
info on the input data:
The input has a lines are as follows:
TimeStamp: 2014-07-16T18:40:48Z
2 lines later: a bunch of messages in one line and within each line, multiple times is:
sourceTimeStamp="2014-07-16T18:38:27Z"
If you have GNU's date (not busybox's), you can give difference in seconds with:
#!/bin/bash
A=$(date -d '2014-07-16T18:40:48Z' '+%s')
B=$(date -d '2014-07-16T18:38:27Z' '+%s')
echo "$(( A - B )) seconds"
For busybox's date and ash (modern probably / BusyBox v1.21.0):
#!/bin/ash
A=$(busybox date -d '2014-07-16 18:40:48' '+%s')
B=$(busybox date -d '2014-07-16 18:38:27' '+%s')
echo "$(( A - B )) seconds"
you should be able to use date like this (e.g.)
date +%s --date="2014-07-16T18:40:48Z"
to convert both timestamps into a unix timestamp. Getting the time difference between them is then reduced to a simple subtraction.
Does this help?
I would use awk. The following script searches for the lines of interest, converts the time value into a UNIX timestamp and saves them in the start, end variables. At the end of the script the difference will get calculated and printed:
timediff.awk:
/received time/ {
"date -d "$1" +%s" | getline end
}
/source time/ {
"date -d "$1" +%s" | getline start
exit
}
END {
printf "%s seconds in between", end - start
}
Execute it like this:
awk -f timediff.awk log.file
Output:
141 seconds in between