LinuxQuestions.org
Did you know LQ has a Linux Hardware Compatibility List?
Go Back   LinuxQuestions.org > Forums > Non-*NIX Forums > Programming
User Name
Password
Programming This forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.

Notices

Reply
 
Search this Thread
Old 03-29-2012, 03:09 PM   #1
ezekieldas
Member
 
Registered: Mar 2010
Posts: 122

Rep: Reputation: 16
any lang: week number


I don't do much programming and I've never tried working out a calendar problem. I'm trying to
do this in python and if I had the background, then maybe I could find the answer using datetime() or something. Anyhow, here's my issue...

I'd like to get a week number. That is, starting with Sunday, ending with Saturday. Looking at UNIX cal I see today, 3/29 would be week 5. I purloined this code from stack overflow and it generally works fine. However when I ran this through a number of tests I found some issues with some weeks where the 21st and 22nd are in the 4th week. March 2011 is an example.

Here's what I'm using. Any suggestions are appreciated.

Code:
print "which date?",
number = int(raw_input())
week_number = (number - 1) // 7 + 1

print "The date you gave was %r, and the calculation is %r." % (number, week_number)
 
Old 03-29-2012, 04:45 PM   #2
evo2
Guru
 
Registered: Jan 2009
Location: Japan
Distribution: Debian, SL
Posts: 5,318

Rep: Reputation: 1141Reputation: 1141Reputation: 1141Reputation: 1141Reputation: 1141Reputation: 1141Reputation: 1141Reputation: 1141Reputation: 1141
Hi,

in a shell the current week can be obtained with:
Code:
date +%W
Or if you want it for a specfic date, Eg 5th October2011:
Code:
date +%W --date 2011-10-05
In python
Code:
import datetime
datetime.datetime(2011,10,5).strftime('%W')
Cheers,

Evo2.

Last edited by evo2; 03-29-2012 at 04:52 PM. Reason: Add python
 
Old 03-29-2012, 04:53 PM   #3
ezekieldas
Member
 
Registered: Mar 2010
Posts: 122

Original Poster
Rep: Reputation: 16
Thanks evo2. I should have been more clear. What I'm after is a week number 1-5. The first week being 1, starting on Sundays. I can see this with UNIX cal but to get a proper calculation has been difficult.
 
Old 03-29-2012, 05:23 PM   #4
Dark_Helmet
Senior Member
 
Registered: Jan 2003
Posts: 2,786

Rep: Reputation: 369Reputation: 369Reputation: 369Reputation: 369
You still need a little more clarity

Quote:
What I'm after is a week number 1-5. The first week being 1, starting on Sundays.
By limiting your range to 1-5, I'm inferring that you want a week number within a given month. My assumption is that your "which date?" prompt really asks "which day of the current month?"

When I execute cal on my machine, I get:
Code:
     March 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
So, if the "first week being 1, starting on Sundays," what week contains March 1, 2, and 3?

Perhaps you would be interested in isocalendar(). From Python 2.7.2 documentation:
Code:
date.isocalendar()

    Return a 3-tuple, (ISO year, ISO week number, ISO weekday).

    The ISO calendar is a widely used variant of the Gregorian calendar. See http://www.phys.uu.n
    /~vgent/calendar/isocalendar.htm for a good explanation.

    The ISO year consists of 52 or 53 full weeks, and where a week starts on a Monday and ends on a
    Sunday. The first week of an ISO year is the first (Gregorian) calendar week of a year containing
    a Thursday. This is called week number 1, and the ISO year of that Thursday is the same as its
    Gregorian year.

    For example, 2004 begins on a Thursday, so the first week of ISO year 2004 begins on Monday, 29
    Dec 2003 and ends on Sunday, 4 Jan 2004, so that date(2003, 12, 29).isocalendar() == (2004, 1,
    1) and date(2004, 1, 4).isocalendar() == (2004, 1, 7).
You would, of course, have to massage the results because the ISO definition for a week starts on a Monday rather than a Sunday.
 
Old 03-29-2012, 05:23 PM   #5
evo2
Guru
 
Registered: Jan 2009
Location: Japan
Distribution: Debian, SL
Posts: 5,318

Rep: Reputation: 1141Reputation: 1141Reputation: 1141Reputation: 1141Reputation: 1141Reputation: 1141Reputation: 1141Reputation: 1141Reputation: 1141
Hi,

"week number" normally means the week of the year 0-53 (man 1 date). Perhaps what you want
is the week of the month?

Could post the invocation, output and version of cal that provides this information.

Cheers,

Evo2.
 
Old 03-29-2012, 05:54 PM   #6
Nominal Animal
Senior Member
 
Registered: Dec 2010
Location: Finland
Distribution: Xubuntu, CentOS, LFS
Posts: 1,723
Blog Entries: 3

Rep: Reputation: 942Reputation: 942Reputation: 942Reputation: 942Reputation: 942Reputation: 942Reputation: 942Reputation: 942
Like evo2 and Dark_Helmet above stated, the problem is that we do not have any definition for your "week number".

For example, consider February 2012. The first and last days of February 2012 fell on Wednesdays.

Which dates are the first week of February 2012?

There are many, all equally valid, answers:
  • 2012-01-29 to 2012-02-04 (Sun to Sat, the week that contains the first of February)
  • 2012-01-29 to 2012-02-04 (Sun to Sat, the week that contains more than half its days in February)
  • 2012-01-05 to 2012-02-11 (Sun to Sat, the first full week in February)
  • 2012-01-30 to 2012-02-05 (Mon to Sun, the week that contains the first of February)
  • 2012-01-30 to 2012-02-05 (Mon to Sun, the week that contains more than half its days in February)
  • 2012-01-06 to 2012-02-12 (Mon to Sun, the first full week in February)
Which one the asker is looking for?

Asking for week number 1-5 is like asking for the NominalAnimalNumber of February 2012. Nobody can answer it correctly before you define exactly what it is.

I'm trying hard to not be a dickweed here. If you want the calendar definitions used in your region, just say so; they're very well defined -- but there are large differences between various regions in the world. See ISO week date and Seven-day week articles at Wikipedia, to see how complex (or simple, depending on how familiar you are with human cultural differences) issue week numbering really is.
 
Old 03-29-2012, 06:03 PM   #7
Dark_Helmet
Senior Member
 
Registered: Jan 2003
Posts: 2,786

Rep: Reputation: 369Reputation: 369Reputation: 369Reputation: 369
I'm just throwing this out there as an example of how I might use the isocalendar() function I referenced. Perhaps it will spur you in the right direction.

This is from an interpreter session:
Code:
Python 2.6.5 (r265:79063, Apr 16 2010, 13:57:41) 
[GCC 4.4.3] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import datetime
>>> monthStart = datetime.date(2012, 3, 1)
>>> currentDay = datetime.date(2012, 3, 29)
>>> monthStart.isocalendar()
(2012, 9, 4)
>>> currentDay.isocalendar()
(2012, 13, 4)
>>> weekNum = currentDay.isocalendar()[1] - monthStart.isocalendar()[1]
>>> weekNum
4
So, basically, the code above calculates the ISO week number for the first day of the month, calculates the ISO week number for the current day, subtracts the two, and the result is (roughly) a 0-based week number within the current month.

And of course, you can always substitute the user-supplied value from your prompt for the literal '29' I used in the above.

But again, that's using the Monday-based ISO calendar format.
 
Old 03-29-2012, 06:06 PM   #8
Tinkster
Moderator
 
Registered: Apr 2002
Location: in a fallen world
Distribution: slackware by choice, others too :} ... android.
Posts: 22,978
Blog Entries: 11

Rep: Reputation: 879Reputation: 879Reputation: 879Reputation: 879Reputation: 879Reputation: 879Reputation: 879
All the theory aside; assuming he uses a linux distro which' locale has the definitions
he desires, these should do the job:
Code:
$ cal
     March 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
$ date "+%w"
5
$ perl -e 'use POSIX; my $date=strftime("%w",localtime); print $date;' 
5
 
Old 03-29-2012, 06:14 PM   #9
Nominal Animal
Senior Member
 
Registered: Dec 2010
Location: Finland
Distribution: Xubuntu, CentOS, LFS
Posts: 1,723
Blog Entries: 3

Rep: Reputation: 942Reputation: 942Reputation: 942Reputation: 942Reputation: 942Reputation: 942Reputation: 942Reputation: 942
Quote:
Originally Posted by Tinkster View Post
All the theory aside; assuming he uses a linux distro which' locale has the definitions
he desires, these should do the job
No!

First, for a Finnish calendar (with LC_ALL=fi_FI.UTF-8 LANG=fi_FI.UTF-8) I need to run ncal -bM to get the standard calendar,
Code:
   Maaliskuu 2012     
ma ti ke to pe la su  
          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
It does not get all the data (like which day starts the week) from the locale, apparently. Therefore, for date manipulations, I do need to use different fields depening on whether I consider the first day of week to be Sunday or Monday, when using e.g. strftime().

Second, '%w' yields the day of week number, 0 = Sun, 1 = Mon, ..., 6 = Sat, not a week number.

Last edited by Nominal Animal; 03-29-2012 at 06:16 PM.
 
Old 03-29-2012, 06:18 PM   #10
Tinkster
Moderator
 
Registered: Apr 2002
Location: in a fallen world
Distribution: slackware by choice, others too :} ... android.
Posts: 22,978
Blog Entries: 11

Rep: Reputation: 879Reputation: 879Reputation: 879Reputation: 879Reputation: 879Reputation: 879Reputation: 879
Aight. It's settled. I need a holiday
 
Old 03-29-2012, 06:20 PM   #11
ezekieldas
Member
 
Registered: Mar 2010
Posts: 122

Original Poster
Rep: Reputation: 16
Thanks for the comments. Sorry for the lack of clarity. I've never worked with this type of problem before. There's a couple of posts on Stack Overflow that discuss this (I'm appending URL below).

I think what Dark_Helmet points out above, using isocalendar(), might do the trick. I'm going to play with this and come back to this post. Visually, this is what I have in mind:

Code:
     March 2012
Su Mo Tu We Th Fr Sa
             1  2  3  = week 1
 4  5  6  7  8  9 10  = week 2
11 12 13 14 15 16 17  = week 3
18 19 20 21 22 23 24  = week 4
25 26 27 28 29 30 31  = week 5
The larger problem involves trying to find 2nd or 4th Monday or Tuesday of each month. For further illustration this is to notify car owners of street cleaning days in Oakland, California :-)

The week_number I posted earlier comes from these posts.

http://stackoverflow.com/questions/7...eek-in-a-month
http://stackoverflow.com/questions/3...r-of-the-month
 
Old 03-29-2012, 07:19 PM   #12
Nominal Animal
Senior Member
 
Registered: Dec 2010
Location: Finland
Distribution: Xubuntu, CentOS, LFS
Posts: 1,723
Blog Entries: 3

Rep: Reputation: 942Reputation: 942Reputation: 942Reputation: 942Reputation: 942Reputation: 942Reputation: 942Reputation: 942
Quote:
Originally Posted by ezekieldas View Post
The larger problem involves trying to find 2nd or 4th Monday or Tuesday of each month. For further illustration this is to notify car owners of street cleaning days in Oakland, California :-)
But.. but.. that has nothing to do with week numbers, or even which day starts a week!

Use the datetime Python module for this. Consider something like the following:
Code:
import datetime

# Remember: Monday = 0, Tuesday = 1, .., Sunday = 6.

# Return the date of weeknum'th weekday of year-month.
def day(year, month, weeknum, weekday):

    # Start at the first of that month.
    theday = datetime.date(year, month, 1)

    # Adjust to the first 'weekday' weekday of that month.
    if theday.weekday() < weekday:
        theday += datetime.timedelta(weekday - theday.weekday())
    elif theday.weekday() > weekday:
        theday += datetime.timedelta(7 + weekday - theday.weekday())

    # Adjust weeknum-1 weeks forward.
    return theday + datetime.timedelta(7 * (weeknum - 1))
Using the above, the second(2) Friday(4) of May(5) 2012 is
Code:
print day(2012, 5, 2, 4)
i.e. 2012-05-11, AKA Fri 11 May 2012.

Does this not solve your larger problem rather simply?
 
Old 03-30-2012, 02:39 AM   #13
ezekieldas
Member
 
Registered: Mar 2010
Posts: 122

Original Poster
Rep: Reputation: 16
Quote:
Originally Posted by Nominal Animal View Post
But.. but.. that has nothing to do with week numbers, or even which day starts a week!
Does this not solve your larger problem rather simply?
It might if I understood it better. I am in a bit over my head with this one. That is, I don't understand the issue very well + I don't know the language that well. If you could break down that example a bit further I might be able to use it.

Prior to reading these additional posts I found I was reasoning with the issue incorrectly. That is, this isn't a *horizontal* calendar issue (like I posted earlier) but rather a *vertical* one. To find the 2nd and 4th Mon and Tue from March 2011:

Code:
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 we took all the Mondays we'd have (7,14,21,28). Note: I'm reading down, vertically on that calendar from Mo. So with perl (I think), 2nd/4th Mondays could be extracted with @Mondays[1,3] (that's the 2nd and 4th element of the array) and we get 14th and 28th. Tuesdays is (1,8,15,22,29) So we take @Tuesdays[1,3] and get the 8th and 22nd. But I'm unsure how to do this with python, which is the language used to develop this prior to finding the trouble involved with this 'week_number = (number - 1) // 7 + 1'

FWIW, here is the old code:

Code:
import time, datetime

today = datetime.date.today()

day_of_week = datetime.datetime.isoweekday(today)
day_of_month = datetime.datetime.now().day
week_number = (day_of_month - 1) // 7 + 1

print "day of week is:", day_of_week
print "week number is:", week_number
print "day of month is:", day_of_month

if (( day_of_week == 7 ) or ( day_of_week == 1 )) and (( week_number == 2 ) or ( week_number == 4 )): 
 print "do it."
else:
 print "do not do it."
 
Old 03-30-2012, 03:50 PM   #14
Nominal Animal
Senior Member
 
Registered: Dec 2010
Location: Finland
Distribution: Xubuntu, CentOS, LFS
Posts: 1,723
Blog Entries: 3

Rep: Reputation: 942Reputation: 942Reputation: 942Reputation: 942Reputation: 942Reputation: 942Reputation: 942Reputation: 942
Quote:
Originally Posted by ezekieldas View Post
It might if I understood it better. I am in a bit over my head with this one. That is, I don't understand the issue very well + I don't know the language that well. If you could break down that example a bit further I might be able to use it.
Okay.

First, the function assumes you specify the desired date as year, month, weeknum (from 1 to 5, for first to fifth, respectively), and weekday (0 for Monday, 1 for Tuesday, and so on, up to 6 for Sunday).

It will then return the datetime.date object that matches that date.

First, we create a datetime.date object that matches the first day of the desired month:
Code:
    theday = datetime.date(year, month, 1)
Next, we check which weekday started the month, and adjust the datetime.date object forward to the (first) weekday that matches the weekday parameter. If the desired weekday is later on in the same week, we can just add the days in between:
Code:
    if theday.weekday() < weekday:
        theday += datetime.timedelta(weekday - theday.weekday())
otherwise we'll have to skip to next week (to be able to count backwards):
Code:
    elif theday.weekday() > weekday:
        theday += datetime.timedelta(7 + weekday - theday.weekday())
The effect of the above is the same if you wrote a loop that advances the object day by day until its weekday matches,
Code:
    while (theday.weekday() != weekday):
              theday += datetime.timedelta(1)
except that doing the addition directly is obviously much cleaner and faster.

At this point, theday is the first desired weekday weekday of the desired month and year. All we need to is adjust theday forwards by weeknum-1 weeks -- as the desired date asked is the weeknum'th weekday:
Code:
    return theday + datetime.timedelta(7 * (weeknum - 1))
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

Your example code indicates you actually use the inverse; that is, you want to know whether this is the first, second, third, fourth, or fifth occurrence of this weekday this month.

This is even simpler, and depends only on the day of month, and is, as you posted, 1 + ((day - 1) // 7) :
Code:
import datetime

# Return 1 to 5, depending on whether the date is the first, second,
# third, fourth, or fifth same weekday of that month.
#
def nth(theday):
    return 1 + ((theday.day - 1) // 7)


# Fixed names for the example below.
# Remember that lists in Python start at index 0.

monthname = [ '',
              'January', 'February', 'March', 'April',
              'May', 'June', 'July', 'August',
              'September', 'October', 'November', 'December' ]
dayname = [ 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday', 'Sunday' ]
nthname = [ '', 'first', 'second', 'third', 'fourth', 'fifth' ]

# Example:

theday = datetime.date.today()

print 'Today is the %s %s of %s, %d.' % ( nthname[nth(theday)], dayname[theday.weekday()], monthname[theday.month], theday.year )
Honestly, if it was more complex than that, do you really expect humans would use the concept at all?
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

Why does 1 + ((day - 1) // 7) then work?

In Python, // is integer division operator. It means the result will be an integer, with all the decimals removed. The key point here is to understand this operation, i.e. that
Code:
      0 // 7 == 0       10 // 7 == 1       20 // 7 == 2
      1 // 7 == 0       11 // 7 == 1       21 // 7 == 3
      2 // 7 == 0       12 // 7 == 1       22 // 7 == 3
      3 // 7 == 0       13 // 7 == 1       23 // 7 == 3
      4 // 7 == 0       14 // 7 == 2       24 // 7 == 3
      5 // 7 == 0       15 // 7 == 2       25 // 7 == 3
      6 // 7 == 0       16 // 7 == 2       26 // 7 == 3
      7 // 7 == 1       17 // 7 == 2       27 // 7 == 3
      8 // 7 == 1       18 // 7 == 2       28 // 7 == 4
      9 // 7 == 1       19 // 7 == 2       29 // 7 == 4
                                           30 // 7 == 4
The answer is simple. The first seven days, 1 to 7, of each month are the first weekdays of that month. They have to be! It does not matter which day of week starts the week, or which weekday the first day of the month might be.

The next seven days, 8 to 14, are the second occurrences of their respective weekdays. The next seven days, 15 to 21, are the third occurrences. The next, 22 to 28, the fourth. Obviously the 29 to 31 are the fifth occurrences.

Now, if you read the two paragraphs above, and look at the integer division table above, the answer should be obvious. Substract one from the day-of-month, integer divide by seven, and add one, and you have your desired result, 1 to 5.

Or, you could even use a fixed list (remembering that Python starts list indices from zero):
Code:
dayname = [ 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday', 'Sunday' ]

nthname = [ 'none',
            'first',  'first',  'first',  'first',  'first',  'first',  'first',
            'second', 'second', 'second', 'second', 'second', 'second', 'second',
            'third',  'third',  'third',  'third',  'third',  'third',  'third',
            'fourth', 'fourth', 'fourth', 'fourth', 'fourth', 'fourth', 'fourth',
            'fifth',  'fifth',  'fifth' ]

import datetime

theday = datetime.date.today()

print 'This is the %s %s of this month.' % (nthname[theday.day], dayname[theday.weekday()])
Hope this helps,
 
1 members found this post helpful.
  


Reply


Thread Tools Search this Thread
Search this Thread:

Advanced Search

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
[SOLVED] find to get the number of directories modified within last week ted_chou12 Linux - Software 6 11-24-2011 12:44 AM
[SOLVED] java.lang.UnsupportedClassVersionError: Bad version number in .class file msbstar Linux - Newbie 5 01-27-2011 03:11 PM
Exception in thread "main" java.lang.NoClassDefFoundError: org/aspectj/lang/Signature canonas Linux - Software 3 06-16-2008 04:00 AM
Calculating the week number for american calendars traene Programming 3 04-23-2005 05:35 AM


All times are GMT -5. The time now is 05:03 PM.

Main Menu
My LQ
Write for LQ
LinuxQuestions.org is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
Syndicate
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
identi.ca: @linuxquestions
Facebook: linuxquestions Google+: linuxquestions
Open Source Consulting | Domain Registration