Example Code

Calculating week number according to ISO8601 using LabWindows/CVI

Products and Environment

This section reflects the products and operating system used to create the example.

To download NI software, including the products shown below, visit ni.com/downloads.

    Software

  • Other

Code and Documents

Attachment

1. Overview:

Calculate week of year for current date according to ISO 8601 specifications.

 

2. Description: 

ISO 8601 indicates week 1 of the year as the one that includes the first Thursday. Since there is actually no CVI native function that calculates week number according to this specification I adapted for CVI the algorithm published by Rick McCarty. The function will return the wek number of the year.

 

3. Requirements

  • LabWindows/CVI 2012 (or compatible)

4. Steps to Implement or Execute Code

  1. Download zip file and extract
  2. Incorperate method into your own native code
  3. Run your program

5. Additional Information or References 

 

**This document has been updated to meet the current required format for the NI Code Exchange.**

 



Proud to use LW/CVI from 3.1 on.

My contributions to the Developer Community
________________________________________
If I have helped you, why not giving me a kudos?

Example code from the Example Code Exchange in the NI Community is licensed with the MIT license.

Comments
holly7787
Member
Member
on

i would like to share this function to calculate the ISO week number of a specified date.

this is a necessary function to calculate Current Time Zone Offset.

 

/// HIRET l'offset in secondi della time zone attuale, considerando anche il daylight saving time (DST).
static time_t CurrentTimeZoneOffset(void)
{
    time_t rawtime = time(NULL);
    struct tm ptm = *gmtime(&rawtime);
    ptm.tm_isdst = -1; // Request that mktime() looksup dst in timezone database
    return (time_t)difftime(rawtime, mktime(&ptm));
}

 

and this is the same function to calculate ISO week number but with parameters.

feel free to correct it if you find any problem, but please share the solution!

 

int CalculateISOweekNumWithParameter(unsigned short wYear, unsigned short wMonth, unsigned short wDay)
{
	/*
		Calcolates week number acording to ISO 8601
		Procedure by Rick McCarty, 1999
		Adapted to CVI by R.Bozzolo, 2006

		Requires #include <windows.h>

		Input: None

		Output: Number of week in the year for local current date



	    Algorithm for Converting Gregorian Dates to ISO 8601 Week Date
	                            (Y2K  Compliant)
	                           Rick McCarty, 1999

	                     From: Gregorian Year-Month-Day
	                 To: ISO YearNumber-WeekNumber-Weekday

	ISO 8601 specifies that Week 01 of the year is the week containing
	the first Thursday; Monday is Weekday 1, Sunday is Weekday 7;
	WeekNumber requires two digits (W01, W02, etc.; "W" is optional)

	Algorithm Conventions:
	   "/" = integer division, discard remainder  (5/2 = 2)
	   "%" = modulus, keep only remainder    (5%2 = 1)
	   "&" = concatenation   ("W" & 12 = "W12")
	   "!=" = unequal   (7 != 8  is true)
	   "+=" = add right value to left variable,
	             if F = 3, then (F += 4) yields F = 7
	   "-=" = subtract right value from left variable

	1. Convert input to Y M D
	   Y = Year     (full specification; input 98 = year 0098)
			(Y must be larger than -1)
	   M = Month    (1 through 12)
	   D = Day      (1 through 31)
	2. Find if Y is LeapYear
	   if (Y % 4 = 0  and  Y % 100 != 0) or Y % 400 = 0
	      then
	         Y is LeapYear
	      else
	         Y is not LeapYear
	3. Find if Y-1 is LeapYear
	4. Find the DayOfYearNumber for Y M D
	   Mnth[1] = 0    Mnth[4] = 90    Mnth[7] = 181   Mnth[10] = 273
	   Mnth[2] = 31   Mnth[5] = 120   Mnth[8] = 212   Mnth[11] = 304
	   Mnth[3] = 59   Mnth[6] = 151   Mnth[9] = 243   Mnth[12] = 334
	   DayOfYearNumber = D + Mnth[M]
	   if Y is LeapYear and M > 2
	      then
	         DayOfYearNumber += 1
	5. Find the Jan1Weekday for Y (Monday=1, Sunday=7)
	   YY = (Y-1) % 100
	   C = (Y-1) - YY
	   G = YY + YY/4
	   Jan1Weekday = 1 + (((((C / 100) % 4) x 5) + G) % 7)
	6. Find the Weekday for Y M D
	   H = DayOfYearNumber + (Jan1Weekday - 1)
	   Weekday = 1 + ((H -1) % 7)
	7. Find if Y M D falls in YearNumber Y-1, WeekNumber 52 or 53
	   if DayOfYearNumber <= (8-Jan1Weekday) and Jan1Weekday > 4
	      then
	         YearNumber = Y - 1
	         if Jan1Weekday = 5 or (Jan1Weekday = 6 and Y-1 is LeapYear)
	            then
	               WeekNumber = 53
	            else
	               WeekNumber = 52
	      else
	         YearNumber = Y
	8. Find if Y M D falls in YearNumber Y+1, WeekNumber 1
	   if YearNumber = Y
	      then
	         if Y is LeapYear
	            then
	               I = 366
	               else
	               I = 365
	         if (I - DayOfYearNumber) < (4 - Weekday)
	            then
	               YearNumber = Y + 1
	               WeekNumber = 1
	9. Find if Y M D falls in YearNumber Y, WeekNumber 1 through 53
	   if YearNumber = Y
	      then
	         J = DayOfYearNumber + (7 - Weekday) + (Jan1Weekday -1)
	         WeekNumber = J / 7
	         if Jan1Weekday > 4
	               WeekNumber -= 1
	10. Output ISO Week Date:
	   if WeekNumber < 10
	      then
	         WeekNumber = "0" & WeekNumber  (WeekNumber requires 2 digits)
	   Print: YearNumber & "-" & WeekNumber & "-" & Weekday    (Optional: "-W" & WeekNumber)
	*/

	int YY = {0};
	int C = {0};
	int G = {0};
	int I = {0};
	int J = {0};
	int DayOfYearNumber = {0};
	int Jan1Weekday = {0};
	int Weekday = {0};
	int YearNumber = {0};
	int LeapYear = {0};
	int precLeapYear = {0};
	int WeekNumber = {0};
	int Mnth[] = { 0, 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334 };
	SYSTEMTIME dh = {0};
	
	double DateTime = {0};
	time_t rawtime = {0};
    struct tm ptm = {0};
	
	//1. Convert input to Y M D
	//2. Find if Y is LeapYear
	MakeDateTime (0, 0, 0, wMonth, wDay, wYear, &DateTime);
	rawtime = (time_t)DateTime - CurrentTimeZoneOffset();
	ptm = *localtime(&rawtime);
	dh.wYear = wYear;
	dh.wMonth = wMonth;
	dh.wDayOfWeek = ptm.tm_wday;
	dh.wDay = wDay;
	
	if ((dh.wYear % 4 == 0 && dh.wYear % 100 != 0) || dh.wYear % 400 == 0)
	{
		LeapYear = 1;
	}

	//3. Find if Y-1 is LeapYear
	if (((dh.wYear - 1) % 4 == 0 && (dh.wYear - 1) % 100 != 0) || (dh.wYear % 400 - 1) == 0)
	{
		precLeapYear = 1;
	}

	//4. Find the DayOfYearNumber for Y M D
	DayOfYearNumber = dh.wDay + Mnth[dh.wMonth];
	if (LeapYear && dh.wMonth > 2)
	{
		DayOfYearNumber++;
	}

	//5. Find the Jan1Weekday for Y (Monday=1, Sunday=7)
	YY = (dh.wYear - 1) % 100;
	C = (dh.wYear - 1) - YY;
	G = YY + YY / 4;
	Jan1Weekday = 1 + (((((C / 100) % 4) * 5) + G) % 7);

	//6. Find the Weekday for Y M D
	Weekday = dh.wDayOfWeek;
	if (!Weekday)
	{
		Weekday = 7;    // Gestisce correttamente la domenica (0 in SYSTEMTIME)
	}

	//7. Find if Y M D falls in YearNumber Y-1, WeekNumber 52 or 53
	if (DayOfYearNumber <= (8 - Jan1Weekday) && Jan1Weekday > 4)
	{
		YearNumber = dh.wYear - 1;
		if (Jan1Weekday == 5 || (Jan1Weekday == 6 && precLeapYear))
		{
			WeekNumber = 53;
		}
		else
		{
			WeekNumber = 52;
		}
	}
	else
	{
		YearNumber = dh.wYear;
	}

	//8. Find if Y M D falls in YearNumber Y+1, WeekNumber 1
	if (YearNumber == dh.wYear)
	{
		if (LeapYear)
		{
			I = 366;
		}
		else
		{
			I = 365;
		}
		if ((I - DayOfYearNumber) < (4 - Weekday))
		{
			YearNumber = dh.wYear + 1;
			WeekNumber = 1;
		}
	}

	//9. Find if Y M D falls in YearNumber Y, WeekNumber 1 through 53
	if (YearNumber == dh.wYear)
	{
		J = DayOfYearNumber + (7 - Weekday) + (Jan1Weekday - 1);
		WeekNumber = J / 7;
		if (Jan1Weekday > 4)
		{
			WeekNumber -= 1;
		}
	}

	return WeekNumber;
}

 

Davide Vittorio G. - TLGB S.R.L.
Italian SW Developer