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

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.

Related

Date arithmetic not working properly in macos bash

I am trying to subtract 5 minutes from date but its giving unexpected output.
$ date -j -f "%Y/%m/%d %H:%M:%s" -v "-5M" "2021/03/01 09:11:14"
Thu Jan 1 05:25:14 IST 1970
Please suggest the correction.
Converting my comment to answer so that solution is easy to find for future visitors.
This date command should work on BSD date:
date -j -f "%Y/%m/%d %H:%M:%S" -v "-5M" "2021/03/01 09:11:14"
Issue in your command was use of .%s instead of .%S for the second component.

How to pass hours and minutes to date command through -d option

I know how to format a date in bash using the date command
date -d 20160304 +%Y%m%d
for example. But now I want to pass a date and time and return the hours and minutes. I know the output format I need is +%H%M, but I don't know how to format the date string and it is not in the man pages.
For example if I try any of these:
date -d 201801010500 +%H%M
date -d 20180101_0500 +%H%M
date -d 2018-01-01_0500 +%H%M
date -d 2018:01:01-05:00 +%H%M
I get an "invalid date" error. When I search google I always find answer referring to the output format, not the input format...
GNU date accepts these format, among others I'm sure
$ date -d '2018-02-16 12:34'
Fri Feb 16 12:34:00 EST 2018
$ date -d '2018-02-16T12:34:56'
Fri Feb 16 12:34:56 EST 2018
$ date -d '2018-02-16T12:34:56Z'
Fri Feb 16 07:34:56 EST 2018
In general, can't go wrong with ISO8601 time formats
I'm in Canada/Eastern time zone
The date utility is pretty impressive in making sense of different arguments for the -d option.
Here is just one example:
$ date -d "20180101 05:00:00"
Mon Jan 1 05:00:00 +07 2018
Note +07 is the local timezone.

Add X days to a particular date in BASH

Totally new to BASH. Apologies in advance.
Problem
I'd like to add X days to a specific date.
Code
I figured out that date in BASH retrieves the current date.
I also figured out that I can add X days to the current date in the following way,
expiration_date=$ date -v +1d
which gives,
Tue Sep 26 20:28:13 CEST 2017
which is indeed the date of writing plus X=1 days.
Question
In stead of date in the command line above, I'd like to insert a particular date to which X days will be added, e.g. 20/09/2017.
Don't care about the format of the particular date.
In other words: How do I make the following work,
expiration_date=$ '20/09/2017' -v +1d
Tried this answer, but doesn't do what I want.
Edit: Did not know things are different for OSX.
You can do this way:
dt='2017-09-20'
date -d "$dt +1 day"
Thu Sep 21 00:00:00 EDT 2017
date -d "$dt +2 day"
Fri Sep 22 00:00:00 EDT 2017
It seems OP is using OSX. You can use date addition this way:
s='20/09/2017'
date -j -v +1d -f "%d/%m/%Y" "$s"
Thu Sep 21 14:49:51 EDT 2017
You can do something like this:
date -d "Sun Sep 6 02:00:00 IST 2012+10 days"

Invalid date format in bash

I'm having trouble with checking time since EPOCH. (and late subtract it from another one).
I get the date like this:
var=$(date)
echo $var
wto, 1 mar 2016, 16:00:14 CET
and later I'm trying to turn it into seconds since epoch:
date -d "$var" +"%s"
date: invalid date ‘wto, 1 mar 2016, 16:00:14 CET’
I'm giving this just as an example. Actually I will be reading the date from file, written in default locale format (I'm operating on couple different machines).
if you type date -h there is the reason why you got this error.
the -d option MUST be declared only with TIME and not with complete DATE format
-d,--date TIME Display TIME, not 'now'
so
date -d "23:59:59"
then:
Tue Mar 1 23:59:59 2016
if you need get only the seconds from a date you have to execute this:
date +"%S"
if you use the -d the output will be deplyed in msec

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.

Resources