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

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.

Related

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.

Shell script to find the first and last day of the previous month and pass those values as a variable

I have a (separate) curl command and I want to pass it two parameters, the first day of the last month and the last day of the last month. I plan to declare these in a shell script. Could anyone identify how I can get these values using bash? I am almost there, I just need help over the line...
First Part:
If I do this:
firstday=$(date -d "-1 month -$(( $(date +%e) - 1 )) days")
echo $firstday
Then I get:
Fri May 1 16:09:51 AEST 2020
Which is the first day of the last month. However I want this in this format:
2020-05-01
Second Part:
If I do this:
date -d "-$(date +%d) days"
That gives me:
Sun May 31 16:14:59 AEST 2020
However I need this in the format:
2020-05-31
Can someone please help me with how I can do this? I think these two commands will do what I want... it's probably just a format mask I need to get it right.
To control the format of the output date, just add it to each date command: +%Y-%m-%d.
firstday=$(date -d "-1 month -$(( $(date +%e) - 1 )) days" +%Y-%m-%d)
echo $firstday
will output: 2020-05-01
date -d "-$(date +%d) days" +%Y-%m-%d
will output: 2020-05-31

bash date invalid date (-d 'feb 29 -3years')

I was working with the date command today and discovered some behaviour I cannot explain (I skimmed through: ~$ info '(coreutils) date invocation' but didn't find anything) and hope that someone here might help me to understand why this is happening.
~$ date -u +%F -d "feb 28 -3years"
>> 2012-02-28
~$ date -u +%F -d "feb 29 2012"
>> 2012-02-29
~$ date -u +%F -d "feb 29 -3years"
>> date: invalid date ‘feb 29 -3years’
~$ date -u +%F -d 'feb 29 3 years ago'
>> date: invalid date ‘feb 29 3 years ago’
This is happening on all leap years/leap days (...2008/2012/2016...) and I just can't figure out why.
I' am running above commands on my Ubuntu Gnome Edition (15.04) and on my Server which runs Debian/Jessie.
It's kinda hacky but a good way of getting the last day of the month is to go to the first day of the next month, then back by one day:
$ date -u +%F -d "mar 1 -3years -1day"
2012-02-29
I don't claim to know how the date command is implemented but it stands to reason that feb 29 is the first part of the string that is interpreted, before making the subtractions. So the safest thing to do is to use a date that is always valid, then make a series of subtractions.

Get UTC time in seconds

It looks like I can't manage to get the bash UTC date in second. I'm in Sydney so + 10hours UTC time
date
Thu Jul 3 17:28:19 WST 2014
date -u
Thu Jul 3 07:28:20 UTC 2014
But when I tried to convert it, I'm getting the same result which is not UTC time
date +%s
1404372514
date -u +%s
1404372515
What am I missing here?
After getting an answer saying date +%s was returning UTC time, here are more details about the problem I'm facing now.
I'm trying to compare a date written in a file with python. This date is written in seconds in UTC time. And the bash date +%s doesn't give me the same one. Actually if I'm doing in python time.asctime(time.localtime(date_in_seconds_from_bash)), I get the current time of Sydney, not UTC. I don't understand.
I believe +%s is seconds since epoch. It's timezone invariant.
I bet this is what was intended as a result.
$ date -u --date=#1404372514
Thu Jul 3 07:28:34 UTC 2014
You say you're using:
time.asctime(time.localtime(date_in_seconds_from_bash))
where date_in_seconds_from_bash is presumably the output of date +%s.
The time.localtime function, as the name implies, gives you local time.
If you want UTC, use time.gmtime() rather than time.localtime().
As JamesNoonan33's answer says, the output of date +%s is timezone invariant, so date +%s is exactly equivalent to date -u +%s. It prints the number of seconds since the "epoch", which is 1970-01-01 00:00:00 UTC. The output you show in your question is entirely consistent with that:
date -u
Thu Jul 3 07:28:20 UTC 2014
date +%s
1404372514 # 14 seconds after "date -u" command
date -u +%s
1404372515 # 15 seconds after "date -u" command
One might consider adding this line to ~/.bash_profile (or similar) in order to can quickly get the current UTC both as current time and as seconds since the epoch.
alias utc='date -u && date -u +%s'
Based on the answer from the other #Adam, here is a one-liner with the UTC date-time and seconds since epoch start:
alias utc='printf "%s : %s\n" "$(date -u)" "$(date -u +%s)"'
The epoch start time is defined as the number of seconds since January 1, 1970 at 00:00 Greenwich Mean Time (GMT), a timezone now known as UTC±00:00 or simply UTC.

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