views:

882

answers:

3

If I've got a time_t value from gettimeofday() or compatible in a Unix environment (e.g., Linux, BSD), is there a compact algorithm available that would be able to tell me the corresponding week number within the month?

Ideally the return value would work in similar to the way %W behaves in strftime() , except giving the week within the month rather than the week within the year.

I think Java has a W formatting token that does something more or less like what I'm asking.


[Everything below written after answers were posted by David Nehme, Branan, and Sparr.]

I realized that to return this result in a similar way to %W, we want to count the number of Mondays that have occurred in the month so far. If that number is zero, then 0 should be returned.

Thanks to David Nehme and Branan in particular for their solutions which started things on the right track. The bit of code returning [using Branan's variable names] ((ts->mday - 1) / 7) tells the number of complete weeks that have occurred before the current day.

However, if we're counting the number of Mondays that have occurred so far, then we want to count the number of integral weeks, including today, then consider if the fractional week left over also contains any Mondays.

To figure out whether the fractional week left after taking out the whole weeks contains a Monday, we need to consider ts->mday % 7 and compare it to the day of the week, ts->wday. This is easy to see if you write out the combinations, but if we insure the day is not Sunday (wday > 0), then anytime ts->wday <= (ts->mday % 7) we need to increment the count of Mondays by 1. This comes from considering the number of days since the start of the month, and whether, based on the current day of the week within the the first fractional week, the fractional week contains a Monday.

So I would rewrite Branan's return statement as follows:

return (ts->tm_mday / 7) + ((ts->tm_wday > 0) && (ts->tm_wday <= (ts->tm_mday % 7)));

+1  A: 

Assuming your first week is week 1:

int getWeekOfMonth()
{
  time_t my_time;
  struct tm *ts;

  my_time = time(NULL);
  ts = localtime(&my_time);

  return ((ts->tm_mday -1) / 7) + 1;
}

For 0-index, drop the +1 in the return statement.

Branan
+1  A: 

If you define the first week to be days 1-7 of the month, the second week days 8-14, ... then the following code will work.

int week_of_month( const time_t *my_time)
{
  struct tm *timeinfo;

  timeinfo =localtime(my_time);
  return 1 + (timeinfo->tm_mday-1) / 7;

}
David Nehme
A: 

Consider this pseudo-code, since I am writing it in mostly C syntax but pretending I can borrow functionality from other languages (string->int assignment, string->time conversion). Adapt or expand for your language of choice.

int week_num_in_month(time_t timestamp) {
  int first_weekday_of_month, day_of_month;
  day_of_month = strftime(timestamp,"%d");
  first_weekday_of_month = strftime(timefstr(strftime(timestamp,"%d/%m/01")),"%w");
  return (day_of_month + first_weekday_of_month - 1 ) / 7 + 1;
}

Obviously I am assuming that you want to handle weeks of the month the way the standard time functions handle weeks of the year, as opposed to just days 1-7, 8-13, etc.

Sparr