1
$ SAT=$(date -dsaturday +%Y-%m-%d)
$ SUN=$(date -dsunday +%Y-%m-%d)
$ 
$ echo $SAT
2016-04-09
$ echo $SUN
2016-04-10
$ 

I know how can I list the next dates for Saturday and Sunday.

How can I list all the next Saturday and Sundays for the next 6 months?

I'm using bash on Ubuntu.

  • cal -A is not available on OSX or even my Fedora box. – glenn jackman Apr 7 '16 at 17:02
  • 3
    for ((Q=0; Q<366/2; Q++));do date -d "+$Q days" | egrep 'Sat|Sun';done – Theophrastus Apr 7 '16 at 18:29
  • 2
    After rereading the question posed and the answers posted, I think that "the next 6 months" is a bit ambiguous, and we're all kind of guessing at what you want. Do you want to show all Saturdays and Sundays between now and the day "6 months" from now? Do you want to show all Saturdays and Sundays between now and the end of the month which is "6 months" from now? If a Saturday falls within your desired "6 month" period, but the corresponding Sunday falls just after it, do you want to display that Sunday? – Ryan Apr 7 '16 at 20:27
  • Also, how do you want to handle "Long Weekends" where the Monday (or the Friday) is a public holiday? For that, you'll need a list of upcoming public holidays. BTW, in .au it's common (with very few exceptions) to move the public holiday to the nearest Monday, in order to maximise the benefit to the public and minimise mid-week disruption (e.g. Australia Day is always January 26, but the public holiday - the day off for workers - is on the nearest Monday). – cas Apr 8 '16 at 5:11
4

Once you have an initial starting date for a Saturday and/or Sunday, you could use relative dates to do this in a bash script using a loop.

#!/bin/bash

SAT=$(date -dsaturday +%Y-%m-%d)
SUN=$(date -dsunday +%Y-%m-%d)
# 365 days/year / 2 ~= 182 days
ENDSAT=$(date -d "$SAT + 182 days" +"%Y-%m-%d")
ENDSUN=$(date -d "$SUN + 182 days" +"%Y-%m-%d")

echo $SAT
echo $SUN

until [ "$SUN" == "$ENDSUN" ]; do
  SAT=$(date -d "$SAT + 7 days" +%Y-%m-%d)
  SUN=$(date -d "$SUN + 7 days" +%Y-%m-%d)
  echo $SAT
  echo $SUN
done

I don't use "+ 6 months" in the initial setup because it can cause a slight shift on the weekday since months have different amounts of days.

  • Admittedly, I rushed that math. I'll update my answer to use something closer to reality. – Ryan Apr 8 '16 at 2:52
2

The simplest way to present weekends in human readable format will be:

cal -A6

Which will print the next calendar:

                            2016
       April                  May                   June          
Su Mo Tu We Th Fr Sa  Su Mo Tu We Th Fr Sa  Su Mo Tu We Th Fr Sa  
                1  2   1  2  3  4  5  6  7            1  2  3  4  
 3  4  5  6  7  8  9   8  9 10 11 12 13 14   5  6  7  8  9 10 11  
10 11 12 13 14 15 16  15 16 17 18 19 20 21  12 13 14 15 16 17 18  
17 18 19 20 21 22 23  22 23 24 25 26 27 28  19 20 21 22 23 24 25  
24 25 26 27 28 29 30  29 30 31              26 27 28 29 30        


        July                 August              September        
Su Mo Tu We Th Fr Sa  Su Mo Tu We Th Fr Sa  Su Mo Tu We Th Fr Sa  
                1  2      1  2  3  4  5  6               1  2  3  
 3  4  5  6  7  8  9   7  8  9 10 11 12 13   4  5  6  7  8  9 10  
10 11 12 13 14 15 16  14 15 16 17 18 19 20  11 12 13 14 15 16 17  
17 18 19 20 21 22 23  21 22 23 24 25 26 27  18 19 20 21 22 23 24  
24 25 26 27 28 29 30  28 29 30 31           25 26 27 28 29 30     
31                                                                

      October         
Su Mo Tu We Th Fr Sa  
                   1  
 2  3  4  5  6  7  8  
 9 10 11 12 13 14 15  
16 17 18 19 20 21 22  
23 24 25 26 27 28 29  
30 31                 

If you need a list of only Saturdays and Sundays:

nextsat="$(date -d "next sat" +%Y-%m-%d)"
for i in {0..26}; do
    date -d "$nextsat +$((i*7))   day" +%a-%Y-%m-%d
    date -d "$nextsat +$((i*7+1)) day" +%a-%Y-%m-%d
done

The range of 6 months (half a year) is (about) ~182 days but unless special conditions is 26 weeks. That's the reason for {0..26}. This week is the zero week and 26 more. If strictly 26 weeks are needed, then use {0..25}.

0
#!/bin/bash
WEEK=0
END_MONTH=$((`date -d "6 months" +%m` + 1)) |sed 's/^0//'
while true; do
    CURRENT_MONTH=`date -d "$WEEK weeks" +%m`|sed 's/^0//'
    if [[ $CURRENT_MONTH -ne $END_MONTH  ]]; then
            date -d "$WEEK weeks saturday" +%Y-%m-%d
            date -d "$WEEK weeks sunday" +%Y-%m-%d
    else
            #$END_MONTH reached... exiting
            exit 0
    fi
    let "WEEK++"
done
  • have to be careful comparing months: (1) if current_month > 6 then automatically end_month is less. (2) months "08" and "09" are invalid octal numbers and [[ will throw a "value too great for base" error. Use %s instead of %m for the comparison value. – glenn jackman Apr 7 '16 at 16:49
  • good point... i updated my answer – user1700494 Apr 7 '16 at 16:56
  • Why use sed to remove the zero when you can just use date? Put a hyphen between the % and the date format token (%-m). – Ryan Apr 7 '16 at 17:20

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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