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.

Given two numbers, month and year, how can I compute the first and the last day of that month ? My goal is to output these three lines:

  1. month / year (month in textual form but that is trivial)

  2. for each day of the month: name of the day of the week for the current day: Fri. & Sat. & Sun. [...]

  3. day number within the month: 1 & 2 & 3 [...] & 28 & .. ?

I'm looking for a solution using GNU date or BSD date (on OS X).

share|improve this question
    
What OS are you using? It might help others give you the right answer. –  Kevdog777 Jul 17 '12 at 10:35
add comment

3 Answers

up vote 2 down vote accepted

Some time ago I had similar issue. There is my solution:

 $ ./get_dates.sh 2012 07
The first day is 01.2012.07, Sunday
The last day is 31.2012.07, Tuesday
 $ cal
 July 2012
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

Script itself:

#!/bin/bash
# last day for month
lastday()  {
#                ja   fe   ma   ap   ma   jn   jl   ag   se   oc   no   de
  mlength=('xx' '31' '28' '31' '30' '31' '30' '31' '31' '30' '31' '30' '31')

  year=$1
  month=$2

  if [ $month -ne 2 ] ; then
    echo ${mlength[$month]}
    return 0
  fi

  leap=0
  ((!(year%100))) && { ((!(year%400))) && leap=1 ; } || { ((!(year%4))) && leap=1 ; }

  feblength=28
  ((leap)) && feblength=29
  echo $feblength
}

# date to Julian date
date2jd() {

  year=$1
  month=$2
  day=$3
  lday=$(lastday $year $month) || exit $?

  if ((day<1 || day> lday)) ; then
    echo day out of range
    exit 1
  fi

  echo $(( jd = day - 32075
                + 1461 * (year + 4800 - (14 - month)/12)/4
                        + 367 * (month - 2 + (14 - month)/12*12)/12
                    - 3 * ((year + 4900 - (14 - month)/12)/100)/4
                - 2400001 ))
}

jd2dow()
{
  days=('Sunday' 'Monday' 'Tuesday' 'Wednesday' 'Thursday' 'Friday' 'Saturday')

  jd=$1
  if ((jd<1 || jd>782028)) ; then
    echo julian day out of range
    return 1
  fi

  ((dow=(jd+3)%7))

  echo ${days[dow]}
}


echo -n "The first day is 01.$1.$2, "
jd2dow $(date2jd $1 $2 01)
echo -n "The last day is $(lastday $1 $2).$1.$2, "
jd2dow $(date2jd $1 $2 $(lastday $1 $2))

I didn't have GNU date on machines I need it, therefore I didn't solve it with date. May be there is more beautiful solution.

share|improve this answer
add comment

I'll be honest; from the way you're asking the question I get the sense you've been assigned some homework, so I'll leave a few steps out of the answer as an exercise for the reader:

You'll want to take a good look at the date manual page; especially the -d flag, which allows you to examine any given day. The first day of month M in year Y would be "M/01/Y"

Getting the last day of the month, your best bet is to add 1 to the number of the month you were given, then deduct one day in the date.

Hint: date can actually accept some extensive arithmetic; I can, for instance, say date -d "01/07/2012 + 1 month - 1 day" and it will give me the correct answer.

You can find out how to display the output you want in 2) and 3) by studying the "format" section of the date manpage.

Hints: Look at %a and %d

share|improve this answer
4  
Homework on a July 17th? I'm just asking my question in the least ambiguous way I could to make it SEO friendly. –  Antoine Lecaille Jul 17 '12 at 10:03
    
The +"format string" parameter to date will also be helpful here, e.g. date -d "01/07/2012 + 1 month - 1 day" +"%d" –  daniel kullmann Jul 17 '12 at 11:32
    
@Antoine: The world is a bigger place then you might have realized. There's lots of places that will have school on any given July day. –  Christian Sep 30 '13 at 14:11
add comment
date -d "20121101 + 1 month - 1 day" +%Y%m%d
share|improve this answer
3  
At least you should specify which of the question's 3 points are answered by your code. –  manatwork Nov 1 '12 at 9:06
add comment

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.