delorie.com/archives/browse.cgi   search  
Mail Archives: djgpp/2001/01/04/02:01:29

To: djgpp AT delorie DOT com
Subject: Re: strftime: Need Help with Time Offsets
References: <1a524t0tk28cmv3vqfq26tooe0qeikhgm5 AT 4ax DOT com> <Pine DOT SUN DOT 3 DOT 91 DOT 1001221110346 DOT 28580O-100000 AT is> <ku454tke181c70f6rimuamfd2pc9p0blfk AT 4ax DOT com> <2561-Fri22Dec2000120234+0200-eliz AT is DOT elta DOT co DOT il> <pki64tssb5jku2tjnqg3ch5oqr5ngevntk AT 4ax DOT com> <1190-Fri22Dec2000173248+0200-eliz AT is DOT elta DOT co DOT il> <0nt94tkh5ptfohe9414da1u3geja7ml4vm AT 4ax DOT com> <20001226124727 DOT A19514 AT kendall DOT sfbr DOT org> <419i4tsoc9dgtbp9okme2cghdn09uocgq4 AT 4ax DOT com>
From: Esa A E Peuha <peuha AT cc DOT helsinki DOT fi>
Date: 04 Jan 2001 09:01:01 +0200
In-Reply-To: Jason Green's message of "Tue, 26 Dec 2000 23:36:05 +0000"
Message-ID: <86pofxnajiq.fsf@sirppi.helsinki.fi>
Lines: 73
X-Mailer: Gnus v5.6.43/Emacs 19.34
Reply-To: djgpp AT delorie DOT com

Jason Green <news AT jgreen4 DOT fsnet DOT co DOT uk> writes:

> This is what needs to be figured out:
> 
> : In this system, weeks begin on a Monday and week 1 of the year is the   
> : week that includes January 4th, which is also the week that includes   
> : the first Thursday of the year, and is also the first week that   
> : contains at least four days in the year.  If the first Monday of   
> : January is the 2nd, 3rd, or 4th, the preceding days are part of the  
> : last week of the preceding year; thus, for Saturday 2nd January 1999,  
> : %G is replaced by 1998 and %V is replaced by 53.  If December 29th,  
> : 30th, or 31st is a Monday, it and any following days are part of week  
> : 1 of the following year.  Thus, for Tuesday 30th December 1997, %G is  
> : replaced by 1998 and %V is replaced by 1. 
> 
> The week number, %V as defined above, needs to be calculated from the
> date fields of a struct tm.

Here's (pseudo)code to compute the week number and the year that the
week belongs to (this assumes that the fields in struct tm are in valid
ranges):

  if(tm_mon == 11 &&
     ((tm_wday == 1 && tm_mday >= 29) ||
      (tm_wday == 2 && tm_mday >= 30) ||
      (tm_wday == 3 && tm_mday == 31)))
    {
      /* day belongs to first week of next year */
      year_offset = 1;
      week_number = 1;
    }
  else if(tm_mon == 0 &&
          ((tm_wday == 5 && tm_mday == 1) ||
           (tm_wday == 6 && tm_mday <= 2) ||
           (tm_wday == 0 && tm_mday <= 3)))
    {
      /* day belongs to last week of previous year */
      year_offset = -1;
      week_number = number_of_week(tm_wday,
                                   tm_yday + 365 + is_leap_year(tm_year));
    }
  else
    {
      /* the usual case */
      year_offset = 0;
      week_number = number_of_week(tm_wday, tm_yday);
    }

This uses two helper functions.  The leap year checking one is simple:

is_leap_year(year)
{
  return (year % 4 == 0) - (year % 100 == 0) + (year % 400 == 100);
}

The other is not (this could obviously be optimized, but this way it's
hopefully rather self-explanatory):

number_of_week(wday, yday)
{
  day_of_the_week_now = (wday + 6) % 7;
  day_of_the_week_jan1 = (day_of_the_week_now + 53 * 7 - yday) % 7;
  days_since_monday_of_first_week = yday + day_of_the_week_jan1
    - 7 * (day_of_the_week_jan1 >= 4);
  return days_since_monday_of_first_week / 7 + 1;
}

I hope this is of some use to you.

-- 
Esa Peuha
student of mathematics at the University of Helsinki
http://www.helsinki.fi/~peuha/

- Raw text -


  webmaster     delorie software   privacy  
  Copyright © 2019   by DJ Delorie     Updated Jul 2019