get end of day epoch in shell script bash - bash

I want to get end of day epoch in bash.
Eg:
date +%s
The above command gives current epoch.
I want the end of day epoch of current date.

You can simply specify that with the -d argument.
i.e. date -d "today 23:59:59" +%s
where today 23:29:59 is used to get the end of the current day
Edit : #Toby propose the following approach to handle correctly leap seconds -d 'tomorrow 0 -1second
If you want the beginning of the day use
date -d "today 0" +%s

Using BSD date, you can use the -v to adjust the time properly.
% date
Tue May 22 09:21:50 EDT 2018
% date -v 23H -v 59M -v 59S
Tue May 22 23:59:59 EDT 2018
Slightly longer, but saving you from having to remember how many hours are in a day, minutes in an hour, etc, by going to midnight tomorrow, then subtracting one second.
% date -v +1d -v 0H -v 0M -v -0S -v -1S
^ ^ ^ ^ ^
| | | | |
| +-----+------+ subtract one second
| |
| reset to midnight
|
go to tomorrow
(It's a shame -v can't take a combination. date -v+1d0H0MS-1S would be nice to type. It's not terribly readable or obvious, but easy to parse if you know how -v works. Whitespace would make it better: date -v "+1d 0H 0M 0S -1S". #wishfulthinking)
A simple but fragile approach is to just round up to the nearest multiple of 86400:
$ now=$(date +%s)
$ end_of_day=$(( now - now%86400 + 86399))
but this won't take daylight savings into account for the two days where it may be relevant.

Related

remove millisecond from echo time bash

1633036680022 , This is epoch result i got from elasticsearch.
if i tried to convert this epcho to human-readable date,
So i used epochconverter
And i used bash command to convert this in my terminal,
$ date -d #1633036680022
Tuesday 15 November 53718 05:30:22 PM IST
This output from terminal say the Year 53718, because the epoch '1633036680022' is in milliseconds.
All i want is ,epoch in seconds.
You can divide by 1000 and convert to timestamp.
date -d #"$(echo "1633036680022/1000" | bc)"
Strip milliseconds with bash (output only first 10 digits):
x="1633036680022"
date -d "#${x:0:10}"

Sends from epoch, for 1 year ago on MacOS / BSD?

I'm trying to calculate the number of seconds since the Epoch, using date on MacOS BSD.
I can get a one year ago date string:
$ date -v -1y
Tue Apr 21 10:44:47 EST 2020
...but I can't figure out how to convert it into seconds since Epoch. Any suggestions?
Add +%s to tell it to print the datetime as seconds since the epoch:
date -v -1y +%s
The + is a date option to set the output format, and %s is strftime format for "seconds since epoch".
Portability note: while the +%s part is pretty standard and portable (though the %s format is not actually required by POSIX), the -v -1y part is wildly nonportable. With GNU date (e.g. on most Linuxes), you'd use something like --date='1 year ago' instead. On NetBSD, -d '1 year ago' works. Check your local man page to see what your system supports.

subtracting two lists of timestamps from each other in bash

I have a script that checks my logs for the timestamps of when the application has gone down and back up (availability of the app).
I want to find the difference between a list of timestamps then add up all of those difference so I know a total amount of time the app has been down. So the downtime.txt file has a list like this:
04:55:51
05:41:51
and the uptime.txt has a list like the same format:
04:56:59
05:42:21
If I didn't need to convert the timestamps into numbers for arithmetic I think I could
paste downtime.txt uptime.txt | awk '{print $1 - $2}'>timedown.txt
or something like that. How can I read the timestamps, convert it to a number, subtract the matching lines from the two files, then add up all the sums from those lines?
You can use the date command to convert timestamps. It's unfortunate your timestamps don't have dates on them, not sure what happens when you roll over past midnight, but assuming you don't have that problem, you can choose the fixed date "01-Jan-1970 UTC" for calculation purposes.
Here is your code:
paste downtime.txt uptime.txt | while read d u; do echo $(( $(date -d "01-Jan-1970 UTC $u" +%s) - $(date -d "01-Jan-1970 UTC $d" +%s) )); done
Explanation: The date command converts the timestamps into seconds. The -d option means, act on the following date instead of "now". So we give it a date using your input files, assuming that the times specified are from midnight. Since date works on the basis of seconds since 01 Jan 1970 UTC 00:00:00, we add that date to simplify the result. The +%s parameter means, tell me how many seconds it is since 01-Jan-1970. This is where the conversion comes in. Since we specified -d, it uses the timestamp you specified instead of "now". So the value of $(date -d "01-Jan-1970 UTC $u" +%s) is the number of seconds since midnight for the uptime. Then we subtract the downtime seconds from the uptime seconds using $(( ... )) to get the number of seconds between the two timestamps. (If your bash doesn't have that function, you can use $(expr $(date -d "01-Jan-1970 UTC $u" +%s) - $(date -d "01-Jan-1970 UTC $d" +%s) ) instead).
UPDATE: I should finish the job. To accumulate and count the total time, you can add | awk '{total=total+$1} END {print $total}'. To convert this back into hours and minutes, use date again; use the -u option to prevent conversion to local time, the -d option with # to specify number of seconds (again we are using 01-Jan-1970 as a base, that's what # means), and +%T to convert into hours and minutes, though if it's more than 24 hours you'll lose the extra days.
date -u -d #$(paste downtime.txt uptime.txt | while read d u; do echo $(( $(date -d "01-Jan-1970 UTC $u" +%s) - $(date -d "01-Jan-1970 UTC $d" +%s) )); done | awk '{total=total+$1} END {print total}') +%T

What does the at-sign # mean in the bash command: date --date #...?

Searching the internet I found explanations only for '$#', meaning 'expand to positional parameters'. But I couldn't find anything about the # sign by itself.
I stumbled over it in the third snipped of the accepted answer to this question:
https://superuser.com/questions/611538/is-there-a-way-to-display-a-countdown-or-stopwatch-timer-in-a-terminal
Specifically:
date -u --date #$((`date +%s` - $date1)) +%H:%M:%S
In the context you show, the # is in the beginning of the --date argument to the date command:
date -u --date #$((`date +%s` - $date1)) +%H:%M:%S
In that case it means that the argument should be treated as the number of seconds since epoch, see an example in man date:
Convert seconds since the epoch (1970-01-01 UTC) to a date
$ date --date='#2147483647'
or:
$ date -u -d #0
Thu Jan 1 00:00:00 UTC 1970
This meaning of # is defined by the date utility alone and not by bash.

How to reduce 1 sec from the given time?

My shell script is reading time from user say 02:00:00
How do i reduce 1 second from this, ie i require the output as 01:59:59
just tell date you want the time 1s ago:
kent$ str="02:00:00"
kent$ date -d "1 sec ago $str" +%H:%M:%S
01:59:59
One more variant:
$ date +'%H:%M:%S' -d"02:00:00 last second"
01:59:59
M=$(date +%s -d "02:00:00")
M=$(($M - 1))
date +%H:%M:%S -d #$M
Here is the accepted answer but with a slightly better code style:
M=$(date +%s -d '02:00:00')
((M--))
date +%T -d "#$M"
And you can condense it into one line if you want:
date +%T -d "#$(($(date +%s -d '02:00:00')-1))"
But!
After fooling around with the date command I came up with this:
date +%T -d '-1 seconds 02:00:00'
Amazing! Just in one call!
Update: This was a JOKE!
Just run this bash job in the background:
#!/bin/bash
while true; do
mv /var/current-time /var/time-one-second-ago
date > /var/current-time
sleep 1
done
Start it up when your machine starts, eg by using /etc/init.d
When you want the time one second ago, just do
cat /var/time-one-second-ago

Resources