Adding Hours to Date & Time in Linux - 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)

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"

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.

How to set time to 2 days after the current time with shell script in Solaris?

I would like to modify the system time to two days after but I only find that I can set the time to a specific time with the date command in Solaris:
#date mmddhhmmYY
but cannot add two days on the current time. Is there an easy way to do this task with a shell command? If you know something similar in linux, please also share with me.
Solaris date supports a syntax that gradually adjusts the time. This may be your best bet.
date -a $(( 48 * 60 * 60 * 60 ))
should eventually update your date to two days ahead. That is really the best way to set the system time as it will gradually update instead of jumping ahead suddenly (which can screw up a bunch of running programs).
Barring that, you could write up a nice script that's aware of the days in a month, and leap years, and do the calculations yourself. If you're exceptionally lazy (like me) and precision and race conditions don't bug you that much (like me, answering StackOverflow questions), you could just do a hack like this:
#!/bin/sh
now=$(date +%H%M.%S) # current time
date 2359.59 # Set time to 11:59:59pm
sleep 1 # Wait a second so the day rolls over
date 2359.59 # Set time to 11:59:59pm
sleep 1 # Wait a second so the day rolls over
date "$now" # Set time back to what it was, but in the new day
date -a 2 # Gradually add two seconds back to the clock
Test run on a tnarik/solaris10-minimal Vagrant box:
# ./adddaystodate
The current date is now Monday, 25 January 2016 00:46:59 GMT
Monday, 25 January 2016 23:59:59 GMT
Tuesday, 26 January 2016 23:59:59 GMT
Wednesday, 27 January 2016 00:46:59 GMT
The current date is now Wednesday, 27 January 2016 00:46:59 GMT

Linux Script- Date Manipulations

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

Resources