ISO 8601 - Week Numbers from TDate

PAG_Promax
PAG_Promax used Ask the Experts™
on
Hi folks,

I was wondering if someone can help me out.  I'm trying to get an ISO 8601 week number from a TDate.  I've had a play with a few suggestions I've found, but none of them seem to reliably return a correct value.

Also, I'd like to know if there's a way to define the 8601 criteria (ie, first monday, week with 4 Jan, first four day week etc) to return the week.

I have looked at the code attached, but I don't necessarily agree with the result it is returning.  For instance, why is Jan 1 - 3 returning Week 0?  I would have thought it would be week 53 from the year before (although I might be wrong with this assumption).

int DateTimeToISOWeekNumber(TDateTime inputDate)
{
  const int EpochDiff = 25569; // days between 30/12/1899 and 01/01/1970
  const int SecsInDay = 86400; // number of seconds in day
  typedef struct tm* tmPtr;

  short     weekNumber = 0;
  char      tempStr[3];
  tmPtr     timePtr = NULL;

  time_t calendarTime((long)((((double)inputDate) - EpochDiff) * SecsInDay));
  timePtr = localtime( &calendarTime );

  strftime( tempStr, sizeof(tempStr), "%W", timePtr );

  weekNumber = atoi(tempStr);

  return weekNumber;
}

Open in new window


This code was taken from another EE question and slightly modified.

Any suggestions or hints would be fantastic.

Cheers!

Stuart




 
Comment
Watch Question

Do more with

Expert Office
EXPERT OFFICE® is a registered trademark of EXPERTS EXCHANGE®

Commented:
The first calendar week of the year according ISO 8601 is the one that includes the first Thursday of the year (the first week that includes four or more days in the year).

You can use Delphi standard functions WeekOf and WeekOfTheYear from unit DateUtils. Delphi help says, that both functions use ISO 8601 standard...

Commented:
You can also write your own WeekOfYear function and compare results with Delphi standard functions:

function MyOwnWeekOfYear(dt: TDateTime) : Byte;
var
  d : Integer;
  Day, Month, Year : Word;
  FirstDate : Integer;
begin
  d:=Trunc(dt);

  d:= d + 3 - ((5 + DayOfWeek(d)) mod 7);
  DecodeDate(d, Year, Month, Day);
  FirstDate := Trunc(EncodeDate(Year, 1, 1));

  result := 1 + (d - FirstDate) div 7;
end;
Commented:
There is also a Jedi / JCL function ISOWeekNumber in unit JCLDateTime:

ISOWeekNumber(DateTime:TDateTime):integer

ISO 8601 weeks start with Monday and the first week of a year is the one which includes the first Thursday

Have a look at sourcecode in unit JCLDateTime to see how to do date/time calcs...
Learn Ruby Fundamentals

This course will introduce you to Ruby, as well as teach you about classes, methods, variables, data structures, loops, enumerable methods, and finishing touches.

Author

Commented:
Hi Thommy,

Thanks for the quick response.  One of my work colleagues just informed me that we have some existing functionality in another part of our application which I can make use of.

Cheers!

Stuart.

Author

Commented:
Thanks for your assistance.  I'll award the points to you as you've provided some code and put in some effort, and that deserves reward.

Thank you!

Commented:
Thank you very much for the points!!!

A good information source for ISO 8601 standard is:

http://en.wikipedia.org/wiki/ISO_8601

Search for the paragraph "Week Dates":

...
If 1 January is on a Monday, Tuesday, Wednesday or Thursday, it is in week 01. If 1 January is on a Friday, Saturday or Sunday, it is in week 52 or 53 of the previous year (there is no week 00). 28 December is always in the last week of its year.

The week number can be described by counting the Thursdays: week 12 contains the 12th Thursday of the year.
...

Author

Commented:
Hi Thommy,

That was my point of reference too.  I was trying to give the user the ability to select different methods of obtaining the week number.


Cheers!

Do more with

Expert Office
Submit tech questions to Ask the Experts™ at any time to receive solutions, advice, and new ideas from leading industry professionals.

Start 7-Day Free Trial