Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Today's date, minus X days in shell script

Tags:

bash

sh

I need to create three variables, each for Year, Month, and Day for Today's date, minus X number of days. For this question I'll choose a random amount of days: 222.

So if:

TodayYear=`date +%Y` TodayMonth=`date +%m` TodayDay=`date +%d` 

What I want is 222 days before this.

222days_before_TodayYear=??? 222days_before_TodayMonth=??? 222days_before_TodayDay=??? 

Edit: Need 222 working days instead 222 regular days.

like image 292
majordomo Avatar asked Nov 23 '12 17:11

majordomo


People also ask

How do I subtract a day from a date in bash?

Set it to the number of days that you want to subtract. Very slight improvement to the command - date --date="${dataset_date} -${date_diff} day" +%Y-%m-%d.

How do I subtract one day from a date in Unix?

The easiest way is to convert the date to a unix time_t value (i.e. seconds since the beginning of the epoch, or '1-1-1970 00:00:00'), and then substract 30 days * 86400 seconds per day from that number. e.g. the following example uses set -x so that you can see the value of the D variable as it changes.

What does X mean in shell script?

The "x" has no special meaning and could be replaced with any non-null string.

What does $() mean in shell script?

$() – the command substitution. ${} – the parameter substitution/variable expansion.


2 Answers

For GNU date:

date_222days_before_TodayYear=$(date --date="222 days ago" +"%Y") date_222days_before_TodayMonth=$(date --date="222 days ago" +"%m") date_222days_before_TodayDay=$(date --date="222 days ago" +"%d") 

For BSD date::

If you are using OS X or FreeBSD, use the following instead because BSD date is different from GNU date:

date_222days_before_TodayYear=$(date -j -v-222d +"%Y") date_222days_before_TodayMonth=$(date -j -v-222d +"%m") date_222days_before_TodayDay=$(date -j -v-222d +"%d") 

Source: BSD date manual page

Note:

In bash and many other languages, you cannot start a variable name with a numerical character, so I prefixed them with date_ for you.


Second Update: New requirement - Using 222 Working days instead of 222 Regular days:

(Assumption: Not considering statutory holidays, because that just gets far beyond the scope of what I can help you with in a shell script:)

Consider 222 working days:

  • 5 working days per week, that is floor(222/5) == 44 weeks
  • 44 weeks * 7 days per week == 308 days
  • Extra days leftover: 222 % 5 == 2
  • Therefore 222 working days == 310 regular days

But, there is a catch! If the number of regular days is 308 or some multiple of 7, then we would have been fine, because any multiple of 7-days ago from a working day is still a working day. So we need to consider whether today is a Monday or a Tuesday:

  • If today is a Monday, we'd get Saturday where we wanted Thursday
  • If today is a Tuesday, we'd get Sunday where we wanted Friday

So you see we need an additional offset of 2 more days if today is either Monday or Tuesday; so let's find that out first before we proceed:

#!/bin/bash  # Use 310 days as offset instead of 222 offset=310 # Find locale's abbreviated weekday name (e.g., Sun) today=$(date -j +"%a") # Check for Mon/Tue if [[ "$today" == "Mon" ]] || [[ "$today" == "Tue" ]]; then      offset=$((offset+2)) fi  date_222_working_days_before_TodayYear=$(date -j -v-${offset}d +"%Y") date_222_working_days_before_TodayMonth=$(date -j -v-${offset}d +"%m") date_222_working_days_before_TodayDay=$(date -j -v-${offset}d +"%d") 

And that should do it =)

like image 73
sampson-chen Avatar answered Sep 22 '22 15:09

sampson-chen


date '+%Y' --date='222 days ago' 
like image 28
chrisaycock Avatar answered Sep 20 '22 15:09

chrisaycock