To download NI software, including the products shown below, visit ni.com/downloads.
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
4. Steps to Implement or Execute Code
5. Additional Information or References
**This document has been updated to meet the current required format for the NI Code Exchange.**
Example code from the Example Code Exchange in the NI Community is licensed with the MIT license.
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;
}
Hello colleagues,
I tried to integrate it without success in 2017 CVI version.
Can you provide me a small project with this functionality integrated?
Thank you!