Computing.Net > Forums > Unix > weeknumber out of given date

Computer Problems? Computing.Net has over 1,000,000 posts about all things technology related! Over 90% answered within 24 hours! Click here to start participating now! Also, be sure to check out the New User Guide.

weeknumber out of given date

Reply to Message Icon

Name: rawijnen
Date: November 23, 2004 at 02:39:57 Pacific
OS: AIX
CPU/Ram: ?
Comment:

I want to calculate a weeknumber out of a given date.

This is easy for the systemdate (date +%V), but how do I do this for a given date?



Sponsored Link
Ads by Google

Response Number 1
Name: Don Arnett
Date: November 23, 2004 at 09:05:22 Pacific
Reply:

1) turn the date into the 'day of year' (ie Jan 1 is 1, Jan 31 is 31, Feb 1 is 32, etc)

2) divide 'day of year' by 7 using integer division, then if there is a remainder, add 1

To turn the date into 'day of year', I usually make an array that holds the 'day of year' for the first of each month (non-leap year). For example

int arr = {1,32,60,91....}

Then you figure out what month it is, and look up the value in the array for the month. This gives you the 'day of year' for the first of the month (ie April 1 is 91). Then add the day of month. So April 15 is (91 + 15 - 1).

(you could adjust each array entry down by one (-1) so that you didn't have to subtract one each time)

Then you have to adjust for leap year if necessary.

Be sure to come back and let us know if our suggestions helped!


0

Response Number 2
Name: Wolfbone
Date: November 23, 2004 at 09:16:57 Pacific
Reply:

Doesn't this work with your version of 'date'?:

date -d '12/25/1984' '+%V'


0

Response Number 3
Name: Don Arnett
Date: November 23, 2004 at 09:32:38 Pacific
Reply:


That would be an easier way!!


0

Response Number 4
Name: Jim Boothe
Date: November 23, 2004 at 13:42:20 Pacific
Reply:

The problem with dividing the nth day of the year by 7 is that that works only when the first week of the year is a whole week (Jan 1 = Sunday).  And yes, it would certainly be nice if we all had GNU date.  I don't on HP-UX.  So here is one clumsy solution for determining week # for non-GNU date.

I build a file of calendar months, then process the file with awk, which will count the weeks (lines) through the week containing the target day. Partial weeks that begin or end a month are counted as half weeks since together those will count as 1, except for the very first week of the year, which is always counted as 1.  If I end up on a half count, bump up to the whole.

MO=$1
DAY=$2
YEAR=$3

calfile=calfile$$
rm $calfile 2> /dev/null

mo=1
while [ $mo -le $MO ]
  do
  cal $mo $YEAR >> $calfile
  ((mo=mo+1))
  done

awk -v MO=$MO -v DAY=$DAY '
{if (match(substr($1,1,1),"[A-Z]"))
    {getline # bypass hdrs
     mo++
     next}
 if (NF==7 || mo==1 && $1==1 )
     weeks=weeks+1
  else
     if (NF>0)
        weeks=weeks+.5
 if (mo==MO && $NF>=DAY)
    exit
}
END {
 weeks=int(weeks+.5)
 print "Week number = " weeks
}' $calfile

rm $calfile

./weekcalc.sh 11 23 2004
Week number = 48

date +%V
48


0

Response Number 5
Name: thepubba
Date: November 23, 2004 at 17:42:40 Pacific
Reply:

Any reason why this wouldn't work?

#!/bin/ksh

function figureWeek

{
today=$(date +%j)
(( theWeek = ((( today - $# ) / 7) + 1 ) ))
print "This is week $theWeek"

}

year=$(date +%Y)
counter=0
cal 01 $year | while read line
do
if [[ $counter = 2 ]]
then
figureWeek $line
break
else
(( counter += 1 ))
fi
done


0

Related Posts

See More



Response Number 6
Name: rawijnen
Date: November 24, 2004 at 03:28:03 Pacific
Reply:

Thank you all for your suggestions and solutions.

I had hoped there was a general solution like the GNU-date command. Unfortunately I do not have the GNU-date function available so "date -d '12/25/1984' '+%V'" doesn't work in my environment.

The solution of Don has the problem that januari 1 should be a Sunday.

Jerry's solution gives an American weeknumber and I need (I forgot to tell you) an ISO-weeknumber.

It looks as if Jim's solution works, but the solution is a little bit long.

To solve the problem I've decided to take a sidestep to Oracle.

WEEK=`printf "$(echo "set echo off feedback off heading off pagesize 0\n select to_char(to_date('${DATUM}','yyyymmdd'),'iw') from dual;" | SQLPLUS -s / )"`

solves the problem for me.



0

Response Number 7
Name: Jim Boothe
Date: November 24, 2004 at 08:23:41 Pacific
Reply:

I like Jerry's approach of calling cal only once to see how the year starts. I condensed the code a bit and adjusted the formula.  And since the requirement is to compute week# from any given date, I added logic to convert a given date to jday (as Don suggests).

I suspect it is a bit more code than Ron wants, but he could use it when his database is shut for backup. ;-)

mm=$1
dd=$2
yyyy=$3

((yyyy%100)) && ((leap=!(yyyy%4))) || ((leap=!(yyyy%400)))

if [ $leap -eq 0 ] ; then
   set -A dim 0 0 31 59 90 120 151 181 212 243 273 304 334 365
else
   set -A dim 0 0 31 60 91 121 152 182 213 244 274 305 335 366
fi

((jday=dim[$mm]+dd))

cal 01 $yyyy |
  awk '{getline;getline;print NF;exit}' |
  read firstweek
((Week=(jday+13-$firstweek)/7))
print "$mm/$dd/$yyyy: jday=$jday week=$Week"

weekcalc.sh 01 03 2004
01/03/2004: jday=3 week=1

weekcalc.sh 01 04 2004
01/04/2004: jday=4 week=2

weekcalc.sh 11 24 2004
11/24/2004: jday=329 week=48


0

Response Number 8
Name: rawijnen
Date: November 25, 2004 at 05:51:52 Pacific
Reply:

Jim thank you for your extra solution.

It has a problem however.

In ISO format week 1 off 2004 starts 12/29/03
Your solution give week 53 off 2003.

1/2/05 must give week 53 off 2004
1/3/05 is week 1 of 2005

I've tried to change your program, I did not find a good resolution (probably because I'm only a novice Unix programmer :-)). To solve the problem you have to find out which day is januari 1st. If it is Thursday or later than week 1 start in december of the previous year. If it is Monday to Wednesday, week 1 starts in the new year and the previous year has a week 53.

So I think with an "if .. then .. else .. fi" in the right place(s) it should be easy but I didn't find the right solution.

Don't spend to much time on this, because I have the Oracle solution implemented already. But if you think it's easy (and you can do it in a couple of minutes) I am curious about the solution.

I won't reply until monday because my weekend starts in 10 minutes.


0

Response Number 9
Name: Jim Boothe
Date: November 29, 2004 at 07:31:05 Pacific
Reply:

Ron, thanks for explaining the rules for ISO week. I don't like to leave things undone, so some time this week I will find some time to adjust the code - and I will use Oracle to confirm results.


0

Response Number 10
Name: Jim Boothe
Date: December 1, 2004 at 15:53:16 Pacific
Reply:

Calculation of ISO week turns out to be somewhat involved, but still I managed to calculate it with just a single call to cal to establish how January (for the year of the requested date) starts off.

ISO weeks begin on Mondays, and week #1 of each year is the first week having a majority of its days (4+) in the current year.  This is also the week that contains Jan 4.  The first week of a year can begin as early as Dec 29 of the previous year.  Also, as many as 3 days of January can be in the last week of the previous year, which could be either week 52 or 53.

# !/bin/ksh

calcweek() {
if [ $LEAP -eq 0 ] ; then
   set -A DIM 0 0 31 59 90 120 151 181 212 243 273 304 334
else
   set -A DIM 0 0 31 60 91 121 152 182 213 244 274 305 335
fi
((JDAY=DIM[$MM]+DD))
((WEEK=(JDAY+$1)/7))
echo $YEAR-$WEEK
}

MM=$1
DD=$2
YEAR=$3

MMDD=$MM$DD
typeset -Z2 WEEK

((YEAR%100)) && ((LEAP=!(YEAR%4))) || ((LEAP=!(YEAR%400)))

cal 01 $YEAR |
  awk '{getline;getline;print NF;exit}' |
  read W1K

case $W1K$LEAP in
  70)  echo '0101 52 9999 5' ;;
  10)  echo '0102 XX 9999 4' ;;
  20)  echo '0103 53 9999 3' ;;
  30)  echo '0000 00 9999 9' ;;
  40)  echo '0000 00 1229 8' ;;
  50)  echo '0000 00 1230 7' ;;
  60)  echo '0000 00 1231 6' ;;
  71)  echo '0101 52 1231 5' ;;
  11)  echo '0102 52 9999 4' ;;
  21)  echo '0103 53 9999 3' ;;
  31)  echo '0000 00 9999 9' ;;
  41)  echo '0000 00 9999 8' ;;
  51)  echo '0000 00 1229 7' ;;
  61)  echo '0000 00 1230 6' ;;
esac | read JCUT PWK DCUT ADJ

if [ $MMDD -le $JCUT ] ; then
   if [ $PWK = 'XX' ] ; then
      ((PYEAR=YEAR-1))
      ((PYEAR%100)) && ((PLEAP=!(PYEAR%4))) || ((PLEAP=!
(PYEAR%400)))
      ((PWK=52+PLEAP))
   fi
   echo $((YEAR=YEAR-1))-$PWK
else
   if [ $MMDD -ge $DCUT ] ; then
      echo $((YEAR=YEAR+1))-01
   else
      calcweek $ADJ
   fi
fi

exit 0

isoweek.sh 12 01 2004
2004-49


0

Response Number 11
Name: rawijnen
Date: December 2, 2004 at 04:46:59 Pacific
Reply:

Jim, thank you for taking the time to write this solution.
As far as I've able to test it, it works.

I'll keep this solution in mind for future use.



0

Response Number 12
Name: Jim Boothe
Date: December 2, 2004 at 06:16:56 Pacific
Reply:

Thanks for the feedback. Quite often, I write code more for the challenge and practice rather than the practicality of it. perl may even have an ISO week function.

But now I certainly know what ISO week is.


0

Sponsored Link
Ads by Google
Reply to Message Icon






Post Locked

This post is quite old and has been locked from receiving new replies. Please create a new posting instead.


Go to Unix Forum Home


Sponsored links

Ads by Google


Results for: weeknumber out of given date

week number of a date from FY www.computing.net/answers/unix/week-number-of-a-date-from-fy/7012.html

Out of clists www.computing.net/answers/unix/out-of-clists/2939.html

problem getting out of electronic mail www.computing.net/answers/unix/problem-getting-out-of-electronic-mail/1881.html