Take the 2-minute tour ×
Unix & Linux Stack Exchange is a question and answer site for users of Linux, FreeBSD and other Un*x-like operating systems.. It's 100% free, no registration required.

I need to run a certain program passing it the week boundaries. (I use CentOS release 6.4, so a bash/gnu date solution is fine). I tried this yesterday (on Monday):

for ((w=1;w<=6;w++)) do 
  week=$(date --date "$w weeks ago" +"%G-%V")
  beg=$(date --date "monday $w weeks ago" +"%F")
  end=$(date --date "sunday $w weeks ago" +"%F")
  echo "$week beg=$beg end=$end" $(( ($(date --date $end +"%s") - $(date --date $beg +"%s")) / 86400 ) + 1) "days"
done
2014-02 beg=2014-01-06 end=2014-01-12 7 days
2014-01 beg=2013-12-30 end=2014-01-05 7 days
2013-52 beg=2013-12-23 end=2013-12-29 7 days
2013-51 beg=2013-12-16 end=2013-12-22 7 days
2013-50 beg=2013-12-09 end=2013-12-15 7 days
2013-49 beg=2013-12-02 end=2013-12-08 7 days

looks good, but when I do the same thing today (Tuesday), I get this:

2014-02 beg=2014-01-13 end=2014-01-12 0 days
2014-01 beg=2014-01-06 end=2014-01-05 0 days
2013-52 beg=2013-12-30 end=2013-12-29 0 days
2013-51 beg=2013-12-23 end=2013-12-22 0 days
2013-50 beg=2013-12-16 end=2013-12-15 0 days
2013-49 beg=2013-12-09 end=2013-12-08 0 days

which does not look good.

So, how do call date to get the week boundaries in the past?

share|improve this question

2 Answers 2

up vote 1 down vote accepted

The problem is that depending on the current day, "Sunday x weeks ago" might be before "Monday x weeks ago":

  • If today is Monday, then "Sunday x weeks ago" = "Monday x weeks ago" + 6
  • If today is not Monday, then "Sunday x weeks ago" = "Monday x weeks ago" - 1

Instead of taking "Sunday x weeks ago" and "Monday x weeks ago", it will be easier to take "Sunday x weeks ago" and "Sunday x weeks ago - 6 days".

With some other error fixes and simplifications, here's your updated script:

#!/bin/bash
for ((w=1;w<=6;w++)); do 
    end=$(date --date "sun $w weeks ago" +%F)
    beg=$(date --date "sun $w weeks ago - 6 days" +%F)
    week=$(date --date "$beg" +%G-%V)
    echo "$week beg=$beg end=$end" $((($(date --date $end +%s) - $(date --date $beg +%s)) / 86400 + 1 )) "days"
done

Notice that I changed the setting of week too, to be based on beg.

However, you still need to keep in mind which Sunday you want to pick on a Sunday: today or the week before? This script will pick the Sunday the week before, never today. If that's not what you want, then you might want to rethink the calculations based on Monday instead of Sunday: take "Monday x weeks ago" and "Monday x weeks ago + 6 days":

for ((w=1;w<=6;w++)); do 
    beg=$(date --date "mon $w weeks ago" +%F)
    end=$(date --date "mon $w weeks ago + 6 days" +%F)
    week=$(date --date "$w weeks ago" +%G-%V)
    echo "$week beg=$beg end=$end" $((($(date --date $end +%s) - $(date --date $beg +%s)) / 86400 + 1 )) "days"
done
share|improve this answer
1  
You'll have the same problem if you run it on a Sunday though. –  terdon Jan 14 at 23:09
    
@terdon I hinted at that, but didn't explain how to handle it. I rewrote my answer that makes this more clear, with other improvements. Thanks for pointing out! –  janos Jan 15 at 5:40
1  
+1 for "pick the Sunday the week before, never today" -- thanks! –  sds Jan 15 at 17:55

You could use date +%u to find the Monday and the Sunday relative to a given date.

Assuming "0 weeks ago" is this week.

for ((w=1;w<=6;w++)); do 
    when=$(date --date "$w weeks ago")
    beg_offset=$(( $(date --date "$when" +%u) - 1))
    beg=$(date --date "$when - $beg_offset days" +"%F")
    end_offset=$((6 - beg_offset))
    end=$(date --date "$when + $end_offset days" +"%F")
    week=$(date --date "$when" +"%G-%V")
    days=$(( ( $(date --date "$end" +"%s") - $(date --date "$beg" +"%s") ) / 86400 + 1))
    echo "$week beg=$beg end=$end $days days"
done
share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.