Reading date with hour and incrementing it in shell script - bash

I have a file with date '2015-06-01-12', how can I get it to increment the hour in shell script? The result I want is '2015-06-01-13'. If its the 23rd hour it has to move forward a date and get 00 as hour.
I was able to do it to date but have so far had not any luck with incrementing hours.
currDate=2015-06-02
nextDate=`date '+%Y-%m-%d' -d "$currDate+1 days"`
echo $nextDate

It is reasonably easy if you keep your date as an epoch (number of seconds since January 1, 1970):
$ currDate=$( date +%s -d "2015-06-02 23:00:00" )
$ echo $currDate
1433300400
$ date +%Y-%m-%d-%H -d #$currDate
2015-06-02-23
$ nextDate=$(( $currDate + 3600 )) #adding an hour's worth of seconds
$ date +%Y-%m-%d-%H -d #$nextDate
2015-06-03-00

Related

Round current time up and down

I'm trying to figure out how to get the current hour rounded down to start of the hour and the next hour in bash?
For example, if I run my script:
./printHour.sh
and let's say the current time at execution is 13:04:12 - it would print
current hour is: 13:00:00
next hour is: 14:00:00
Progress so far: (but this gives 1hour ago so it does not work) - any ideas?
lastHour=$(date -d '1 hour ago' "+%H:%M:%S")
echo "current hour is: "$lastHour
You can use this utility function:
hrdt() { date -d "${1?} hour ago" '+%H:00:00'; }
Testing:
> hrdt
bash: 1: parameter not set
> hrdt 0
08:00:00
> hrdt 1
07:00:00
> hrdt 2
06:00:00
> hrdt 3
05:00:00
Could you please try following, written and tested as per shown samples, my date is GNU date version.
cat script.bash
#!/bin/bash
currentHour=$(date "+%H:00:00")
nextHour=$(date -d '+1 hour' "+%H:00:00")
echo "current hour is: $currentHour"
echo "next hour is: $nextHour"
When I run above script I get as follows:
current hour is: 06:00:00
next hour is: 07:00:00
Seems like you don't need anything special so this should do it:
date -d '1 hour ago' "+%H:00:00"
Why bother when you want exactly the hour where both %M and %S are expected to be zero?
You don't need date in this case; as seen below, built-in printf can generate formatted date-time strings too. Here -1 represents current time, and EPOCHSECONDS is a dynamic variable that expands to the number of seconds since epoch.
$ printf 'current hour is: %(%H)T:00:00\n' -1
current hour is: 17:00:00
$
$ printf 'next hour is: %(%H)T:00:00\n' $((EPOCHSECONDS + 3600))
next hour is: 18:00:00
Using awk,
$ awk ' BEGIN { st=systime();
print "current hour=" strftime("%F %H:00:00",st);
print "next hour=" strftime("%F %H:00:00",st+(60*60)) } '
current hour=2020-12-26 23:00:00
next hour=2020-12-27 00:00:00
$

Subtracting 30 days from current date in awk Unix command

I want to modify this command to subtract 30 days from current date automatically
$ awk -v t=$(date +%Y-%m-%d) -F "'" '$1 < t' myname.dat
When I try
$ awk -v t=$(date "--date=$(date) -30days" +%Y-%m-%d) -F "'" '$1 < t' myname.dat
I get the following error; date: illegal option
I want to do this without having to convert the dates to epoch time in the file.
#edit: The following will work with GNU date only:
You can always subtract seconds.
date --date=#$(($(date +%s) - 30 * 24 * 3600)) +%Y-%m-%d
If you are interested in subtracting 30 days form "now", just:
date --date="-30days" +%Y-%m-%d
date date formatting is so broad, it's good to specify the exact date with for example -I option, from man date:
-I[FMT], --iso-8601[=FMT]
output date/time in ISO 8601 format. FMT='date' for date only
(the default), 'hours', 'minutes', 'seconds', or 'ns' for date
and time to the indicated precision. Example:
2006-08-14T02:34:56-06:00
The following:
date --date="$(date -I) -30days" +%Y-%m-%d
works on my system as expected.

Add 30 Mins Time to DateTime format YYYY-MM-DD hh:mm:ss in AIX 5.0

I'm running AIX with coreutils 5.0. I need to advance an arbitrary date (or time) as given conformative to ISO-8601 format YYYY-MM-DD hh:mm:ss.
For example:
Value of D1 is: 2017-07-08 19:20:01, and I need to add 30 minutes.
In a modern UNIX-system I could probably write something like
date -d "$D1 + 30 minutes" +'%H:%M'
but, alas, I need it to work on an old AIX.
Try
$ date -d "$(date -d "$D1") + 30 minutes" +'%H:%M'
This works in bash, but not in ksh.
The inner call to date will parse D1 to a date, and present it in date's "native" format.
$ date -d "$D1"
Sat Jul 8 19:20:01 CEST 2017
This output will be used with + 30 minutes to create the date that you want, with the outer call to date.
The inner call to date will be expanded so that
$ date -d "$(date -d "$D1") + 30 minutes" +'%H:%M'
will be equivalent to
$ date -d "Sat Jul 8 19:20:01 CEST 2017 + 30 minutes" +'%H:%M'
which will be
19:50
date -d #$(($(date -d "$D1" +%s) + 30 * 60)) +%H:%M
$(date -d "$D1" +%s) echoes the epoch
$((epoch + value)) calculates the wanted time
date -d#epoch +fmt formats it
If you are running AIX from 2003 you are in dire straits, my friend, but if you only need the time, not the full date, as your question implies, I think #RamanSailopal got us half way there.
echo $D1 | awk -F "[: ]" '{
m = $3+30;
h = ($2+int(m/60)) % 24;
printf("%02i:%02i\n", h, m%60)
}'
awk splits the input in different fields, with the splitter pattern given in the -F argument. The pattern denotes : or space .
The input will be split in
$1 = 2017-07-08
$2 = 19
$3 = 20
$4 = 01
Then the script calculates a fake minute value (that can be more than or equal to 60) and stores it in m. From that value it calculates the hour, modulo 24, and the actual minutes, m modulo 60.
This could fail if you hit a leap second, so if you need second precision at all times, you should use some other method.
Awk solution:
awk -F '[-: ]' '{
ram=(mktime($1" "$2" "$3" "$4" "$5" "$6)+(30*60));
print strftime("%Y-%m-%d %T",ram)
}' <<< "$D1"
Convert the date to a date string using awk's mktime function. Add 30 minutes (30*60) and then convert back to a date string with the required format using strftime.

Shell add day to date saved in parameter

Hoping someone can help me work out what on earth is happening here.
I've got a script which receives a date as a parameter in this format "2016-09-01 00:00:00" and should create another variable containing the date for one day in the future, code is below
currentDate=$1
currentDate=$(date +"%Y-%m-%d %H:%M:%S" -d "$currentDate")
nextDate=$(date +"%Y-%m-%d %H:%M:%S" -d "$currentDate + 1 day")
echo $currentDate
echo $nextDate
Sometimes this works perfectly fine for example
2016-09-01 00:00:00 - date given as parameter
2016-09-02 00:00:00 - output for next day
But sometimes it'll only add 23 hours depending on the date provided
2016-02-01 00:00:00 - date given as parameter
2016-02-01 23:00:00 - output for next day
if I change the nextDay variable to add three days as below
nextDate=$(date +"%Y-%m-%d %H:%M:%S" -d "$currentDate + 3 day")
it gives the output as below adding only 21 hours instead of 3 days
2016-02-01 00:00:00 - date given as parameter
2016-02-01 21:00:00 - output for next day
Could someone help me understand why this is happening, is it related to timezones?
The reason appears to be how difficult it is to do free-form date parsing:
A baseline date: (I'm in the America/Toronto time zone)
$ date -d "2016-11-06 01:00:00" "+%F %T%z"
2016-11-06 01:00:00-0400
Try adding a day
$ date -d "2016-11-06 01:00:00 + 1 day" "+%F %T%z"
2016-11-06 19:00:00-0500
Hmm, that's strange, looks like it's adding a day but then expressing it as midnight, then subtracting 5 hours.
Let's try adding a day to just the date part
$ date -d "2016-11-06 + 1 day 01:00:00" "+%F %T%z"
2016-11-07 01:00:00-0500
That looks better.
In your script try this:
read current_date current_time < <(date -d "$1" +"%F %T%z")
echo "$current_date $current_time"
next_day=$(date -d "$current_date + 1 day $current_time" +"%F %T%z")
echo "$next_day"
three_days=$(date -d "$current_date + 3 day $current_time" +"%F %T%z")
echo "$three_days"

Bash: subtracting 10 mins from a given time

In a bash script, if I have a number that represents a time, in the form hhmmss (or hmmss), what is the best way of subtracting 10 minutes?
ie, 90000 -> 85000
This is a bit tricky. Date can do general manipulations, i.e. you can do:
date --date '-10 min'
Specifying hour-min-seconds (using UTC because otherwise it seems to assume PM):
date --date '11:45:30 UTC -10 min'
To split your date string, the only way I can think of is substring expansion:
a=114530
date --date "${a:0:2}:${a:2:2}:${a:4:2} UTC -10 min"
And if you want to just get back hhmmss:
date +%H%M%S --date "${a:0:2}:${a:2:2}:${a:4:2} UTC -10 min"
why not just use epoch time and then take 600 off of it?
$ echo "`date +%s` - 600"| bc; date
1284050588
Thu Sep 9 11:53:08 CDT 2010
$ date -d '1970-01-01 UTC 1284050588 seconds' +"%Y-%m-%d %T %z"
2010-09-09 11:43:08 -0500
Since you have a 5 or 6 digit number, you have to pad it before doing string manipulation:
$ t=90100
$ while [ ${#t} -lt 6 ]; do t=0$t; done
$ echo $t
090100
$ date +%H%M%S --utc -d"today ${t:0:2}:${t:2:2}:${t:4:2} UTC - 10 minutes"
085100
Note both --utc and UTC are required to make sure the system's timezone doesn't affect the results.
For math within bash (i.e. $(( and ((), leading zeros will cause the number to be interpreted as octal. However, your data is more string-like (with a special format) than number-like, anyway. I've used a while loop above because it sounds like you're treating it as a number and thus might get 100 for 12:01 am.
My version of bash doesn't support -d or --date as used above. However, assuming a correctly 0-padded input, this does work
$ input_time=130503 # meaning "1:05:03 PM"
# next line calculates epoch seconds for today's date at stated time
$ epoch_seconds=$(date -jf '%H%M%S' $input_time '+%s')
# the 600 matches the OP's "subtract 10 minutes" spec. Note: Still relative to "today"
$ calculated_seconds=$(( epoch_seconds - 600 )) # bc would work here but $((...)) is builtin
# +%H%M%S formats the result same as input, but you can do what you like here
$ echo $(date -r $calculated_seconds '+%H%M%S')
# output is 125503: Note that the hour rolled back as expected.
For MacOS users you can do the following:
$(date -v -10M +"%H:%M:%S")
Date time without a specific format:
$(date -v -10M)
For non-macOS users:
Date time without a specific format:
date --date '-10 min'

Resources