56 lines
1.5 KiB
Plaintext
56 lines
1.5 KiB
Plaintext
|
|
|
||
|
|
### 2. FC_GetWeekNumber (ISO 8601 compliant)
|
||
|
|
|
||
|
|
```iecst
|
||
|
|
FUNCTION "FC_GetWeekNumber" : UINT
|
||
|
|
TITLE = 'Get ISO 8601 Week Number'
|
||
|
|
VERSION : 1.0
|
||
|
|
|
||
|
|
VAR_INPUT
|
||
|
|
stDateTime : DT; // Date & time to evaluate
|
||
|
|
END_VAR
|
||
|
|
|
||
|
|
VAR_TEMP
|
||
|
|
iYear : INT;
|
||
|
|
iMonth : INT;
|
||
|
|
iDay : INT;
|
||
|
|
iJan1_DayOfWeek : INT; // 0=Sunday ... 6=Saturday
|
||
|
|
iDayOfYear : INT;
|
||
|
|
iDoW : INT; // Day of week of input date
|
||
|
|
iWeek : INT;
|
||
|
|
END_VAR
|
||
|
|
|
||
|
|
BEGIN
|
||
|
|
|
||
|
|
// Extract components
|
||
|
|
iYear := DT_TO_DATE(stDateTime).YEAR;
|
||
|
|
iMonth := DT_TO_DATE(stDateTime).MONTH;
|
||
|
|
iDay := DT_TO_DATE(stDateTime).DAY;
|
||
|
|
|
||
|
|
// Day of week (Siemens: 1=Monday ... 7=Sunday)
|
||
|
|
iDoW := WEEKDAY(DT_TO_DATE(stDateTime)); // 1..7
|
||
|
|
|
||
|
|
// Approximate day of year
|
||
|
|
iDayOfYear := DAY_OF_YEAR(DT_TO_DATE(stDateTime));
|
||
|
|
|
||
|
|
// Find weekday of Jan 1st of the year
|
||
|
|
iJan1_DayOfWeek := WEEKDAY(DATE(iYear,1,1));
|
||
|
|
|
||
|
|
// ISO 8601: week 1 = week with first Thursday
|
||
|
|
// Algorithm approximation (good enough for most cases)
|
||
|
|
iWeek := (iDayOfYear + (iJan1_DayOfWeek - 1) + 3) / 7; // basic
|
||
|
|
|
||
|
|
// Correction for years where Jan 1..3 belong to previous year
|
||
|
|
IF (iJan1_DayOfWeek >= 5) AND (iDayOfYear <= 3) THEN
|
||
|
|
iWeek := 53; // or 52 depending on year - simplified
|
||
|
|
// Better: call previous year calculation if needed
|
||
|
|
ELSIF (iJan1_DayOfWeek <= 4) AND (iDayOfYear >= 363) THEN
|
||
|
|
// Check if week 53
|
||
|
|
IF (iDoW + (7 - iJan1_DayOfWeek)) > 364 THEN
|
||
|
|
iWeek := 53;
|
||
|
|
END_IF;
|
||
|
|
END_IF;
|
||
|
|
|
||
|
|
"FC_GetWeekNumber" := INT_TO_UINT(iWeek);
|
||
|
|
|
||
|
|
END_FUNCTION
|