Linux Script- Date Manipulations - linux

I will set one date variable(Say '08-JUN-2011') and I want to do some calculations based on that date namely,
1. Have to get the first day of the given day's month.
2. Previous date of the given date's month.
3. Last day of the given date's month.
All I know is manipulating using the current system date and time but don't know how to implement with user defined date. I need this to be achieved using Linux shell script.
Any help will be appreciated.
Thanks,
Karthik

Here's how to perform the manipulations using GNU date:
#!/bin/sh
USER_DATE=JUN-08-2011
# first day of the month
FIRST_DAY_OF_MONTH=$(date -d "$USER_DATE" +%b-01-%Y)
PREVIOUS_DAY=$(date -d "$USER_DATE -1 days" +%b-%d-%Y)
# last day of the month
FIRST_DAY_NEXT_MONTH=$(date -d "$USER_DATE +1 month" +%b-01-%Y)
LAST_DAY_OF_MONTH=$(date -d "$FIRST_DAY_NEXT_MONTH -1 day" +%b-%d-%Y)
echo "User date: $USER_DATE"
echo "1. First day of the month: $FIRST_DAY_OF_MONTH"
echo "2. Previous day: $PREVIOUS_DAY"
echo "3. Last day of the month: $LAST_DAY_OF_MONTH"
The output is:
User date: JUN-08-2011
1. First day of the month: Jun-01-2011
2. Previous day: Jun-07-2011
3. Last day of the month: Jun-30-2011

This is going to be convoluted in a shell script. You are better off using Date::Manip in perl, or something similar in another full-featured language. However, I can think of some ways to do this with the date command. First of all, you can use a --date parameter to set a starting point for date, like so:
$ date --date='08-JUN-2011'
Wed Jun 8 00:00:00 EDT 2011
You can get the previous date like this:
$ date --date='08-JUN-2011 -1 days'
Tue Jun 7 00:00:00 EDT 2011
For the last day of the month, I would just walking back from 31 until date does not fail. You can check $? for that
$ date --date='31-JUN-2011';echo $?
date: invalid date `31-JUN-2011'
1
$ date --date='30-JUN-2011';echo $?
Thu Jun 30 00:00:00 EDT 2011
0
For the first day of the month...that is usually 01 :)

As you're using Linux, hhopefully you have the GNU date utility available. It can handle almost any description of a relative date that you think of.
Here are some examples
date --date="last month" +%Y-%m-%d
date --date="yesterday" +%Y-%m-%d
date --date="last month" +%b
x=$(date --date "10 days ago" +%Y/%m/%d)
To learn more about it see GNU Date examples
Once you use it some, you can shortcut your information gathering with date --help, which shows all the basic options (but is sometimes is hard to interpret.)
I hope this helps.

$ date +%m/01/%Y
I came here looking for a way to get the first day of the current month.

Using dateutils' dround tool:
Current month:
$ dround today -1
2014-02-01
Previous month
$ dround today -31
2014-01-31
Last day of current month:
$ dround today +31
2014-02-28
Of course you can use a custom date instead of today, the idea is to round down or up to the desired day-of-the month, e.g. the next first-of-the-month given 2010-10-04:
$ dround 2010-10-04 +1d
2010-11-01

Related

Given YYYY-MM-DD, how to find start date of week & end date of week? [duplicate]

This question already has answers here:
Get Monday and Sunday etc.. for a week for any date as parameter in Unix
(2 answers)
Closed 2 years ago.
Is there a way to use the date function in linux to get the exact date of the start of the week & end of the week for a given YYYY-MM-DD?
For example, I could enter 2020-07-24 and it would return 2020-07-20 (Monday) & 2020-07-26 (Sunday) as start & end date for this particular week respectively.
This shell script should work on most Linux as mostly they use GNU date
It converts the input to epoch seconds and then goes back a day until Monday is
found
#!/bin/bash
# take the parameter from command line
d="$1"
# find the current time as seconds since 1st Jan 1970 (epoch time)
start=$(date -d "$d" '+%s')
consider="$start"
# day of the week for the time we are considering
dow=$(date -d "#$consider" '+%A')
# is the day of the week monday? if not, carry on
while [[ "$dow" != "Monday" ]]; do
# adjust the time to be a day further in the past, 24*60*60 seconds is 1 day
let "consider=$consider - 86400"
dow=$(date -d "#$consider" '+%A')
done
# output the found date
date -d "#$consider"

Adding Hours to Date & Time in Linux

I am trying to add 5 hours to a date & time in Linux (Ubuntu 18.04.03) using the 'date' command. I get different results if I specify a date vs if I don't.
Example 1: I want to add 5 hours to a specific date:
[12:45:25 ~]$ date -d "2019-12-08 12:16:45 +5 hours"
Sun Dec 8 03:16:45 EST 2019
But the result is 9 hours BEFORE the specified date and time. I was expecting to have a date of 12/8 and time of 17:16:45.
Example 2: I add 5 hours to the system date:
[12:45:37 ~]$ date -d "+5 hours"
Sun Dec 8 17:46:02 EST 2019
This result is correct and as I expected.
I want to use this in a bash script and can't determine what I am doing incorrectly that I get these different results.
Any help will be appreciated.
After playing around a bit it seems like specifying the timezone with no spaces achieves what you're looking for:
date -d "2019-12-08 11:16:45EST+5hours"
This command outputs Sun Dec 8 16:16:45 EST 2019
Hope this helps!
GNU date very strangely parses the date, which makes it unreliable. The most reliable thing is to convert to seconds since epoch.
Convert the date to seconds.
Add 5 hours of seconds.
Convert the data to your favourite format.
date -d "#$(( $(date -d "2019-12-08 12:16:45" %s) + (5 * 60 * 60) ))"
date -d "2019-12-08 12:16:45 +5 hours"
I guess the +5 get's parsed as the timezone. So if you are in a timezone +5 and want EST, then you need to substact 5 hours for the timezone and 4 hours for current EST time. The hours get's ignored.
Add EST to the date & time string will give the correct answer.
I found it worthwhile to get the timezone and offset like so:
dateInfo=$(date +"%Z %z")
dateTZ=${dateInfo:0:3}
dateOffset="+"${dateInfo:5:2}
Then use them in the conversion code:
DATE=$(date -d "$CDATE1 $dateTZ $dateOffset hours" +%Y%m%d)
(where CDATE1 was parsed from a file's creation date as date & time)

Linux date objects behaving differently when hour/minute/second are specified

Why does adding one day work differently with the variables $d and $dt below?
Linux version: CentOS 6.8
If there is some kind of hidden timezone conversion going on with $dt but not with $d? If so, how do I suppress it?
d="2019-04-01"
dt="2019-04-01 01:00:00"
date --date="$d +1 days" +'%Y-%m-%d'
Output: 2019-04-02
date --date="$dt +1 days" +'%Y-%m-%d %H:%M:%S'
Output: 2019-04-01 17:00:00
Just so this question is answered (I couldn't find a duplicate) it was pointed out in the comments that the +1 in +1 days was being interpreted as a UTC offset appended to the date.
The solution is to terminate the date string with a time zone specifier such as Z or UTC so it's recognized as a complete date.
See info '(coreutils) date invocation' for more details on date specifications.

How to extract the UTC offset of a specific date and time using bash?

To be specific I do not want date +%z or date -R for the current local time, but I need something very similar that should work for any date in the past. For example, something like:
command 2018-04-01 12:33:45
should return the UTC offset (assume Chicago as my local time zone) at 12:33:45 on 1st April 2018 local time, Chicago time for example.
I searched extensively and there, probably, is no question close to this one, everyone wants current offset not date-time specific one, therefore it is not a duplicate.
Thanks very much
Update:
I have found something here, that asnwers how to get past dates using date command, then I have combined it with -R to get something close to what I want:
date -d "35 days ago" -R
I can go 35 days back and get the UTC offset.
To convert a particular date time to UTC you can use below command
for example date you provided in your question
2018-04-01 12:33:45
It would be something like below
date -u --date=#$(date "+%s" --date="2018-04-01 12:33:45")
which would have output similar to Sun Apr 1 10:33:45 UTC 2018
If you would like to achieve command date here then you can either create a command alias for above command or use above command in your script providing the date value to convert as an argument
I am answering my own question based on
My own update just after submitting the question.
Nahuel Fouilleul's comment.
Quoting from my own "edit":
"I have found something here, that answers how to get past dates using date command, then I have combined it with -R to get something close to what I want:
date -d "35 days ago" -R
I can go 35 days back and get the UTC offset."
here comes Nahuel's comment, "what about date -d 2018-04-01T12:33:45 -R"
That is in line with what I wrote in my "edit". Nahuel's solution works perfectly for me.
also Usman Malik's answer perfectly provides the solution.
So to summarize, my (not entirely though) answer will be:
date -d specific_past_date -R
where the specific_past_date is the date on which I need the UTC offset, using the date and time that I mentioned in my question, if I do:
date -d 2018-04-01T12:33:45 -R
I get Sun, 01 Apr 2018 12:33:45 -0500 from Chicago, that means Chicago time was 5 hours behind UTC on 1st April 2018 at 12:33:45.

Get Monday and Sunday etc.. for a week for any date as parameter in Unix

How to get the date of Monday and Sunday in a week for a date?
This gives date for 'last' monday:
date -dlast-monday +%Y%m%d
I want to pass a date as parameter to find the Monday and Sunday for that week. Basically, I want to get Sunday and Monday for a week, for ANY date, NOT only for last monday.
Try this:
export day=2013-10-01
date -d "$day -$(date -d $day +%w) days"
This will always print the Sunday before the given date (or the date itself).
date -d "$day -$(date -d $day +%u) days"
This will always print the Sunday before the given date (and never the date itself).
For Mondays you need to add + 1 day:
date -d "$day -$(date -d $day +%u) days + 1 day"
You should also consider what Monday or Sunday you want to get (this wasn't quite clear) for which date. This also depends on whether you consider the Sunday the first or the last day of the week.
date can parse the date on the command line like so:
date -j -f %s 1380628152
which is the date+time in seconds since the UNIX epoch. You can combine the command abovewith your command. The -j means you don't want to actually set the date. The -f specifies a strftime string to use to parse the date on the command line.
Please note that this is on a BSD system and it looks like you are on a GNU system with different options to date (but it must support something similar).

Resources