date command in a bash shell script - bash

At work all the days config files are generated fresh and appended with a
session number. The company went public on Feb 16, and the 86400 is seconds
in one day. The session number is generated by subtracting the company start
day from seconds_since_last_day and adding a few zero's
That is the key to interacting with the days config files. I get this - However I do not
understand the
date -ud "$distance days ago 00:00:00".
Is it the number of seconds since 1970?
if $session; then
# return the session of the last day
seconds_since_day_one=`date -ud "Feb 16 2002" +"%s"`
seconds_since_last_day=`date -ud "$distance days ago 00:00:00" +"%s"`
days_between=`printf "%010d" $(( (seconds_since_last_day - seconds_since_day_one) / 86400 ))`
# Truncate on the left to 9 bytes to leave room
# to append the engine suffix for your environment
echo $days_between | awk '{l=length($1); print substr( $1, (l-8), l )}'

date -ud "$distance days ago 00:00:00" in itself just prints the date a certain amount of days ago in a quite readable format, but when you add the FORMAT string to control the output +"%s" does indeed mean the number in so called Unix Time (number of seconds since 1970-01-01 00:00:00 UTC).
If the variable $distance is set to a number it shows the date that number of days ago, if its set to 0 it means today, 1 it means yesterday, 2 the day before yesterday and so on. To better understand these formats and relative keywords there are rather good documentations in (amongst other places) the GNU coreutils package.
Check these URLs:
http://www.gnu.org/software/coreutils/manual/html_node/Relative-items-in-date-strings.html#Relative-items-in-date-strings
http://www.gnu.org/software/coreutils/manual/html_node/Date-input-formats.html
http://www.gnu.org/software/coreutils/manual/html_node/date-invocation.html#date-invocation
Wikipedia explanation of Unix Time:
http://en.wikipedia.org/wiki/Unix_time

The option -d to date provides a generic string to obtain the date.
So, for example, date -d yesterday will print yesterday's date, and date -d 'yesterday 12:00 AM' will print yesterday's date with the time set to 12:00 AM.
So, date -d 6 days ago 00:00:00 will print the date from 6 days ago, with the time set to 00:00:00. I hope it answers your question.
The format +"%s" tells date to print the number of seconds from 1970, instead the date.

mktime and strftime in awk can be used to get the date of the time.
http://www.gnu.org/software/gawk/manual/html_node/Time-Functions.html
For instance, strftime("%A",mktime("YYYY MM DD 00 00 00"))
should give you the day.

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.

Determining how many days ago a timestamp refers to in bash

I'm trying to determine the age of AWS keys in days. I'm using Bash.
I get the creation date of the AWS key using this command:
user_key1_date=$(aws iam list-access-keys --user-name "$aws_user_name" --profile "$aws_key" --output text --query 'AccessKeyMetadata[*].[AccessKeyId,CreateDate]' | awk 'NR==1 { print $2 }')
And I get a result like this:
2018-01-04T20:59:01Z
I am then trying to get the age of the keys in days and assign it to a variable with this line:
key1Age=$(date -d "$user_key1_date" +%j)
I then try to report the age of the key with this line:
The AWS access key: $user_access_key1 for user name: $aws_user_name was created on $date1. This key is $key1Age days old and needs to be replaced.
But the age of the key that gets reported is innacurate:
Key AKIAIPSNLEFKBLH2CLOQ is 004 days old. Time to change your key!
What am I doing wrong?
%j gives you the number of days into a year on which a date takes place. January 4th of 2018 is thus 4, but so is January 4th of 1998; it's not useful when you need to do comparisons that can cross year boundaries.
Consider something more like:
now=$(date +%s) # slow but more reliable way
key1Date=2018-01-04T20:59:01Z
key1TimeSeconds=$(date -d "$key1Date" +%s)
key1AgeSeconds=$(( now - key1TimeSeconds ))
key1AgeDays=$(( key1AgeSeconds / (60 * 60 * 24) ))
echo "Key created on $key1Date. This key is $key1AgeDays days old and needs to be replaced."
...which, when run (as of today), emits:
Key created on 2018-01-04T20:59:01Z. This key is 188 days old and needs to be replaced.
If you're only using new versions of bash, printf -v now '%(%s)T' -1 is a more efficient alternative to now=$(date +%s).
The date command may not be giving the answer you want, but it is giving the correct answer to the question you asked. :) The %j gives Julian days, or the number of days from the beginning of the year. Jan 4 is the 4th day of the year.
There are probably several ways of doing what you want. I'll give you one way to get you in the right direction.
echo "($(date +%s) - $(date -d "2018-01-04T20:59:01Z" +%s)) / 3600 / 24"|bc
The %s converts a date into the the number of seconds from Jan 1, 1970. Here I took the number of seconds now and subtract the number of seconds from your key date. Dividing by 3600 gets me the number of hours and then by 24 gets me the number of days. bc converts the math expression to a value. I believe this will be truncated, but you might want to experiment with this.
The %j format in my date's man page refers to day of year (001..366), so for Jan 4th, 004 would make sense.
You need to do some math to get the difference and there are plenty of answers out there for that, e.g How to find the difference in days between two dates?

Yesterday's date variable in BASH on AIX Server

I want to store yesterday's date in BASH variable to search for yesterday's files with that variable in the file-name wildcard search. I am using the following format for New York City, NY, USA (EST) time zone, and wanted to know whether it is guaranteed to fetch yesterday's date from the system date; else I can make further changes to the variable.
yesterday=$(TZ=GMT+28 date +%Y%m%d)
...
for file in $HOME_DIR/*$yesterday*.txt;
...
The text filename in HOME_DIR would be as follows:
"ABC_20171011064612.txt"
update 1: Attempt for removing daylight savings related issues:
yesterday=$(echo -e "$(TZ=GMT+28 date +%Y%m%d)\n$(TZ=GMT+18 date +%Y%m%d)"|grep -v $(date +%Y%m%d)|sort|tail -1)
1) Convert two dates to string, 24 hours and 14 (picked arbitrarily to be less than 24 hours) hours before today's date
2) Filter for dates that are not today's date
3) Sort strings from 2) in ascending order
4) Assign yesterday variable to last tail -1 entry of the list
It may not be always right due to DST, although it will not be a big issue.
You could rather say:
yesterday=$(date -d yesterday +%Y%m%d)
You attempted
yesterday=$(echo -e "$(TZ=GMT+28 date +%Y%m%d)\n$(TZ=GMT+18 date +%Y%m%d)|
grep -v $(date +%Y%m%d)|sort|tail -1)
I think it worked.

Construct a new date by adding X number of hours (Unix Shell)

Given a UNIX date variable, I need to construct a new date adding a certain number of hours (must be variable) to the initial date. I've looked at this post, which explains how to do this with the current date. For example with 1 hour, date -d '+1 hour' '+%F %T' returns the time it will be in exactly one hour. However, I need to do this with a date variable, not with the current date.
I've tried messing around with the -d flag, but if I set the date to another date variable, I can't figure out how to change it again (such as adding another X number of hours).
Is there a good way to do this? Am I on the right track with the -d flag or is there a better way?
Thanks!
You can use:
# your date variable
dt=$(date -d '2016-08-15 11:10:15')
# add 1 hour to $dt now
date -d "$dt +1 hour"
Mon Aug 15 12:10:15 EDT 2016

Unix Shell scripting - calculating last week date based on given date

Need a help in unix shell script in calculating date.
I will be getting date value (eg: 20150908) as parameter, now inside the script i need to calculate 7 days ago date (20150908 -7).
something like below:
date=20150908
lastweek_date=20150908 - 7 ---> this should output as 20150901
Could someone help me on this.
Thanks
With GNU date, we can subtract one week:
$ date -d "20150908 - 1 week" '+%Y%m%d'
20150901
Alternatively, we could subtract 7 days:
$ date -d "20150908 - 7 days" '+%Y%m%d'
20150901
And, to show that this works over month boundaries:
$ date -d "20150901 - 1 week" '+%Y%m%d'
20150825
This solution is not OSX/BSD compatible.
A week is 604800 seconds long so to get the number of seconds since the epoch in a portable and POSIX compliant fashion and use it to compute the date 1 week ago do as follows:
PRESENT=$( date +%s )
WEEKAGO=$(( PRESENT - 604800 ))
printf "%s\n" "$WEEKAGO"

Resources